jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def cost_funct(self,
                   edge):
        '''
        Computes the line integral per unit pixel length along the posterior curve, or candidate edge, given 
        the image gradient.
        
        We numerically integrate the edge by computing the curvilinear coordinates along the image gradient 
        using euclidean distance and Simpson's rule. This is then normalised by the length of the edge to
        penalise sharp movements.

        INPUTS:
        -------------------
            edge (np.array) : edge indices in xy-space, shape=(N, 2), i.e. 
                new_edge = np.array([[x0, y0],...[xN, yN]])
                
        RETURNS:
        -------------------
            cost (np.float64) : Cost of the edge.
        '''
        # Evaluate edge along interpolated gradient image
        edge = edge[edge[:,0].argsort(), :]
        grad_score = self.grad_interp(edge[:,1], edge[:,0], grid=False)+self.kde_thresh
        #grad_score = self.grad_interp(edge[:,0], edge[:,1])

        # Compute cumulative sum of euclidean distance between pixel indexes of edge.
        # This is the equivalent of computing the curvilinear coordinates of the edge
        pixel_diff = np.cumsum(np.sqrt(np.sum(np.diff(edge, axis=0)**2, axis=1)))

        # Compute integrand of arc length of edge
        pixel_deriv = self.finite_diff(edge[:,1], typ=0, h=1)
        integrand = np.sqrt(1 + pixel_deriv**2)

        # Compute cost = 1 / (line integral / arc length) = arc length / line integral - smaller costs are better 
        line_integral = scipy.integrate.simpson(grad_score[:-1], pixel_diff)
        arc_length = scipy.integrate.simpson(integrand, edge[:-1,0])
                                    
        # Cost is the line integral per unit pixel length
        cost = arc_length / line_integral 
        
        return cost
