Changeset ffca8f2 in sasview for pr_inversion


Ignore:
Timestamp:
May 23, 2008 3:23:05 PM (16 years ago)
Author:
Mathieu Doucet <doucetm@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
a8b6364
Parents:
896abb3
Message:

More docs and a little cleaning up

Location:
pr_inversion
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pr_inversion/__init__.py

    r896abb3 rffca8f2  
    2424# [5] S. Hansen and J. Skov Pedersen, J.Appl. Cryst (1991) 24, 541-548. 
    2525# 
     26## \subsection class Class Diagram: 
     27# The following shows a partial class diagram with the main attributes and methods of the invertor. 
     28# 
     29# \image html architecture.png 
    2630# 
    2731# \section install_sec Installation 
     
    7781# matrix for those coefficients, respectively. 
    7882# 
     83# To get P(r): 
     84# \verbatim 
     85#    r = 10.0 
     86#    pr = invertor.pr(c_out, r) 
     87# \endverbatim 
     88# Alternatively, one can get P(r) with the error on P(r): 
     89# \verbatim 
     90#    r = 10.0 
     91#    pr, dpr = invertor.pr_err(c_out, c_cov, r) 
     92# \endverbatim 
     93# 
     94# To get the output I(q) from the set of coefficients found: 
     95# \verbatim 
     96#    q = 0.001 
     97#    iq = invertor.iq(c_out, q) 
     98# \endverbatim 
     99# 
    79100# Examples are available as unit tests under sans.pr_inversion.test. 
    80101# 
  • pr_inversion/invertor.py

    r896abb3 rffca8f2  
    3535        Invertor class to perform P(r) inversion 
    3636         
    37         TODO: explain the maths 
    38          
     37        The problem is solved by posing the problem as  Ax = b, 
     38        where x is the set of coefficients we are looking for. 
     39         
     40        Npts is the number of points. 
     41         
     42        In the following i refers to the ith base function coefficient. 
     43        The matrix has its entries j in its first Npts rows set to 
     44            A[i][j] = (Fourier transformed base function for point j)  
     45             
     46        We them choose a number of r-points, n_r, to evaluate the second 
     47        derivative of P(r) at. This is used as our regularization term. 
     48        For a vector r of length n_r, the following n_r rows are set to 
     49            A[i+Npts][j] = (2nd derivative of P(r), d**2(P(r))/d(r)**2, evaluated at r[j]) 
     50             
     51        The vector b has its first Npts entries set to 
     52            b[j] = (I(q) observed for point j) 
     53             
     54        The following n_r entries are set to zero. 
     55         
     56        The result is found by using scipy.linalg.basic.lstsq to invert 
     57        the matrix and find the coefficients x. 
    3958         
    4059        Methods inherited from Cinvertor: 
     
    144163        return invertor 
    145164     
    146     def invert(self, nfunc=5): 
     165    def invert(self, nfunc=10, nr=20): 
    147166        """ 
    148167            Perform inversion to P(r) 
    149         """ 
     168             
     169            The problem is solved by posing the problem as  Ax = b, 
     170            where x is the set of coefficients we are looking for. 
     171             
     172            Npts is the number of points. 
     173             
     174            In the following i refers to the ith base function coefficient. 
     175            The matrix has its entries j in its first Npts rows set to 
     176                A[i][j] = (Fourier transformed base function for point j)  
     177                 
     178            We them choose a number of r-points, n_r, to evaluate the second 
     179            derivative of P(r) at. This is used as our regularization term. 
     180            For a vector r of length n_r, the following n_r rows are set to 
     181                A[i+Npts][j] = (2nd derivative of P(r), d**2(P(r))/d(r)**2, evaluated at r[j]) 
     182                 
     183            The vector b has its first Npts entries set to 
     184                b[j] = (I(q) observed for point j) 
     185                 
     186            The following n_r entries are set to zero. 
     187             
     188            The result is found by using scipy.linalg.basic.lstsq to invert 
     189            the matrix and find the coefficients x. 
     190             
     191            @param nfunc: number of base functions to use. 
     192            @param nr: number of r points to evaluate the 2nd derivative at for the reg. term. 
     193            @return: c_out, c_cov - the coefficients with covariance matrix  
     194        """ 
     195        #TODO: call the pyhton implementation for now. In the future, translate this to C. 
     196        return self.lstsq(nfunc, nr=nr) 
     197     
     198    def invert_optimize(self, nfunc=10, nr=20): 
     199        """ 
     200            Slower version of the P(r) inversion that uses scipy.optimize.leastsq. 
     201             
     202            This probably produce more reliable results, but is much slower. 
     203            The minimization function is set to sum_i[ (I_obs(q_i) - I_theo(q_i))/err**2 ] + alpha * reg_term, 
     204            where the reg_term is given by Svergun: it is the integral of the square of the first derivative 
     205            of P(r), d(P(r))/dr, integrated over the full range of r. 
     206             
     207            @param nfunc: number of base functions to use. 
     208            @param nr: number of r points to evaluate the 2nd derivative at for the reg. term. 
     209            @return: c_out, c_cov - the coefficients with covariance matrix  
     210        """ 
     211         
    150212        from scipy import optimize 
    151213        import time 
     
    175237    def pr_fit(self, nfunc=5): 
    176238        """ 
    177             Perform inversion to P(r) 
     239            This is a direct fit to a given P(r). It assumes that the y data 
     240            is set to some P(r) distribution that we are trying to reproduce 
     241            with a set of base functions. 
     242             
     243            This method is provided as a test.  
    178244        """ 
    179245        from scipy import optimize 
     
    209275            @param r: r-value to evaluate P(r) at 
    210276            @return: P(r) 
    211              
    212277        """ 
    213278        return self.get_pr_err(c, c_cov, r) 
     
    223288        return True 
    224289        
    225     def lstsq(self, nfunc=5): 
     290    def lstsq(self, nfunc=5, nr=20): 
    226291        #TODO: do this on the C side 
    227292        # 
     
    230295        # ... before passing it to C 
    231296        """ 
    232             TODO: Document this 
     297            The problem is solved by posing the problem as  Ax = b, 
     298            where x is the set of coefficients we are looking for. 
     299             
     300            Npts is the number of points. 
     301             
     302            In the following i refers to the ith base function coefficient. 
     303            The matrix has its entries j in its first Npts rows set to 
     304                A[i][j] = (Fourier transformed base function for point j)  
     305                 
     306            We them choose a number of r-points, n_r, to evaluate the second 
     307            derivative of P(r) at. This is used as our regularization term. 
     308            For a vector r of length n_r, the following n_r rows are set to 
     309                A[i+Npts][j] = (2nd derivative of P(r), d**2(P(r))/d(r)**2, evaluated at r[j]) 
     310                 
     311            The vector b has its first Npts entries set to 
     312                b[j] = (I(q) observed for point j) 
     313                 
     314            The following n_r entries are set to zero. 
     315             
     316            The result is found by using scipy.linalg.basic.lstsq to invert 
     317            the matrix and find the coefficients x. 
     318             
     319            @param nfunc: number of base functions to use. 
     320            @param nr: number of r points to evaluate the 2nd derivative at for the reg. term. 
    233321        """ 
    234322        import math 
     
    239327        # b -- An M x nrhs matrix or M vector. 
    240328        npts = len(self.x) 
    241         nq   = 20 
     329        nq   = nr 
    242330        sqrt_alpha = math.sqrt(self.alpha) 
    243331         
     
    250338                if self._accept_q(self.x[i]): 
    251339                    a[i][j] = self.basefunc_ft(self.d_max, j+1, self.x[i])/self.err[i] 
     340                     
     341            #TODO: refactor this: i_q should really be i_r 
    252342            for i_q in range(nq): 
    253343                r = self.d_max/nq*i_q 
     
    298388        return c, err 
    299389         
    300     def svd(self, nfunc=5): 
    301         import math, time 
    302         # Ac - b = 0 
    303          
    304         A = numpy.zeros([nfunc, nfunc]) 
    305         y = numpy.zeros(nfunc) 
    306          
    307         t_0 = time.time() 
    308         for i in range(nfunc): 
    309             # A 
    310             for j in range(nfunc): 
    311                 A[i][j] = 0.0 
    312                 for k in range(len(self.x)): 
    313                     err = self.err[k] 
    314                     A[i][j] += 1.0/err/err*self.basefunc_ft(self.d_max, j+1, self.x[k]) \ 
    315                             *self.basefunc_ft(self.d_max, i+1, self.x[k]); 
    316                 #print A[i][j] 
    317                 #A[i][j] -= self.alpha*(math.cos(math.pi*(i+j)) - math.cos(math.pi*(i-j))); 
    318                 if i==j: 
    319                     A[i][j] += -1.0*self.alpha 
    320                 elif i-j==1 or i-j==-1: 
    321                     A[i][j] += 1.0*self.alpha 
    322                 #print "   ",A[i][j] 
    323             # y 
    324             y[i] = 0.0 
    325             for k in range(len(self.x)): 
    326                 y[i] = self.y[k]/self.err[k]/self.err[k]*self.basefunc_ft(self.d_max, i+1, self.x[k]) 
    327              
    328         print time.time()-t_0, 'secs' 
    329          
    330         # use numpy.pinv(A) 
    331         #inv_A = numpy.linalg.inv(A) 
    332         #c = y*inv_A 
    333         print y 
    334         c = numpy.linalg.solve(A, y) 
    335          
    336          
    337         print c 
    338          
    339         err = numpy.zeros(len(c)) 
    340         return c, err 
    341          
    342390    def estimate_alpha(self, nfunc): 
    343391        """ 
     
    392440                     
    393441                    peaks = pr.get_peaks(out) 
    394                     print pr.alpha, peaks 
    395442                    if peaks>1: 
    396443                        found = True 
  • pr_inversion/test/utest_invertor.py

    r43c0a8e rffca8f2  
    176176        self.invertor.err = err 
    177177        # Perform inversion 
    178         out, cov = self.invertor.invert(10) 
     178        out, cov = self.invertor.invert_optimize(10) 
    179179        # This is a very specific case 
    180180        # We should make sure it always passes 
     
    404404    def test_qmin(self): 
    405405        self.invertor.q_min = 1.0 
    406         print self.invertor.q_min 
    407406        self.assertEqual(self.invertor.q_min, 1.0) 
    408407         
Note: See TracChangeset for help on using the changeset viewer.