//  [python]
def exp_plus_flat(x,slope,expamp,flat,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = expamp*np.exp(-slope*xnorm) + flat

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simps(ynorm,x=xnorm)

    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            #ynorm = np.exp(-slope*xnorm)
            ynorm = expamp*np.exp(-slope*xnorm) + flat

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simps(ynorm,x=xnorm)

    #y = np.exp(-slope*x)/normalization
    y = (expamp*np.exp(-slope*x) + flat)/normalization

    #'''
    if efficiency!=None:
        y *= efficiency(x)
    #'''

    return y
//  [python]
def exp_plus_flat(x,slope,expamp,flat,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = expamp*np.exp(-slope*xnorm) + flat

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simpson(ynorm,x=xnorm)

    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            #ynorm = np.exp(-slope*xnorm)
            ynorm = expamp*np.exp(-slope*xnorm) + flat

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simpson(ynorm,x=xnorm)

    #y = np.exp(-slope*x)/normalization
    y = (expamp*np.exp(-slope*x) + flat)/normalization

    #'''
    if efficiency!=None:
        y *= efficiency(x)
    #'''

    return y
//  [python]
def cos(x,frequency,phase,amplitude,offset,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = offset + amplitude*np.cos(frequency*xnorm + phase)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simps(ynorm,x=xnorm)

    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            #ynorm = np.exp(-slope*xnorm)
            ynorm = offset + amplitude*np.cos(frequency*xnorm + phase)

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simps(ynorm,x=xnorm)
            #print "building normalization: ", normalization

    #y = np.exp(-slope*x)/normalization
    y = offset + amplitude*np.cos(frequency*x + phase)

    if efficiency!=None:
        y *= efficiency(x)

    return y/normalization
//  [python]
def cos(x,frequency,phase,amplitude,offset,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = offset + amplitude*np.cos(frequency*xnorm + phase)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simpson(ynorm,x=xnorm)

    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            #ynorm = np.exp(-slope*xnorm)
            ynorm = offset + amplitude*np.cos(frequency*xnorm + phase)

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simpson(ynorm,x=xnorm)
            #print "building normalization: ", normalization

    #y = np.exp(-slope*x)/normalization
    y = offset + amplitude*np.cos(frequency*x + phase)

    if efficiency!=None:
        y *= efficiency(x)

    return y/normalization
//  [python]
def _get_ngtm_mgtm_from_dndm(self):

        # Generates ngtm and mgtm with Murray's formulas
        ngtm = []
        mgtm = []
        for i in range(len(self.tab_z)):
            m = self.tab_M[np.logical_not(np.isnan(self.tab_M))]
            dndm = self.tab_dndm[i][np.logical_not(np.isnan(self.tab_dndm[i]))]
            dndlnm = m * dndm
            if m[-1] < m[0] * 10 ** 18 / m[3]:
                m_upper = np.arange(np.log(m[-1]), np.log(10 ** 18), np.log(m[1]) - np.log(m[0]))
                mf_func = InterpolatedUnivariateSpline(np.log(m), np.log(dndlnm), k=1)
                mf = mf_func(m_upper)

                int_upper_n = simps(np.exp(mf), dx=m_upper[2] - m_upper[1], even='first')
                int_upper_m = simps(np.exp(m_upper + mf), dx=m_upper[2] - m_upper[1], even='first')
            else:
                int_upper_n = 0
                int_upper_m = 0

            ngtm_ = np.concatenate((cumtrapz(dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1)))
            mgtm_ = np.concatenate((cumtrapz(m[::-1] * dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1)))

            ngtm.append(ngtm_ + int_upper_n)
            mgtm.append(mgtm_ + int_upper_m)

        return np.array(ngtm), np.array(mgtm)
//  [python]
def _get_ngtm_mgtm_from_dndm(self):

        # Generates ngtm and mgtm with Murray's formulas
        ngtm = []
        mgtm = []
        for i in range(len(self.tab_z)):
            m = self.tab_M[np.logical_not(np.isnan(self.tab_M))]
            dndm = self.tab_dndm[i][np.logical_not(np.isnan(self.tab_dndm[i]))]
            dndlnm = m * dndm
            if m[-1] < m[0] * 10 ** 18 / m[3]:
                m_upper = np.arange(np.log(m[-1]), np.log(10 ** 18), np.log(m[1]) - np.log(m[0]))
                mf_func = InterpolatedUnivariateSpline(np.log(m), np.log(dndlnm), k=1)
                mf = mf_func(m_upper)

                int_upper_n = simpson(np.exp(mf), dx=m_upper[2] - m_upper[1])
                int_upper_m = simpson(np.exp(m_upper + mf), dx=m_upper[2] - m_upper[1])
            else:
                int_upper_n = 0
                int_upper_m = 0

            ngtm_ = np.concatenate((cumtrapz(dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1)))
            mgtm_ = np.concatenate((cumtrapz(m[::-1] * dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1)))

            ngtm.append(ngtm_ + int_upper_n)
            mgtm.append(mgtm_ + int_upper_m)

        return np.array(ngtm), np.array(mgtm)
//  [python]
def gauss(x,mean,sigma,xlo,xhi,efficiency=None,num_int_points=100):

    gauss_func = stats.norm(loc=mean,scale=sigma)

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = gauss_func.pdf(xnorm)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simps(ynorm,x=xnorm)
    
    y = gauss_func.pdf(x)/normalization

    if efficiency!=None:
        y *= efficiency(x)


    return y
//  [python]
def gauss(x,mean,sigma,xlo,xhi,efficiency=None,num_int_points=100):

    gauss_func = stats.norm(loc=mean,scale=sigma)

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = gauss_func.pdf(xnorm)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simpson(ynorm,x=xnorm)
    
    y = gauss_func.pdf(x)/normalization

    if efficiency!=None:
        y *= efficiency(x)


    return y
//  [python]
def lorentzian(x,mean,sigma,xlo,xhi,efficiency=None,num_int_points=100):

    #lorentzian_func = stats.cauchy(loc=mean,scale=sigma)

    xnorm = np.linspace(xlo,xhi,num_int_points)
    #ynorm = lorentzian_func.pdf(xnorm)
    ynorm = (1.0/np.pi)*sigma/((xnorm-mean)**2 + sigma**2)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simps(ynorm,x=xnorm)
    
    #y = lorentzian_func.pdf(x)/normalization
    y = ((1.0/np.pi)*sigma/((x-mean)**2 + sigma**2))/normalization

    if efficiency!=None:
        y *= efficiency(x)

    return y
//  [python]
def lorentzian(x,mean,sigma,xlo,xhi,efficiency=None,num_int_points=100):

    #lorentzian_func = stats.cauchy(loc=mean,scale=sigma)

    xnorm = np.linspace(xlo,xhi,num_int_points)
    #ynorm = lorentzian_func.pdf(xnorm)
    ynorm = (1.0/np.pi)*sigma/((xnorm-mean)**2 + sigma**2)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simpson(ynorm,x=xnorm)
    
    #y = lorentzian_func.pdf(x)/normalization
    y = ((1.0/np.pi)*sigma/((x-mean)**2 + sigma**2))/normalization

    if efficiency!=None:
        y *= efficiency(x)

    return y
//  [python]
def Ge_gamma_response(x,slope,lowE_slope,rel_scale,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    ############################################################################
    # Sawtooth
    def sawtooth(xpts,k0,k1,n):
        ypts = np.zeros(len(xpts))

        b = [1.1,1.3]
        #b = [1.1,1.1]

        index0 = xpts<b[0]
        index1 = (xpts>=b[0])*(xpts<=b[1])
        index2 = xpts>b[1]

        i0 = np.where(index0==True)[0][-1]
        i1 = np.where(index2==True)[0][0]

        ypts[index2] = np.exp(-k0*xpts[index2])
        ypts[index0] = n*np.exp(-k1*xpts[index0])

        y0 = ypts[i0]; x0 = xpts[i0]
        y1 = ypts[i1]; x1 = xpts[i1]

        slope = (y1-y0)/(x1-x0)
        intercept = y1 - slope*x1

        #print "slope/intercept: ",slope,intercept
        ypts[index1] = intercept + slope*xpts[index1]
        #y = np.exp(-k0*x)

        return ypts

     ############################################
    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = sawtooth(xnorm,slope,lowE_slope,rel_scale)
    #ynorm = np.exp(-slope*xnorm)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simps(ynorm,x=xnorm)

    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            #ynorm = np.exp(-slope*xnorm)
            ynorm = sawtooth(xnorm,slope,lowE_slope,rel_scale)

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simps(ynorm,x=xnorm)

    #y = np.exp(-slope*x)/normalization
    y = sawtooth(x,slope,lowE_slope,rel_scale)/normalization

    #'''
    if efficiency!=None:
        y *= efficiency(x)
    #'''

    return y
//  [python]
def Ge_gamma_response(x,slope,lowE_slope,rel_scale,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    ############################################################################
    # Sawtooth
    def sawtooth(xpts,k0,k1,n):
        ypts = np.zeros(len(xpts))

        b = [1.1,1.3]
        #b = [1.1,1.1]

        index0 = xpts<b[0]
        index1 = (xpts>=b[0])*(xpts<=b[1])
        index2 = xpts>b[1]

        i0 = np.where(index0==True)[0][-1]
        i1 = np.where(index2==True)[0][0]

        ypts[index2] = np.exp(-k0*xpts[index2])
        ypts[index0] = n*np.exp(-k1*xpts[index0])

        y0 = ypts[i0]; x0 = xpts[i0]
        y1 = ypts[i1]; x1 = xpts[i1]

        slope = (y1-y0)/(x1-x0)
        intercept = y1 - slope*x1

        #print "slope/intercept: ",slope,intercept
        ypts[index1] = intercept + slope*xpts[index1]
        #y = np.exp(-k0*x)

        return ypts

     ############################################
    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = sawtooth(xnorm,slope,lowE_slope,rel_scale)
    #ynorm = np.exp(-slope*xnorm)

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simpson(ynorm,x=xnorm)

    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            #ynorm = np.exp(-slope*xnorm)
            ynorm = sawtooth(xnorm,slope,lowE_slope,rel_scale)

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simpson(ynorm,x=xnorm)

    #y = np.exp(-slope*x)/normalization
    y = sawtooth(x,slope,lowE_slope,rel_scale)/normalization

    #'''
    if efficiency!=None:
        y *= efficiency(x)
    #'''

    return y
//  [python]
def compute_normalization(self):
        self.normalization = 1.0
        norm = scipy.integrate.simps(self._prob(self.zs), self.zs)
        self.normalization = norm
//  [python]
def compute_normalization(self):
        self.normalization = 1.0
        norm = scipy.integrate.simpson(self._prob(self.zs), self.zs)
        self.normalization = norm
//  [python]
def nnf(func,normrange=(0,10),data=None,num_int_points=100,verbose=False,subnormranges=None):

    xnorm = np.linspace(normrange[0],normrange[1],num_int_points)

    # Subranges of the normalization.
    normalization = 1.0
    if subnormranges!=None:
        xnormtot = []
        normalization = 0.0
        for sr in subnormranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            ynorm = func.pdf(xnorm)

            normalization += integrate.simps(ynorm,x=xnorm)
            xnormtot += xnorm.tolist()
        xnorm = np.array(xnormtot)
    else:
        normalization = integrate.simps(func.pdf(xnorm),x=xnorm)

    if verbose:
        print("normalization: {0}".format(normalization))

    if data is None:
        return func.pdf(xnorm)/normalization,xnorm
    else:
        return func.pdf(data)/normalization,xnorm
//  [python]
def nnf(func,normrange=(0,10),data=None,num_int_points=100,verbose=False,subnormranges=None):

    xnorm = np.linspace(normrange[0],normrange[1],num_int_points)

    # Subranges of the normalization.
    normalization = 1.0
    if subnormranges!=None:
        xnormtot = []
        normalization = 0.0
        for sr in subnormranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            ynorm = func.pdf(xnorm)

            normalization += integrate.simpson(ynorm,x=xnorm)
            xnormtot += xnorm.tolist()
        xnorm = np.array(xnormtot)
    else:
        normalization = integrate.simpson(func.pdf(xnorm),x=xnorm)

    if verbose:
        print("normalization: {0}".format(normalization))

    if data is None:
        return func.pdf(xnorm)/normalization,xnorm
    else:
        return func.pdf(data)/normalization,xnorm
//  [python]
def lognormal(x,mu,sigma,xlo,xhi,efficiency=None,num_int_points=100):

    # Catch 0's. The ln(0) in the function will barf otherwise.
    if xlo==0:
        xlo = 0.0000000001

    if type(x)==np.ndarray:
        x[x==0] = 0.0000000001
    else:
        if x==0:
            x = 0.0000000001

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = (1.0/(xnorm*sigma*np.sqrt(2*np.pi)))*np.exp(-((np.log(xnorm)-mu)**2)/(2*sigma*sigma))

    #'''
    if efficiency!=None:
        ynorm *= efficiency(xnorm)
    #'''

    normalization = integrate.simps(ynorm,x=xnorm)
    
    y = (1.0/(x*sigma*np.sqrt(2*np.pi)))*np.exp(-((np.log(x)-mu)**2)/(2*sigma*sigma))
    y /= normalization

    if efficiency!=None:
        y *= efficiency(x)

    return y
//  [python]
def lognormal(x,mu,sigma,xlo,xhi,efficiency=None,num_int_points=100):

    # Catch 0's. The ln(0) in the function will barf otherwise.
    if xlo==0:
        xlo = 0.0000000001

    if type(x)==np.ndarray:
        x[x==0] = 0.0000000001
    else:
        if x==0:
            x = 0.0000000001

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = (1.0/(xnorm*sigma*np.sqrt(2*np.pi)))*np.exp(-((np.log(xnorm)-mu)**2)/(2*sigma*sigma))

    #'''
    if efficiency!=None:
        ynorm *= efficiency(xnorm)
    #'''

    normalization = integrate.simpson(ynorm,x=xnorm)
    
    y = (1.0/(x*sigma*np.sqrt(2*np.pi)))*np.exp(-((np.log(x)-mu)**2)/(2*sigma*sigma))
    y /= normalization

    if efficiency!=None:
        y *= efficiency(x)

    return y
//  [python]
def poly(x,constants,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    if type(x)==np.ndarray:
        x[x==0] = 0.0000000001
    else:
        x = np.array([x])
        x[x==0] = 0.0000000001

    npts = len(x)

    poly = np.ones(npts)

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = np.ones(num_int_points)

    for i,c in enumerate(constants):
        poly += c*np.power(x,(i+1))
        ynorm += c*np.power(xnorm,(i+1))

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simps(ynorm,x=xnorm)
    
    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            ynorm = np.ones(num_int_points)

            for i,c in enumerate(constants):
                ynorm += c*np.power(xnorm,(i+1))

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simps(ynorm,x=xnorm)

    #'''
    if efficiency!=None:
        poly *= efficiency(x)

    #'''
    return poly/normalization
//  [python]
def poly(x,constants,xlo,xhi,efficiency=None,num_int_points=100,subranges=None):

    if type(x)==np.ndarray:
        x[x==0] = 0.0000000001
    else:
        x = np.array([x])
        x[x==0] = 0.0000000001

    npts = len(x)

    poly = np.ones(npts)

    xnorm = np.linspace(xlo,xhi,num_int_points)
    ynorm = np.ones(num_int_points)

    for i,c in enumerate(constants):
        poly += c*np.power(x,(i+1))
        ynorm += c*np.power(xnorm,(i+1))

    if efficiency!=None:
        ynorm *= efficiency(xnorm)

    normalization = integrate.simpson(ynorm,x=xnorm)
    
    # Subranges of the normalization.
    if subranges!=None:
        normalization = 0.0
        for sr in subranges:
            xnorm = np.linspace(sr[0],sr[1],num_int_points)
            ynorm = np.ones(num_int_points)

            for i,c in enumerate(constants):
                ynorm += c*np.power(xnorm,(i+1))

            if efficiency!=None:
                ynorm *= efficiency(xnorm)

            normalization += integrate.simpson(ynorm,x=xnorm)

    #'''
    if efficiency!=None:
        poly *= efficiency(x)

    #'''
    return poly/normalization
//  [python]
def nth_moment(P, x, n, c, normalize=True):
  """
  For a probability density function P(x) defined on x, calculate the n'th
  moment about c.
  This method uses scipy.integrate.simps(), which works best if P is
  moderately well-sampled, I think.
  If keyword 'normalize' is not set to False, P is first normalized.

  Examples:
    Define a PDF:
    >>> x      = np.linspace(-2,10,120)
    >>> xi,w,a = 0,2,6                               #Location, width, asymmetry
    >>> P      = test_add_asym.skewGauss(x,xi,w,a)   #Define PDF
    >>> mu     = test_add_asym.nth_moment(P,x,1,0)   #1st moment about 0 (mean)
    >>> var    = test_add_asym.nth_moment(P,x,2,mu)  #2nd moment about the mean (variance)
    >>> sig    = np.sqrt(var)                        #Standard deviation
    >>> skew   = test_add_asym.nth_moment(P,x,3,mu)/sig**3 #3rd about mean (skewness)
  """
  if normalize: P = P / simps(P,x)
  return simps((x-c)**n * P, x)
//  [python]
def nth_moment(P, x, n, c, normalize=True):
  """
  For a probability density function P(x) defined on x, calculate the n'th
  moment about c.
  This method uses scipy.integrate.simps(), which works best if P is
  moderately well-sampled, I think.
  If keyword 'normalize' is not set to False, P is first normalized.

  Examples:
    Define a PDF:
    >>> x      = np.linspace(-2,10,120)
    >>> xi,w,a = 0,2,6                               #Location, width, asymmetry
    >>> P      = test_add_asym.skewGauss(x,xi,w,a)   #Define PDF
    >>> mu     = test_add_asym.nth_moment(P,x,1,0)   #1st moment about 0 (mean)
    >>> var    = test_add_asym.nth_moment(P,x,2,mu)  #2nd moment about the mean (variance)
    >>> sig    = np.sqrt(var)                        #Standard deviation
    >>> skew   = test_add_asym.nth_moment(P,x,3,mu)/sig**3 #3rd about mean (skewness)
  """
  if normalize: P = P / simpson(P,x)
  return simpson((x-c)**n * P, x)
//  [python]
def get_coordination_number(r, rdf, cutoff, density):
    """
    return coordination number
    x, rdf: arrays of same size
    cutoff: float, in Angstrom
    density: float, number density of the entire system (counting every species) in Angstrom^-3
    """
    mask = (r > 0) & (r < cutoff)
    r = r[mask]
    rdf = rdf[mask]
    integral = scipy.integrate.simps(rdf * (r**2), r)
    return 4 * np.pi * density * integral
//  [python]
def get_coordination_number(r, rdf, cutoff, density):
    """
    return coordination number
    x, rdf: arrays of same size
    cutoff: float, in Angstrom
    density: float, number density of the entire system (counting every species) in Angstrom^-3
    """
    mask = (r > 0) & (r < cutoff)
    r = r[mask]
    rdf = rdf[mask]
    integral = scipy.integrate.simpson(rdf * (r**2), r)
    return 4 * np.pi * density * integral
//  [python]
def f(phi_v, phi_u, a=0.0, b=1.0, n=1000, re_im=False):
    # int_a^b exp(i * (phi_v * s + phi_u * s^2)) ds
    s = np.linspace(a, b, n)
    phis_cos = np.cos(psi(phi_v, phi_u, s))
    phis_sin = np.sin(psi(phi_v, phi_u, s))
    re = scipy.integrate.simps(y=phis_cos, x=s)
    im = scipy.integrate.simps(y=phis_sin, x=s)
    if not re_im:
        angle = np.arctan2(im, re)
        absolute = np.sqrt((re ** 2.0) + (im ** 2.0))
        return absolute, angle
    else:
        return re, im
//  [python]
def f(phi_v, phi_u, a=0.0, b=1.0, n=1000, re_im=False):
    # int_a^b exp(i * (phi_v * s + phi_u * s^2)) ds
    s = np.linspace(a, b, n)
    phis_cos = np.cos(psi(phi_v, phi_u, s))
    phis_sin = np.sin(psi(phi_v, phi_u, s))
    re = scipy.integrate.simpson(y=phis_cos, x=s)
    im = scipy.integrate.simpson(y=phis_sin, x=s)
    if not re_im:
        angle = np.arctan2(im, re)
        absolute = np.sqrt((re ** 2.0) + (im ** 2.0))
        return absolute, angle
    else:
        return re, im
//  [python]
def skewness(P, x, normalize=True, Thiele=False):
  """
  For a probability density function P(x) defined on x, calculate the
  skewness, defined by the third moments about the mean.
  If the mean is already at hand, it's faster to use nth_moment().
  If keyword 'normalize' is not set to False, P is first normalized.
  If keyword 'Thiele' is set to True, calculate instead the unnormalized skew,
  which is th third semi-invariant cumulant (Thiele 1889).

  Examples:
    Define a PDF:
    >>> x      = np.linspace(-2,10,120)
    >>> xi,w,a = 0,2,6                             #Location, width, asymmetry
    >>> P      = test_add_asym.skewGauss(x,xi,w,a) #Define PDF
    >>> S      = test_add_asym.skewness(P,x)       #Skewness
  """

  if normalize: P = P / simps(P,x)              #Normalize here rather than at
                                                #every call to nth_moment()
  mu = nth_moment(P,x,1,0,normalize=False)      #Mean

  if not Thiele:
    sig = sqrt(nth_moment(P,x,2,mu,normalize=False)) #Standard deviation
    S   = nth_moment(P,x,3,mu,normalize=False) / sig**3
  else:
    mu_x3 = nth_moment(P,x**3,1,0,normalize=False) #Mean of x cubed
    mu_x2 = nth_moment(P,x**2,1,0,normalize=False) #Mean of x squared
    S     = mu_x3 - 3*mu*mu_x2 + 2*mu**3           #Unnomalized skew

  return S
//  [python]
def skewness(P, x, normalize=True, Thiele=False):
  """
  For a probability density function P(x) defined on x, calculate the
  skewness, defined by the third moments about the mean.
  If the mean is already at hand, it's faster to use nth_moment().
  If keyword 'normalize' is not set to False, P is first normalized.
  If keyword 'Thiele' is set to True, calculate instead the unnormalized skew,
  which is th third semi-invariant cumulant (Thiele 1889).

  Examples:
    Define a PDF:
    >>> x      = np.linspace(-2,10,120)
    >>> xi,w,a = 0,2,6                             #Location, width, asymmetry
    >>> P      = test_add_asym.skewGauss(x,xi,w,a) #Define PDF
    >>> S      = test_add_asym.skewness(P,x)       #Skewness
  """

  if normalize: P = P / simpson(P,x)              #Normalize here rather than at
                                                #every call to nth_moment()
  mu = nth_moment(P,x,1,0,normalize=False)      #Mean

  if not Thiele:
    sig = sqrt(nth_moment(P,x,2,mu,normalize=False)) #Standard deviation
    S   = nth_moment(P,x,3,mu,normalize=False) / sig**3
  else:
    mu_x3 = nth_moment(P,x**3,1,0,normalize=False) #Mean of x cubed
    mu_x2 = nth_moment(P,x**2,1,0,normalize=False) #Mean of x squared
    S     = mu_x3 - 3*mu*mu_x2 + 2*mu**3           #Unnomalized skew

  return S
//  [python]
def integrate(self, age):

        # calculate range to integrate over
        lower_bound = age - self.maxage
        upper_bound = age - self.minage

        # if upper_bound is negative then this is a later region and we are working on early ages
        # If so, return zeros
        if upper_bound < 0: return (np.zeros(self.ls.size), 0)

        # find things in the age range (include a little extra to account for rounding errors)
        inds = np.where((self.ages >= lower_bound - age * 1e-5) & (
            self.ages <= upper_bound + age * 1e-5))[0]

        # simpsons rule is based on intervals, so include the SED one age lower if it exists
        # otherwise one interval will be missed at every boundary
        if inds[0] > 0 and np.abs(self.ages[inds[0]] -
                                  lower_bound) > 1e-5 * age:
            inds = np.append(inds[0] - 1, inds)

        weights = self.sfh_func(age - self.ages[inds])

        # if weights are all zero then there is no star formation in this region and therefore no need to integrate
        if max(weights) <= 0:
            return (np.zeros(self.ls.size), 0)

        if self.has_dust:
            # integrate weights*sed*dust
            seds = integrate.simps(weights * self.seds[:, inds] *
                                   self.dust_func(self.ages[inds], self.ls),
                                   x=self.ages[inds],
                                   even='avg')
        else:
            # integrate weights*sed
            seds = integrate.simps(weights * self.seds[:, inds],
                                   x=self.ages[inds],
                                   even='avg')

        # integrate weights*mass
        mass = integrate.simps(weights * self.masses[inds],
                               x=self.ages[inds],
                               even='avg') if self.has_masses else 0

        return (seds, mass)
//  [python]
def integrate(self, age):

        # calculate range to integrate over
        lower_bound = age - self.maxage
        upper_bound = age - self.minage

        # if upper_bound is negative then this is a later region and we are working on early ages
        # If so, return zeros
        if upper_bound < 0: return (np.zeros(self.ls.size), 0)

        # find things in the age range (include a little extra to account for rounding errors)
        inds = np.where((self.ages >= lower_bound - age * 1e-5) & (
            self.ages <= upper_bound + age * 1e-5))[0]

        # simpsons rule is based on intervals, so include the SED one age lower if it exists
        # otherwise one interval will be missed at every boundary
        if inds[0] > 0 and np.abs(self.ages[inds[0]] -
                                  lower_bound) > 1e-5 * age:
            inds = np.append(inds[0] - 1, inds)

        weights = self.sfh_func(age - self.ages[inds])

        # if weights are all zero then there is no star formation in this region and therefore no need to integrate
        if max(weights) <= 0:
            return (np.zeros(self.ls.size), 0)

        if self.has_dust:
            # integrate weights*sed*dust
            seds = integrate.simpson(weights * self.seds[:, inds] *
                                   self.dust_func(self.ages[inds], self.ls),
                                   x=self.ages[inds])
        else:
            # integrate weights*sed
            seds = integrate.simpson(weights * self.seds[:, inds],
                                   x=self.ages[inds])

        # integrate weights*mass
        mass = integrate.simpson(weights * self.masses[inds],
                               x=self.ages[inds]) if self.has_masses else 0

        return (seds, mass)
//  [python]
def fourier_t2w(v_t,tgrd,wgrd,method):

    methods = ['linear','quadratic','cubic','simpson']
    assert (method in methods), '@fourier_t2w. This method does not exist'

    xj = 1.0j
    Nt = len(v_t)-1
    dt = tgrd[1]-tgrd[0]

    v_w = np.zeros(len(wgrd),dtype='complex')

    if method == 'linear':
        v_w = linear_fourier_t2w(v_t,tgrd,wgrd)

    elif method == 'quadratic' or method == 'cubic':

        f_t = interpolate.interp1d(tgrd,v_t, kind=method, bounds_error=False,fill_value=0.0)

        for iw in range(len(wgrd)):
            def f_t_exp_iwt(t):
                return f_t(t)*np.exp(xj*wgrd[iw]*t)

            v_w[iw],error = complex_quad(f_t_exp_iwt,tgrd[0],tgrd[-1])

    elif method == 'simpson':
        for iw in range(len(wgrd)):
            f_re = np.cos(wgrd[iw]*tgrd[:])*v_t[:]
            f_im = np.sin(wgrd[iw]*tgrd[:])*v_t[:]
            v_w_re = simps(f_re,dx=dt)
            v_w_im = simps(f_im,dx=dt)
            v_w[iw] = v_w_re + xj*v_w_im

    return v_w
//  [python]
def fourier_t2w(v_t,tgrd,wgrd,method):

    methods = ['linear','quadratic','cubic','simpson']
    assert (method in methods), '@fourier_t2w. This method does not exist'

    xj = 1.0j
    Nt = len(v_t)-1
    dt = tgrd[1]-tgrd[0]

    v_w = np.zeros(len(wgrd),dtype='complex')

    if method == 'linear':
        v_w = linear_fourier_t2w(v_t,tgrd,wgrd)

    elif method == 'quadratic' or method == 'cubic':

        f_t = interpolate.interp1d(tgrd,v_t, kind=method, bounds_error=False,fill_value=0.0)

        for iw in range(len(wgrd)):
            def f_t_exp_iwt(t):
                return f_t(t)*np.exp(xj*wgrd[iw]*t)

            v_w[iw],error = complex_quad(f_t_exp_iwt,tgrd[0],tgrd[-1])

    elif method == 'simpson':
        for iw in range(len(wgrd)):
            f_re = np.cos(wgrd[iw]*tgrd[:])*v_t[:]
            f_im = np.sin(wgrd[iw]*tgrd[:])*v_t[:]
            v_w_re = simpson(f_re,dx=dt)
            v_w_im = simpson(f_im,dx=dt)
            v_w[iw] = v_w_re + xj*v_w_im

    return v_w
//  [python]
def fourier_t2w(v_t,tgrd,wgrd,method):
    
    methods = ['linear','quadratic','cubic','simpson']
    assert (method in methods), '@fourier_t2w. This method does not exist'
    
    xj = 1.0j
    Nt = len(v_t)-1
    dt = tgrd[1]-tgrd[0]
    
    v_w = np.zeros(len(wgrd),dtype='complex')

    if method == 'linear':
        v_w = linear_fourier_t2w(v_t,tgrd,wgrd)

    elif method == 'quadratic' or method == 'cubic':
 
        f_t = interpolate.interp1d(tgrd,v_t, kind=method, bounds_error=False,fill_value=0.0)

        for iw in range(len(wgrd)):
            def f_t_exp_iwt(t):
                return f_t(t)*np.exp(xj*wgrd[iw]*t)

            v_w[iw],error = complex_quad(f_t_exp_iwt,tgrd[0],tgrd[-1])
    
    elif method == 'simpson':
        for iw in range(len(wgrd)):
            f_re = np.cos(wgrd[iw]*tgrd[:])*v_t[:]
            f_im = np.sin(wgrd[iw]*tgrd[:])*v_t[:]
            v_w_re = simps(f_re,dx=dt)
            v_w_im = simps(f_im,dx=dt)
            v_w[iw] = v_w_re + xj*v_w_im
                
    return v_w
//  [python]
def fourier_t2w(v_t,tgrd,wgrd,method):
    
    methods = ['linear','quadratic','cubic','simpson']
    assert (method in methods), '@fourier_t2w. This method does not exist'
    
    xj = 1.0j
    Nt = len(v_t)-1
    dt = tgrd[1]-tgrd[0]
    
    v_w = np.zeros(len(wgrd),dtype='complex')

    if method == 'linear':
        v_w = linear_fourier_t2w(v_t,tgrd,wgrd)

    elif method == 'quadratic' or method == 'cubic':
 
        f_t = interpolate.interp1d(tgrd,v_t, kind=method, bounds_error=False,fill_value=0.0)

        for iw in range(len(wgrd)):
            def f_t_exp_iwt(t):
                return f_t(t)*np.exp(xj*wgrd[iw]*t)

            v_w[iw],error = complex_quad(f_t_exp_iwt,tgrd[0],tgrd[-1])
    
    elif method == 'simpson':
        for iw in range(len(wgrd)):
            f_re = np.cos(wgrd[iw]*tgrd[:])*v_t[:]
            f_im = np.sin(wgrd[iw]*tgrd[:])*v_t[:]
            v_w_re = simpson(f_re,dx=dt)
            v_w_im = simpson(f_im,dx=dt)
            v_w[iw] = v_w_re + xj*v_w_im
                
    return v_w
//  [python]
def PsiHat(self, N, absorber, donor=None, x=None, t=None):
        """
        Equation 2.21 in the manual.
        """

        if self.pf['tables_discrete_gen']:
            raise NotImplemented('help')
        else:

            Ei = self.E_th[absorber]

            # Otherwise, continuous spectrum
            if self.pf['photon_conserving']:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ei, channel='heat') * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0])
            else:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ei, channel='heat') * \
                    PhotoIonizationCrossSection(E, species) * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) \
                    / self.E_th[absorber]

            # Integrate over energies in lookup table
            c = self.E >= max(Ei, self.src.Emin)
            c &= self.E <= self.src.Emax
            samples = np.array([integrand(E) for E in self.E[c]])[..., 0]

            integral = simps(samples, self.E[c])

        if not self.pf['photon_conserving']:
            integral *= self.E_th[absorber]

        return integral
//  [python]
def PsiHat(self, N, absorber, donor=None, x=None, t=None):
        """
        Equation 2.21 in the manual.
        """

        if self.pf['tables_discrete_gen']:
            raise NotImplemented('help')
        else:

            Ei = self.E_th[absorber]

            # Otherwise, continuous spectrum
            if self.pf['photon_conserving']:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ei, channel='heat') * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0])
            else:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ei, channel='heat') * \
                    PhotoIonizationCrossSection(E, species) * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) \
                    / self.E_th[absorber]

            # Integrate over energies in lookup table
            c = self.E >= max(Ei, self.src.Emin)
            c &= self.E <= self.src.Emax
            samples = np.array([integrand(E) for E in self.E[c]])[..., 0]

            integral = simpson(samples, self.E[c])

        if not self.pf['photon_conserving']:
            integral *= self.E_th[absorber]

        return integral
//  [python]
def PhiWiggle(self, N, absorber, donor, x=None, t=None):
        """
        Equation 2.18 in the manual.
        """

        if self.pf['tables_discrete_gen']:
            raise NotImplemented('help')
        else:

            Ej = self.E_th[donor]

            # Otherwise, continuous spectrum
            if self.pf['photon_conserving']:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ej, channel=absorber) * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) / E

            #else:
            #    integrand = lambda E: 1e10 * \
            #        self.esec.DepositionFraction(E, xHII, channel = species + 1) * \
            #        PhotoIonizationCrossSection(E, species) * \
            #        self.src.Spectrum(E, t = t) * \
            #        np.exp(-self.SpecificOpticalDepth(E, ncol)[0]) / E \
            #        / self.E_th[absorber]

            # Integrate over energies in lookup table
            c = self.E >= max(Ej, self.src.Emin)
            c &= self.E <= self.src.Emax
            samples = np.array([integrand(E) for E in self.E[c]])[..., 0]

            integral = simps(samples, self.E[c]) / erg_per_ev

        if not self.pf['photon_conserving']:
            integral *= self.E_th[absorber]

        return integral
//  [python]
def PhiWiggle(self, N, absorber, donor, x=None, t=None):
        """
        Equation 2.18 in the manual.
        """

        if self.pf['tables_discrete_gen']:
            raise NotImplemented('help')
        else:

            Ej = self.E_th[donor]

            # Otherwise, continuous spectrum
            if self.pf['photon_conserving']:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ej, channel=absorber) * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) / E

            #else:
            #    integrand = lambda E: 1e10 * \
            #        self.esec.DepositionFraction(E, xHII, channel = species + 1) * \
            #        PhotoIonizationCrossSection(E, species) * \
            #        self.src.Spectrum(E, t = t) * \
            #        np.exp(-self.SpecificOpticalDepth(E, ncol)[0]) / E \
            #        / self.E_th[absorber]

            # Integrate over energies in lookup table
            c = self.E >= max(Ej, self.src.Emin)
            c &= self.E <= self.src.Emax
            samples = np.array([integrand(E) for E in self.E[c]])[..., 0]

            integral = simpson(samples, self.E[c]) / erg_per_ev

        if not self.pf['photon_conserving']:
            integral *= self.E_th[absorber]

        return integral
//  [python]
def integrate(integrand, mn, mx, dx, inttype="trapz"):
    if inttype is "simp":
        from scipy.integrate import simps
        return np.array([0] + [simps(integrand[mn:n], dx=dx, even="first") 
                       for n in range(mn+1,mx)])
    elif inttype is "trapz":
        return np.array([np.trapz(integrand[mn:n], dx=dx) 
                       for n in range(mn,mx)])
    else:
        raise IOError("inttype should be simp or trapz")
//  [python]
def integrate(integrand, mn, mx, dx, inttype="trapz"):
    if inttype is "simp":
        from scipy.integrate import simpson
        return np.array([0] + [simpson(integrand[mn:n], dx=dx, even="first") 
                       for n in range(mn+1,mx)])
    elif inttype is "trapz":
        return np.array([np.trapz(integrand[mn:n], dx=dx) 
                       for n in range(mn,mx)])
    else:
        raise IOError("inttype should be simp or trapz")
//  [python]
def PhiHat(self, N, absorber, donor=None, x=None, t=None, ind=None):
        """
        Equation 2.20 in the manual.
        """

        Ei = self.E_th[absorber]

        if self.pf['tables_discrete_gen']:
            if self.pf['photon_conserving']:
                integrand = self.fheat * self.I_E \
                    * np.exp(-self.tau_E_N[absorber][:,ind])
            else:
                integrand = self.fheat * self.sigma_E * self.I_E \
                    * np.exp(-self.tau_E_N[absorber][:,ind]) / Ei

        else:

            # Otherwise, continuous spectrum
            if self.pf['photon_conserving']:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x,E=E-Ei, channel='heat') * \
                    self.src.Spectrum(E, t=t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) / E
            else:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ei, channel='heat') * \
                    PhotoIonizationCrossSection(E, absorber) * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) / E \
                    / self.E_th[absorber]

            # Integrate over energies in lookup table
            c = self.E >= max(Ei, self.src.Emin)
            c &= self.E <= self.src.Emax
            samples = np.array([integrand(E) for E in self.E[c]])[..., 0]

            integral = simps(samples, self.E[c]) / erg_per_ev

        if not self.pf['photon_conserving']:
            integral *= self.E_th[absorber]

        return integral
//  [python]
def PhiHat(self, N, absorber, donor=None, x=None, t=None, ind=None):
        """
        Equation 2.20 in the manual.
        """

        Ei = self.E_th[absorber]

        if self.pf['tables_discrete_gen']:
            if self.pf['photon_conserving']:
                integrand = self.fheat * self.I_E \
                    * np.exp(-self.tau_E_N[absorber][:,ind])
            else:
                integrand = self.fheat * self.sigma_E * self.I_E \
                    * np.exp(-self.tau_E_N[absorber][:,ind]) / Ei

        else:

            # Otherwise, continuous spectrum
            if self.pf['photon_conserving']:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x,E=E-Ei, channel='heat') * \
                    self.src.Spectrum(E, t=t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) / E
            else:
                integrand = lambda E: \
                    self.esec.DepositionFraction(x, E=E-Ei, channel='heat') * \
                    PhotoIonizationCrossSection(E, absorber) * \
                    self.src.Spectrum(E, t = t) * \
                    np.exp(-self.SpecificOpticalDepth(E, N)[0]) / E \
                    / self.E_th[absorber]

            # Integrate over energies in lookup table
            c = self.E >= max(Ei, self.src.Emin)
            c &= self.E <= self.src.Emax
            samples = np.array([integrand(E) for E in self.E[c]])[..., 0]

            integral = sp.integrate.simpson(samples, self.E[c]) / erg_per_ev

        if not self.pf['photon_conserving']:
            integral *= self.E_th[absorber]

        return integral
//  [python]
def BayesCost(x, p, xest, rho, M, W=[], eps=1e-8):
    """
    Calculation of the average Bayesian cost with a quadratic cost function.

    Parameters
    ----------
    > **x:** `list`
        -- The regimes of the parameters for the integral.

    > **p:** `multidimensional array`
        -- The prior distribution.
        
    > **xest:** `list`
        -- The estimators.

    > **rho:** `multidimensional list`
        -- Parameterized density matrix.

    > **M:** `array`
        -- A set of POVM.
    
    > **W:** `array`
        -- Weight matrix.

    > **eps:** `float`
        -- Machine epsilon.

    Returns
    ----------
    **The average Bayesian cost:** `float`
        -- The average Bayesian cost.
    """
    para_num = len(x)
    if para_num == 1:
        # single-parameter scenario
        if M == []:
            M = SIC(len(rho[0]))
        else:
            if type(M) != list:
                raise TypeError("Please make sure M is a list!")
        p_num = len(x[0])
        value = [p[i]*sum([np.trace(np.dot(rho[i], M[mi]))*(x[0][i]-xest[mi][0])**2 for mi in range(len(M))]) for i in range(p_num)]
        C = simps(value, x[0])
        return np.real(C)
    else:
        # multi-parameter scenario
        p_shape = np.shape(p)
        p_ext = extract_ele(p, para_num)
        rho_ext = extract_ele(rho, para_num)

        p_list, rho_list = [], []
        for p_ele, rho_ele in zip(p_ext, rho_ext):
            p_list.append(p_ele)
            rho_list.append(rho_ele)

        x_pro = product(*x)
        x_list = []
        for x_ele in x_pro:
            x_list.append([x_ele[i] for i in range(para_num)])
            
        dim = len(rho_list[0])
        p_num = len(p_list)
        
        if W == []:
            W = np.identity(para_num)
            
        if M == []:
            M = SIC(dim)
        else:
            if type(M) != list:
                raise TypeError("Please make sure M is a list!")

        value = [0.0 for i in range(p_num)]
        for i in range(p_num):
            x_tp = np.array(x_list[i])
            xCx = 0.0
            for mi in range(len(M)):
                xCx += np.trace(np.dot(rho_list[i], M[mi]))*np.dot((x_tp-xest[mi]).reshape(1, -1), np.dot(W, (x_tp-xest[mi]).reshape(-1, 1)))[0][0]
            value[i] = p_list[i]*xCx
        C = np.array(value).reshape(p_shape)
        for si in reversed(range(para_num)):
            C = simps(C, x[si])
        return np.real(C)
//  [python]
def BayesCost(x, p, xest, rho, M, W=[], eps=1e-8):
    """
    Calculation of the average Bayesian cost with a quadratic cost function.

    Parameters
    ----------
    > **x:** `list`
        -- The regimes of the parameters for the integral.

    > **p:** `multidimensional array`
        -- The prior distribution.
        
    > **xest:** `list`
        -- The estimators.

    > **rho:** `multidimensional list`
        -- Parameterized density matrix.

    > **M:** `array`
        -- A set of POVM.
    
    > **W:** `array`
        -- Weight matrix.

    > **eps:** `float`
        -- Machine epsilon.

    Returns
    ----------
    **The average Bayesian cost:** `float`
        -- The average Bayesian cost.
    """
    para_num = len(x)
    if para_num == 1:
        # single-parameter scenario
        if M == []:
            M = SIC(len(rho[0]))
        else:
            if type(M) != list:
                raise TypeError("Please make sure M is a list!")
        p_num = len(x[0])
        value = [p[i]*sum([np.trace(np.dot(rho[i], M[mi]))*(x[0][i]-xest[mi][0])**2 for mi in range(len(M))]) for i in range(p_num)]
        C = sp.integrate.simpson(value, x[0])
        return np.real(C)
    else:
        # multi-parameter scenario
        p_shape = np.shape(p)
        p_ext = extract_ele(p, para_num)
        rho_ext = extract_ele(rho, para_num)

        p_list, rho_list = [], []
        for p_ele, rho_ele in zip(p_ext, rho_ext):
            p_list.append(p_ele)
            rho_list.append(rho_ele)

        x_pro = product(*x)
        x_list = []
        for x_ele in x_pro:
            x_list.append([x_ele[i] for i in range(para_num)])
            
        dim = len(rho_list[0])
        p_num = len(p_list)
        
        if W == []:
            W = np.identity(para_num)
            
        if M == []:
            M = SIC(dim)
        else:
            if type(M) != list:
                raise TypeError("Please make sure M is a list!")

        value = [0.0 for i in range(p_num)]
        for i in range(p_num):
            x_tp = np.array(x_list[i])
            xCx = 0.0
            for mi in range(len(M)):
                xCx += np.trace(np.dot(rho_list[i], M[mi]))*np.dot((x_tp-xest[mi]).reshape(1, -1), np.dot(W, (x_tp-xest[mi]).reshape(-1, 1)))[0][0]
            value[i] = p_list[i]*xCx
        C = np.array(value).reshape(p_shape)
        for si in reversed(range(para_num)):
            C = sp.integrate.simpson(C, x[si])
        return np.real(C)