Changeset ef9ed58 in sasview for Invariant


Ignore:
Timestamp:
Nov 30, 2009 7:10:39 PM (14 years ago)
Author:
Gervaise Alina <gervyh@…>
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:
c5607fa
Parents:
2733188
Message:

working on invariant

Location:
Invariant
Files:
2 added
1 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • Invariant/invariant.py

    r2cce133 ref9ed58  
    55 
    66import math  
    7 import numpy.linalg.lstsq 
     7import numpy 
    88 
    99from DataLoader.data_info import Data1D as LoaderData1D 
     10#from DataLoader.data_info import Data1D as LoaderData1D 
    1011from DataLoader.qsmearing import smear_selection 
    1112 
     
    2021INTEGRATION_NSTEPS = 1000 
    2122 
    22 class FitFunctor: 
    23     """ 
    24         compute f(x) 
    25     """ 
    26     def __init__(self,data , function): 
    27         """ 
    28             @param function :the function used for computing residuals 
    29             @param Data: data used for computing residuals 
    30         """ 
    31         self.function = function 
    32         self.data  = data 
    33         x_len = len(self.data.x) -1 
    34         #fitting range  
    35         self.qmin =  self.data[0]     
    36         if self.qmin == 0: 
    37             self.qmin = Q_MINIMUM  
    38      
    39         self.qmax = self.data[x_len] 
    40         #Unsmeared q range 
    41         self._qmin_unsmeared = 0 
    42         self._qmax_unsmeared = self.data[x_len] 
    43          
    44         #bin for smear data 
    45         self._first_unsmeared_bin = 0 
    46         self._last_unsmeared_bin  = x_len 
    47          
    48         # Identify the bin range for the unsmeared and smeared spaces 
    49         self.idx = (self.x>=self.qmin) & (self.x <= self.qmax) 
    50         self.idx_unsmeared = (self.x>=self._qmin_unsmeared) & (self.x <= self._qmax_unsmeared) 
    51    
    52         #get the smear object of data 
    53         self.smearer = smear_selection( self.data ) 
    54         self.func_name = "Residuals" 
    55          
    56     def setFitRange(self): 
    57         """ to set the fit range""" 
    58         self.qmin =  self.data[0]     
    59         if self.qmin== 0: 
    60             self.qmin= MINIMUM  
    61          
    62         x_len= len(self.data.x) -1 
    63         self.qmax= self.data[x_len] 
    64              
    65         # Determine the range needed in unsmeared-Q to cover 
    66         # the smeared Q range 
    67         self._qmin_unsmeared = self.qmin 
    68         self._qmax_unsmeared = self.qmax     
    69          
    70         self._first_unsmeared_bin = 0 
    71         self._last_unsmeared_bin  = len(self.data.x)-1 
    72          
    73         if self.smearer!=None: 
    74             self._first_unsmeared_bin, self._last_unsmeared_bin = self.smearer.get_bin_range(self.qmin, self.qmax) 
    75             self._qmin_unsmeared = self.data.x[self._first_unsmeared_bin] 
    76             self._qmax_unsmeared = self.data.x[self._last_unsmeared_bin] 
    77              
    78         # Identify the bin range for the unsmeared and smeared spaces 
    79         self.idx = (self.data.x>=self.qmin) & (self.data.x <= self.qmax) 
    80         self.idx_unsmeared = (self.data.x>=self._qmin_unsmeared) & (self.data.x <= self._qmax_unsmeared) 
    81    
    82          
    83     def _get_residuals(self, params): 
    84         """ 
    85             Compute residuals 
    86             @return res: numpy array of float of size.self.data.x 
    87         """ 
    88          # Compute theory data f(x) 
    89         fx = numpy.zeros(len(self.data.x)) 
    90         fx[self.idx_unsmeared] = self.funtion(self.data.x[self.idx_unsmeared]) 
    91         
    92         ## Smear theory data 
    93         if self.smearer is not None: 
    94             fx = self.smearer(fx, self._first_unsmeared_bin, self._last_unsmeared_bin) 
    95         
    96         ## Sanity check 
    97         if numpy.size(self.data.dy)!= numpy.size(fx): 
    98             raise RuntimeError, "Residuals: invalid error array %d <> %d" % (numpy.shape(self.data.dy), 
    99                                                                               numpy.size(fx)) 
    100                                                                                
    101         return (self.data.y[self.idx]-fx[self.idx])/self.data.dy[self.idx] 
    102      
    103      
    104     def __call__(self,params): 
    105         """ 
    106             Compute residuals 
    107             @param params: value of parameters to fit 
    108         """ 
    109         return self._get_residuals(params) 
    110      
    111      
    11223def guinier(x, scale=1, radius=0.1): 
    11324    """ 
    11425        Compute a F(x) = scale* e-((radius*x)**2/3). 
    115         @param x: a vector of q values or one q value 
     26        @param x: a vector of q values  
    11627        @param scale: the scale value 
    11728        @param radius: the guinier radius value 
    11829        @return F(x) 
    119     """ 
    120      
     30    """    
     31    value = numpy.array([math.exp(-((radius * i)**2/3)) for i in x ])  
     32    return scale * value 
     33 
    12134def power_law(x, scale=1, power=4): 
    12235    """ 
     
    12538            else power_law 
    12639        The model has three parameters:  
     40        @param x: a vector of q values 
    12741        @param power: power of the function 
    12842        @param scale : scale factor value 
    12943        @param F(x) 
    130     """     
    131  
    132      
     44    """   
     45    value = numpy.array([ math.pow(i, -power) for i in x ])   
     46    return scale * value 
     47 
     48class FitFunctor: 
     49    """ 
     50        compute f(x) 
     51    """ 
     52    def __init__(self,data , function): 
     53        """ 
     54            @param function :the function used for computing residuals 
     55            @param Data: data used for computing residuals 
     56        """ 
     57        self.function = function 
     58        self.data  = data 
     59        x_len = len(self.data.x) -1 
     60        #fitting range  
     61        self.qmin =  self.data.x[0]     
     62        if self.qmin == 0: 
     63            self.qmin = Q_MINIMUM  
     64     
     65        self.qmax = self.data.x[x_len] 
     66        #Unsmeared q range 
     67        self._qmin_unsmeared = 0 
     68        self._qmax_unsmeared = self.data.x[x_len] 
     69         
     70        #bin for smear data 
     71        self._first_unsmeared_bin = 0 
     72        self._last_unsmeared_bin  = x_len 
     73         
     74        # Identify the bin range for the unsmeared and smeared spaces 
     75        self.idx = (self.data.x >= self.qmin) & (self.data.x <= self.qmax) 
     76        self.idx_unsmeared = (self.data.x >= self._qmin_unsmeared) \ 
     77                            & (self.data.x <= self._qmax_unsmeared) 
     78   
     79        #get the smear object of data 
     80        self.smearer = smear_selection( self.data ) 
     81       
     82         
     83    def set_fit_range(self ,qmin=None, qmax=None): 
     84        """ to set the fit range""" 
     85        if qmin is not None: 
     86            self.qmin = qmin 
     87        if qmax is not None: 
     88            self.qmax = qmax 
     89             
     90        # Determine the range needed in unsmeared-Q to cover 
     91        # the smeared Q range 
     92        self._qmin_unsmeared = self.qmin 
     93        self._qmax_unsmeared = self.qmax     
     94         
     95        self._first_unsmeared_bin = 0 
     96        self._last_unsmeared_bin  = len(self.data.x)-1 
     97         
     98        if self.smearer!=None: 
     99            self._first_unsmeared_bin, self._last_unsmeared_bin = self.smearer.get_bin_range(self.qmin, self.qmax) 
     100            self._qmin_unsmeared = self.data.x[self._first_unsmeared_bin] 
     101            self._qmax_unsmeared = self.data.x[self._last_unsmeared_bin] 
     102             
     103        # Identify the bin range for the unsmeared and smeared spaces 
     104        self.idx = (self.data.x >= self.qmin) & (self.data.x <= self.qmax) 
     105        self.idx_unsmeared = (self.data.x >= self._qmin_unsmeared) \ 
     106                                & (self.data.x <= self._qmax_unsmeared) 
     107   
     108    def fit(self): 
     109        """ 
     110           Fit data for y = ax + b  return a and b 
     111            
     112        """ 
     113        fx = self.data.y 
     114        ## Smear theory data 
     115        if self.smearer is not None: 
     116            fx = self.smearer(fx, self._first_unsmeared_bin, 
     117                               self._last_unsmeared_bin)                                                          
     118        A = numpy.vstack([ self.data.x, numpy.ones(len(self.data.x))]).T 
     119 
     120        a, b = numpy.linalg.lstsq(A, fx)[0] 
     121        return a, b 
     122 
    133123class InvariantCalculator(object): 
    134124    """ 
     
    141131        @note: Some computations depends on each others.  
    142132    """ 
     133     
     134     
    143135    def __init__(self, data, background=0, scale=1 ): 
    144136        """ 
     
    168160        self._low_extrapolation_function = guinier 
    169161        self._low_extrapolation_power = 4 
    170          
     162    
    171163        self._high_extrapolation_npts = 4 
    172164        self._high_extrapolation_function = power_law 
    173165        self._high_extrapolation_power = 4 
    174166         
     167         
    175168    def set_extrapolation(self, range, npts=4, function=None, power=4): 
    176169        """ 
    177170            Set the extrapolation parameters for the high or low Q-range. 
    178171            Note that this does not turn extrapolation on or off. 
     172            @param range: a keyword set the type of extrapolation . type string 
     173            @param npts: the numbers of q points of data to consider for extrapolation 
     174            @param function: a keyword to select the function to use for extrapolation. 
     175                of type string. 
     176            @param power: an power to apply power_low function 
     177                 
    179178        """ 
    180179        range = range.lower() 
     
    185184            raise ValueError, "Extrapolation function should be 'guinier' or 'power_law'" 
    186185         
    187         if range=='high': 
     186        if range == 'high': 
    188187            if function != 'power_law': 
    189188                raise ValueError, "Extrapolation only allows a power law at high Q" 
     
    207206            #Process only data that inherited from DataLoader.Data_info.Data1D 
    208207            raise ValueError,"Data must be of type DataLoader.Data1D" 
    209          
    210          
    211     def _fit(self, function, params=[]): 
     208        return self._scale * data - self._background 
     209         
     210    def _fit(self, function, qmin=Q_MINIMUM, qmax=Q_MAXIMUM): 
    212211        """ 
    213212            fit data with function using  
     
    216215            y = data.y 
    217216            out, cov_x = linalg.lstsq(y,fx) 
    218  
    219          
     217            @param qmin: data first q value to consider during the fit 
     218            @param qmax: data last q value to consider during the fit 
    220219            @param function: the function to use during the fit 
    221             @param params: the list of parameters values to use during the fit 
    222              
    223         """ 
    224          
     220            @return a: the scale of the function 
     221            @return b: the other parameter of the function for guinier will be radius 
     222                    for power_law will be the power value 
     223        """ 
     224        if function.__name__ == "guinier": 
     225            fit_x = self._data.x * self._data.x 
     226            qmin = qmin**2 
     227            qmax = qmax**2 
     228            fit_y = [math.log(y) for y in self._data.y] 
     229        elif function.__name__ == "power_law": 
     230            fit_x = [math.log(x) for x in self._data.x] 
     231            qmin = math.log(qmin) 
     232            qmax = math.log(qmax) 
     233            fit_y = [math.log(y) for y in self._data.y] 
     234        else: 
     235            raise ValueError("Unknown function used to fit %s"%function.__name__) 
     236             
     237        fit_data = LoaderData1D(x=fit_x, y=fit_y) 
     238        fit_data.dxl = self._data.dxl 
     239        fit_data.dxw = self._data.dxw    
     240         
     241        functor = FitFunctor(data=fit_data, function= function) 
     242        functor.set_fit_range(qmin=qmin, qmax=qmax) 
     243        a, b = functor.fit() 
     244         
     245        if function.__name__ == "guinier": 
     246            # b is the radius value of the guinier function 
     247            print "b",b 
     248            b = math.sqrt(-3 * b) 
     249        
     250        # a is the scale of the guinier function 
     251        a = math.exp(a) 
     252        return a, math.fabs(b) 
     253     
     254    def _get_qstar(self, data): 
     255        """ 
     256            Compute invariant for data 
     257            @param data: data to use to compute invariant. 
     258               
     259        """ 
     260        if data is None: 
     261            return 0 
     262        if data.is_slit_smeared(): 
     263            return self._get_qstar_smear(data) 
     264        else: 
     265            return self._get_qstar_unsmear(data) 
     266         
     267             
    225268    def get_qstar(self, extrapolation=None): 
    226269        """ 
     
    231274                else: 
    232275                    qstar_0 = self._get_qstar_unsmear() 
    233                      
     276                if extrapolation is None: 
     277                    return qstar_0     
    234278                if extrapolation==low: 
    235279                    return qstar_0 + self._get_qstar_low() 
     
    238282                elif extrapolation==both: 
    239283                    return qstar_0 + self._get_qstar_low() + self._get_qstar_high() 
    240                      
     284            
     285            @param extrapolation: string to apply optional extrapolation     
    241286            @return q_star: invariant of the data within data's q range 
    242         """ 
    243          
    244          
    245     def _get_qstar_unsmear(self): 
     287             
     288            @warning: When using setting data to Data1D , the user is responsible of 
     289            checking that the scale and the background are properly apply to the data 
     290             
     291            @warning: if error occur self._get_qstar_low() or self._get_qstar_low() 
     292            their returned value will be ignored 
     293        """ 
     294        qstar_0 = self._get_qstar(data=self._data) 
     295         
     296        if extrapolation is None: 
     297            self._qstar = qstar_0 
     298            return self._qstar 
     299        # Compute invariant plus invaraint of extrapolated data 
     300        extrapolation = extrapolation.lower()     
     301        if extrapolation == "low": 
     302            self._qstar = qstar_0 + self._get_qstar_low() 
     303            return self._qstar 
     304        elif extrapolation == "high": 
     305            self._qstar = qstar_0 + self._get_qstar_high() 
     306            return self._qstar 
     307        elif extrapolation == "both": 
     308            self._qstar = qstar_0 + self._get_qstar_low() + self._get_qstar_high() 
     309            return self._qstar 
     310      
     311    def _get_qstar_unsmear(self, data): 
    246312        """ 
    247313            Compute invariant for pinhole data. 
     
    255321            dx0 = (x1 - x0)/2 
    256322            dxn = xn - xn-1 
    257  
    258             @return q_star: invariant value for pinhole data. 
    259         """ 
    260          
    261     def _get_qstar_smear(self): 
     323            @param data: the data to use to compute invariant. 
     324            @return q_star: invariant value for pinhole data. q_star > 0 
     325        """ 
     326        if len(data.x) <= 1 or len(data.y) <= 1 or len(data.x)!= len(data.y): 
     327            msg =  "Length x and y must be equal" 
     328            msg += " and greater than 1; got x=%s, y=%s"%(len(data.x), len(data.y)) 
     329            raise ValueError, msg 
     330        else: 
     331            n = len(data.x)- 1 
     332            #compute the first delta q 
     333            dx0 = (data.x[1] - data.x[0])/2 
     334            #compute the last delta q 
     335            dxn = data.x[n] - data.x[n-1] 
     336            sum = 0 
     337            sum += data.x[0] * data.x[0] * data.y[0] * dx0 
     338            sum += data.x[n] * data.x[n] * data.y[n] * dxn 
     339             
     340            if len(data.x) == 2: 
     341                return sum 
     342            else: 
     343                #iterate between for element different from the first and the last 
     344                for i in xrange(1, n-1): 
     345                    dxi = (data.x[i+1] - data.x[i-1])/2 
     346                    sum += data.x[i] * data.x[i] * data.y[i] * dxi 
     347                return sum 
     348             
     349    def _get_qstar_smear(self, data): 
    262350        """ 
    263351            Compute invariant for slit-smeared data. 
     
    273361            @return q_star: invariant value for slit smeared data. 
    274362        """ 
    275          
    276     def _get_qstar_unsmear_uncertainty(self): 
     363        if not data.is_slit_smeared(): 
     364            msg = "_get_qstar_smear need slit smear data " 
     365            msg += "Hint :dxl= %s , dxw= %s"%(str(data.dxl), str(data.dxw)) 
     366            raise ValueError, msg 
     367 
     368        if len(data.x) <= 1 or len(data.y) <= 1 or len(data.x) != len(data.y)\ 
     369              or len(data.x)!= len(data.dxl): 
     370            msg = "x, dxl, and y must be have the same length and greater than 1" 
     371            raise ValueError, msg 
     372        else: 
     373            n = len(data.x)-1 
     374            #compute the first delta 
     375            dx0 = (data.x[1] + data.x[0])/2 
     376            #compute the last delta 
     377            dxn = data.x[n] - data.x[n-1] 
     378            sum = 0 
     379            sum += data.x[0] * data.dxl[0] * data.y[0] * dx0 
     380            sum += data.x[n] * data.dxl[n] * data.y[n] * dxn 
     381             
     382            if len(data.x)==2: 
     383                return sum 
     384            else: 
     385                #iterate between for element different from the first and the last 
     386                for i in xrange(1, n-1): 
     387                    dxi = (data.x[i+1] - data.x[i-1])/2 
     388                    sum += data.x[i] * data.dxl[i] * data.y[i] * dxi 
     389                return sum 
     390         
     391    def _get_qstar_uncertainty(self, data=None): 
     392        """ 
     393            Compute uncertainty of invariant value 
     394            Implementation: 
     395                if data is None: 
     396                    data = self.data 
     397             
     398                if data.slit smear: 
     399                        return self._get_qstar_smear_uncertainty(data) 
     400                    else: 
     401                        return self._get_qstar_unsmear_uncertainty(data) 
     402           
     403            @param: data use to compute the invariant which allow uncertainty 
     404            computation. 
     405            @return: uncertainty 
     406        """ 
     407        if data is None: 
     408            data = self.data 
     409     
     410        if data.is_slit_smeared(): 
     411            return self._get_qstar_smear_uncertainty(data) 
     412        else: 
     413            return self._get_qstar_unsmear_uncertainty(data) 
     414         
     415    def _get_qstar_unsmear_uncertainty(self, data=None): 
    277416        """ 
    278417            Compute invariant uncertainty with with pinhole data. 
     
    285424            dxn = xn - xn-1 
    286425            dyn: error on dy 
    287             @param data: data of type Data1D where the scale is applied 
    288                         and the background is subtracted. 
     426            
     427            @param data: 
    289428            note: if data doesn't contain dy assume dy= math.sqrt(data.y) 
    290429        """ 
     430        if data is None: 
     431            data = self.data 
     432             
     433        if len(data.x) <= 1 or len(data.y) <= 1 or \ 
     434            len(self.data.x) != len(self.data.y): 
     435            msg = "Length of data.x and data.y must be equal" 
     436            msg += " and greater than 1; got x=%s, y=%s"%(len(data.x), 
     437                                                         len(data.y)) 
     438            raise ValueError, msg 
     439        else: 
     440            #Create error for data without dy error 
     441            if (data.dy is None) or (not data.dy): 
     442                dy = math.sqrt(y)  
     443            else: 
     444                dy = data.dy 
     445                 
     446            n = len(data.x) - 1 
     447            #compute the first delta 
     448            dx0 = (data.x[1] - data.x[0])/2 
     449            #compute the last delta 
     450            dxn= data.x[n] - data.x[n-1] 
     451            sum = 0 
     452            sum += (data.x[0] * data.x[0] * dy[0] * dx0)**2 
     453            sum += (data.x[n] * data.x[n] * dy[n] * dxn)**2 
     454            if len(data.x) == 2: 
     455                return math.sqrt(sum) 
     456            else: 
     457                #iterate between for element different from the first and the last 
     458                for i in xrange(1, n-1): 
     459                    dxi = (data.x[i+1] - data.x[i-1])/2 
     460                    sum += (data.x[i] * data.x[i] * dy[i] * dxi)**2 
     461                return math.sqrt(sum) 
    291462         
    292463    def _get_qstar_smear_uncertainty(self): 
     
    307478            note: if data doesn't contain dy assume dy= math.sqrt(data.y) 
    308479        """ 
     480        if data is None: 
     481            data = self._data 
     482             
     483        if not data.is_slit_smeared(): 
     484            msg = "_get_qstar_smear_uncertainty need slit smear data " 
     485            msg += "Hint :dxl= %s , dxw= %s"%(str(data.dxl), str(data.dxw)) 
     486            raise ValueError, msg 
     487 
     488        if len(data.x) <= 1 or len(data.y) <= 1 or len(data.x) != len(data.y)\ 
     489                or len(data.x) != len(data.dxl): 
     490            msg = "x, dxl, and y must be have the same length and greater than 1" 
     491            raise ValueError, msg 
     492        else: 
     493            #Create error for data without dy error 
     494            if (data.dy is None) or (not data.dy): 
     495                dy = math.sqrt(y) 
     496            else: 
     497                dy = data.dy 
     498                 
     499            n = len(data.x) - 1 
     500            #compute the first delta 
     501            dx0 = (data.x[1] - data.x[0])/2 
     502            #compute the last delta 
     503            dxn = data.x[n] - data.x[n-1] 
     504            sum = 0 
     505            sum += (data.x[0] * data.dxl[0] * dy[0] * dx0)**2 
     506            sum += (data.x[n] * data.dxl[n] * dy[n] * dxn)**2 
     507             
     508            if len(data.x) == 2: 
     509                return math.sqrt(sum) 
     510            else: 
     511                #iterate between for element different from the first and the last 
     512                for i in xrange(1, n-1): 
     513                    dxi = (data.x[i+1] - data.x[i-1])/2 
     514                    sum += (data.x[i] * data.dxl[i] * dy[i] * dxi)**2 
     515                return math.sqrt(sum) 
    309516         
    310517    def get_surface(self,contrast, porod_const): 
     
    322529            @return: specific surface  
    323530        """ 
    324         
     531        #Check whether we have Q star 
     532        if self._qstar is None: 
     533            self._qstar = self.get_star() 
     534        if self._qstar == 0: 
     535            raise RuntimeError("Cannot compute surface, invariant value is zero") 
     536        # Compute the volume 
     537        volume = self.get_volume_fraction(contrast) 
     538        return 2 * math.pi * volume *(1 - volume) * float(porod_const)/self._qstar 
     539         
     540         
    325541    def get_volume_fraction(self, contrast): 
    326542        """ 
     
    328544             
    329545            q_star = 2*(pi*contrast)**2* volume( 1- volume) 
    330             for k = 10^(8)*q_star/(2*(pi*|contrast|)**2) 
     546            for k = 10^(-8)*q_star/(2*(pi*|contrast|)**2) 
    331547            we get 2 values of volume: 
     548                 with   1 - 4 * k >= 0 
    332549                 volume1 = (1- sqrt(1- 4*k))/2 
    333550                 volume2 = (1+ sqrt(1- 4*k))/2 
     
    335552            q_star: the invariant value included extrapolation is applied 
    336553                         unit  1/A^(3)*1/cm 
    337                     q_star = self._qstar 
     554                    q_star = self.get_qstar() 
    338555                     
    339556            the result returned will be 0<= volume <= 1 
     
    344561            @note: volume fraction must have no unit 
    345562        """ 
    346          
     563        if contrast < 0: 
     564            raise ValueError, "contrast must be greater than zero"   
     565         
     566        if self._qstar is None: 
     567            self._qstar = self.get_qstar() 
     568         
     569        if self._qstar < 0: 
     570            raise RuntimeError, "invariant must be greater than zero" 
     571         
     572        print "self._qstar",self._qstar 
     573        # Compute intermediate constant 
     574        k =  1.e-8 * self._qstar/(2 * (math.pi * math.fabs(float(contrast)))**2) 
     575        #Check discriminant value 
     576        discrim = 1 - 4 * k 
     577        print "discrim",k,discrim 
     578        # Compute volume fraction 
     579        if discrim < 0: 
     580            raise RuntimeError, "could not compute the volume fraction: negative discriminant" 
     581        elif discrim ==0: 
     582            return 1/2 
     583        else: 
     584            volume1 = 0.5 *(1 - math.sqrt(discrim)) 
     585            volume2 = 0.5 *(1 + math.sqrt(discrim)) 
     586             
     587            if 0 <= volume1 and volume1 <= 1: 
     588                return volume1 
     589            elif 0 <= volume2 and volume2 <= 1:  
     590                return volume2  
     591            raise RuntimeError, "could not compute the volume fraction: inconsistent results" 
     592     
    347593    def _get_qstar_low(self): 
    348594        """ 
     
    355601            @return q_star: the invariant for data extrapolated at low q. 
    356602        """ 
     603        data = self._get_extra_data_low() 
     604        return self._get_qstar(data=data) 
    357605         
    358606    def _get_qstar_high(self): 
     
    366614            @return q_star: the invariant for data extrapolated at high q. 
    367615        """ 
     616        data = self._get_extra_data_high() 
     617        return self._get_qstar( data=data) 
    368618         
    369619    def _get_extra_data_low(self): 
     
    388638            @return: a new data of type Data1D 
    389639        """ 
    390          
     640        # Data boundaries for fiiting 
     641        qmin = self._data.x[0] 
     642        qmax = self._data.x[self._low_extrapolation_npts] 
     643         
     644        try: 
     645            # fit the data with a model to get the appropriate parameters 
     646            a, b = self._fit(function=self._low_extrapolation_function, 
     647                                   qmin=qmin, qmax=qmax) 
     648        except: 
     649            raise 
     650            return None 
     651        
     652        #create new Data1D to compute the invariant 
     653        new_x = numpy.linspace(start=Q_MINIMUM, 
     654                               stop=qmin, 
     655                               num=INTEGRATION_NSTEPS, 
     656                               endpoint=True) 
     657        new_y = self._low_extrapolation_function(x=new_x, 
     658                                                          scale=a,  
     659                                                          radius=b) 
     660        dxl = None 
     661        dxw = None 
     662        if self._data.dxl is not None: 
     663            dxl = numpy.ones(1, INTEGRATION_NSTEPS) 
     664            dxl = dxl * self._data.dxl[0] 
     665        if self._data.dxw is not None: 
     666            dwl = numpy.ones(1, INTEGRATION_NSTEPS) 
     667            dwl = dwl * self._data.dwl[0] 
     668             
     669        data_min = LoaderData1D(x=new_x, y=new_y) 
     670        data_min.dxl = dxl 
     671        data_min.dxw = dxw 
     672        self._data.clone_without_data( clone= data_min) 
     673         
     674        return data_min 
     675           
    391676    def _get_extra_data_high(self): 
    392677        """ 
     
    403688            @return: a new data of type Data1D 
    404689        """ 
    405          
    406     def get_qstar_with_error(self): 
     690        # Data boundaries for fiiting 
     691        x_len = len(self._data.x) - 1 
     692        qmin = self._data.x[x_len - self._high_extrapolation_npts] 
     693        qmax = self._data.x[x_len] 
     694         
     695        try: 
     696            # fit the data with a model to get the appropriate parameters 
     697            a, b = self._fit(function=self._high_extrapolation_function, 
     698                                   qmin=qmin, qmax=qmax) 
     699        except: 
     700            raise 
     701            return None 
     702        
     703        #create new Data1D to compute the invariant 
     704        new_x = numpy.linspace(start=qmax, 
     705                               stop=Q_MAXIMUM, 
     706                               num=INTEGRATION_NSTEPS, 
     707                               endpoint=True) 
     708        new_y = self._high_extrapolation_function(x=new_x, 
     709                                                  scale=a,  
     710                                                  power=b) 
     711        dxl = None 
     712        dxw = None 
     713        if self._data.dxl is not None: 
     714            dxl = numpy.ones(1, INTEGRATION_NSTEPS) 
     715            dxl = dxl * self._data.dxl[0] 
     716        if self._data.dxw is not None: 
     717            dwl = numpy.ones(1, INTEGRATION_NSTEPS) 
     718            dwl = dwl * self._data.dwl[0] 
     719             
     720        data_max = LoaderData1D(x=new_x, y=new_y) 
     721        data_max.dxl = dxl 
     722        data_max.dxw = dxw 
     723        self._data.clone_without_data( clone=data_max) 
     724         
     725        return data_max 
     726     
     727    def get_qstar_with_error(self, extrapolation=None): 
    407728        """ 
    408729            Compute the invariant uncertainty. 
    409730            This uncertainty computation depends on whether or not the data is 
    410731            smeared. 
    411             @return dq_star: 
    412                 if slit smear: 
    413                     return self._get_qstar(), self._get_qstar_smear_uncertainty() 
    414                 else: 
    415                     return self._get_qstar(), self._get_qstar_unsmear_uncertainty() 
    416         """ 
    417          
     732            @return: invariant,  the invariant uncertainty 
     733                return self._get_qstar(), self._get_qstar_smear_uncertainty()    
     734        """ 
     735        if self._qstar is None: 
     736            self._qstar = self.get_qstar(extrapolation=extrapolation) 
     737        if self._qstar_err is None: 
     738            self._qstar_err = self._get_qstar_smear_uncertainty() 
     739             
     740        return self._qstar, self._qstar_err 
     741     
    418742    def get_volume_fraction_with_error(self, contrast): 
    419743        """ 
     
    430754            @return: V, dV = self.get_volume_fraction_with_error(contrast), dV 
    431755        """ 
    432          
     756        self._qstar, self._qstar_err = self.get_qstar_with_error() 
     757         
     758        volume = self.get_volume_fraction(contrast) 
     759        if self._qstar < 0: 
     760            raise ValueError, "invariant must be greater than zero" 
     761         
     762        k =  1.e-8 * self._qstar /(2*(math.pi* math.fabs(float(contrast)))**2) 
     763        #check value inside the sqrt function 
     764        value = 1 - k * self._qstar 
     765        if (1 - k * self._qstar) <= 0: 
     766            raise ValueError, "Cannot compute incertainty on volume" 
     767        # Compute uncertainty 
     768        uncertainty = (0.5 * 4 * k * self._qstar_err)/(2 * math.sqrt(1- k * self._qstar)) 
     769         
     770        return volume, math.fabs(uncertainty) 
     771     
    433772    def get_surface_with_error(self, contrast, porod_const): 
    434773        """ 
     
    448787            @return S, dS: the surface, with its uncertainty 
    449788        """ 
    450          
    451      
     789        v, dv = self.get_volume_fraction_with_error(contrast) 
     790        self._qstar, self._qstar_err = self.get_qstar_with_error() 
     791        if self._qstar <= 0: 
     792            raise ValueError, "invariant must be greater than zero" 
     793        ds = porod_const * 2 * math.pi * (( dv - 2 * v * dv)/ self._qstar\ 
     794                 + self._qstar_err * ( v - v**2)) 
     795        s = self.get_surface(contrast=contrast, porod_const=porod_const) 
     796        return s, ds 
  • Invariant/test/utest_use_cases.py

    rb6666d4 ref9ed58  
    44""" 
    55import unittest 
     6import numpy 
    67from DataLoader.loader import  Loader 
    78from sans.invariant import invariant 
    89 
    9  
     10class Data1D: 
     11    print "I am not of type Dataloader.Data1D" 
     12     
    1013class TestInvPolySphere(unittest.TestCase): 
    1114    """ 
     
    1417    def setUp(self): 
    1518        self.data = Loader().load("PolySpheres.txt") 
     19         
     20    def test_wrong_data(self): 
     21        """ test receiving Data1D not of type loader""" 
     22         
     23        wrong_data= Data1D() 
     24        try: 
     25            self.assertRaises(ValueError,invariant.InvariantCalculator(wrong_data)) 
     26        except ValueError, msg: 
     27            print "test pass "+ str(msg) 
     28        else: raise ValueError, "fail to raise exception when expected" 
     29     
    1630         
    1731    def test_use_case_1(self): 
     
    3347        # methods should check that Q* has been computed. If not, it should  
    3448        # compute it by calling get_qstare(), leaving the parameters as default. 
    35         volume_fraction = inv.get_volume_fraction(contrast=1.0) 
    36         surface         = inv.get_surface(contrast=1.0, porod_const=1.0) 
     49        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     50        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     51         
     52        # Test results 
     53        self.assertAlmostEquals(qstar, 7.48959e-5,2) 
     54        self.assertAlmostEquals(v, 0.005644689) 
     55        self.assertAlmostEquals(s, 9.42e+2,2) 
    3756         
    3857    def test_use_case_2(self): 
     
    4665        # Get the invariant with errors 
    4766        qstar, qstar_err = inv.get_qstar_with_error() 
    48         v, dv            = inv.get_volume_fraction_with_error(contrast=1.0) 
    49         s, ds            = inv.get_surface_with_error(contrast=1.0, porod_const=1.0) 
     67         
     68        # The volume fraction and surface use Q*. That means that the following  
     69        # methods should check that Q* has been computed. If not, it should  
     70        # compute it by calling get_qstare(), leaving the parameters as default. 
     71        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     72        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     73        # Test results 
     74        self.assertAlmostEquals(qstar, 7.48959e-5,2) 
     75        self.assertAlmostEquals(v, 0.005644689) 
     76        self.assertAlmostEquals(s, 9.42e+2,2) 
     77        
    5078         
    5179    def test_use_case_3(self): 
     
    6290        # The function parameter should default to None. If it is None, 
    6391        #    the method should pick a good default (Guinier at low-Q and 1/q^4 at high-Q). 
    64         #    The method should also check for consistency of the extrapolate and function 
     92        #    The method should also check for consistency of the extrapolation and function 
    6593        #    parameters. For instance, you might not want to allow 'high' and 'guinier'. 
    6694        # The power parameter (not shown below) should default to 4. 
    67         inv.set_extraplotation(range='low', npts=5, function='guinier') 
     95        inv.set_extrapolation(range='low', npts=20, function='guinier') 
    6896         
    6997        # The version of the call without error 
    7098        # At this point, we could still compute Q* without extrapolation by calling 
    71         # get_qstar with arguments, or with extrapolate=None. 
    72         qstar = inv.get_qstar(extrapolate='low') 
    73          
    74         # The version of the call with error 
    75         qstar, qstar_err = inv.get_qstar_with_error(extrapolate='low') 
    76  
    77         # Get the volume fraction and surface 
    78         v, dv            = inv.get_volume_fraction_with_error(contrast=1.0) 
    79         s, ds            = inv.get_surface_with_error(contrast=1.0, porod_const=1.0) 
    80          
     99        # get_qstar with arguments, or with extrapolation=None. 
     100        qstar = inv.get_qstar(extrapolation='low') 
     101         
     102        # The version of the call with error 
     103        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') 
     104 
     105        # Get the volume fraction and surface 
     106        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     107        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     108         
     109        # Test results 
     110        self.assertAlmostEquals(qstar, 7.49e-5,2) 
     111        self.assertAlmostEquals(v, 0.005648401) 
     112        self.assertAlmostEquals(s, 9.42e+2,2) 
     113             
    81114    def test_use_case_4(self): 
    82115        """ 
     
    86119        inv = invariant.InvariantCalculator(data=self.data) 
    87120         
    88  
    89121        # Set the extrapolation parameters for the high-Q range 
    90          
    91         # The npts parameter should have a good default. 
    92         # The range parameter should be 'high' or 'low'. Those should be stored separately. 
    93         # The function parameter should default to None. If it is None, 
    94         #    the method should pick a good default (Guinier at low-Q and 1/q^4 at high-Q). 
    95         #    The method should also check for consistency of the extrapolate and function 
    96         #    parameters. For instance, you might not want to allow 'high' and 'guinier'. 
    97         # The power parameter should default to 4. 
    98         inv.set_extraplotation(range='high', npts=5, function='power_law', power=4) 
    99          
    100          
    101         # The version of the call without error 
    102         # The function parameter defaults to None, then is picked to be 'power_law' for extrapolate='high' 
    103         qstar = inv.get_qstar(extrapolate='high') 
    104          
    105         # The version of the call with error 
    106         qstar, qstar_err = inv.get_qstar_with_error(extrapolate='high') 
    107  
    108         # Get the volume fraction and surface 
    109         v, dv            = inv.get_volume_fraction_with_error(contrast=1.0) 
    110         s, ds            = inv.get_surface_with_error(contrast=1.0, porod_const=1.0) 
     122        inv.set_extrapolation(range='high', npts=20, function='power_law', power=4) 
     123         
     124        # The version of the call without error 
     125        # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     126        qstar = inv.get_qstar(extrapolation='high') 
     127         
     128        # The version of the call with error 
     129        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='high') 
     130 
     131        # Get the volume fraction and surface 
     132        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     133        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     134         
     135        # Test results 
     136        self.assertAlmostEquals(qstar, 7.49e-5,2) 
     137        self.assertAlmostEquals(v, 0.005952674) 
     138        self.assertAlmostEquals(s, 9.42e+2,2) 
    111139         
    112140    def test_use_case_5(self): 
     
    118146         
    119147        # Set the extrapolation parameters for the low- and high-Q ranges 
    120         inv.set_extraplotation(range='low', npts=5, function='guinier') 
    121         inv.set_extraplotation(range='high', npts=5, function='power_law', power=4) 
    122          
    123         # The version of the call without error 
    124         # The function parameter defaults to None, then is picked to be 'power_law' for extrapolate='high' 
    125         qstar = inv.get_qstar(extrapolate='both') 
    126          
    127         # The version of the call with error 
    128         qstar, qstar_err = inv.get_qstar_with_error(extrapolate='both') 
    129  
    130         # Get the volume fraction and surface 
    131         v, dv            = inv.get_volume_fraction_with_error(contrast=1.0) 
    132         s, ds            = inv.get_surface_with_error(contrast=1.0, porod_const=1.0) 
    133          
    134                  
     148        inv.set_extrapolation(range='low', npts=5, function='guinier') 
     149        inv.set_extrapolation(range='high', npts=5, function='power_law', power=4) 
     150         
     151        # The version of the call without error 
     152        # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     153        qstar = inv.get_qstar(extrapolation='both') 
     154         
     155        # The version of the call with error 
     156        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='both') 
     157 
     158        # Get the volume fraction and surface 
     159        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     160        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     161         
     162        # Test results 
     163        self.assertAlmostEquals(qstar, 7.90069e-5,2) 
     164        self.assertAlmostEquals(v, 0.005952674) 
     165        self.assertAlmostEquals(s, 9.42e+2,2) 
     166       
     167class TestInvSlitSmear(unittest.TestCase): 
     168    """ 
     169        Test slit smeared data for invariant computation 
     170    """ 
     171    def setUp(self): 
     172        # Data with slit smear  
     173        list = Loader().load("latex_smeared.xml") 
     174        self.data_slit_smear = list[1] 
     175     
     176    def test_use_case_1(self): 
     177        """ 
     178            Invariant without extrapolation 
     179        """ 
     180        inv = invariant.InvariantCalculator(data=self.data_slit_smear) 
     181        # get invariant 
     182        qstar = inv.get_qstar() 
     183        # Get the volume fraction and surface 
     184        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     185        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     186        # Test results 
     187        self.assertAlmostEquals(qstar, 4.1539e-4) 
     188        self.assertAlmostEquals(v, 0.032164596) 
     189        self.assertAlmostEquals(s, 9.42e+2,2) 
     190        
     191    def test_use_case_2(self): 
     192        """ 
     193            Invariant without extrapolation. Invariant, volume fraction and surface  
     194            are given with errors. 
     195        """ 
     196        # Create invariant object. Background and scale left as defaults. 
     197        inv = invariant.InvariantCalculator(data=self.data_slit_smear) 
     198        # Get the invariant with errors 
     199        qstar, qstar_err = inv.get_qstar_with_error() 
     200        # Get the volume fraction and surface 
     201        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     202        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     203        # Test results 
     204        self.assertAlmostEquals(qstar, 4.1539e-4) 
     205        self.assertAlmostEquals(v, 0.032164596) 
     206        self.assertAlmostEquals(s, 9.42e+2,2) 
     207         
     208    def test_use_case_3(self): 
     209        """ 
     210            Invariant with low-Q extrapolation 
     211        """ 
     212        # Create invariant object. Background and scale left as defaults. 
     213        inv = invariant.InvariantCalculator(data=self.data_slit_smear) 
     214        # Set the extrapolation parameters for the low-Q range 
     215        inv.set_extrapolation(range='low', npts=20, function='guinier') 
     216        # The version of the call without error 
     217        # At this point, we could still compute Q* without extrapolation by calling 
     218        # get_qstar with arguments, or with extrapolation=None. 
     219        qstar = inv.get_qstar(extrapolation='low') 
     220        # The version of the call with error 
     221        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') 
     222        # Get the volume fraction and surface 
     223        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     224        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     225         
     226        # Test results 
     227        self.assertAlmostEquals(qstar,4.1534e-4,3) 
     228        self.assertAlmostEquals(v, 0.032164596) 
     229        self.assertAlmostEquals(s, 9.42e+2,2) 
     230             
     231    def test_use_case_4(self): 
     232        """ 
     233            Invariant with high-Q extrapolation 
     234        """ 
     235        # Create invariant object. Background and scale left as defaults. 
     236        inv = invariant.InvariantCalculator(data=self.data_slit_smear) 
     237         
     238        # Set the extrapolation parameters for the high-Q range 
     239        inv.set_extrapolation(range='high', npts=20, function='power_law', power=4) 
     240         
     241        # The version of the call without error 
     242        # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     243        qstar = inv.get_qstar(extrapolation='high') 
     244         
     245        # The version of the call with error 
     246        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='high') 
     247 
     248        # Get the volume fraction and surface 
     249        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     250        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     251         
     252        # Test results 
     253        self.assertAlmostEquals(qstar, 4.1539e-4) 
     254        self.assertAlmostEquals(v, 0.032164596) 
     255        self.assertAlmostEquals(s, 9.42e+2,2) 
     256         
     257    def test_use_case_5(self): 
     258        """ 
     259            Invariant with both high- and low-Q extrapolation 
     260        """ 
     261        # Create invariant object. Background and scale left as defaults. 
     262        inv = invariant.InvariantCalculator(data=self.data_slit_smear) 
     263         
     264        # Set the extrapolation parameters for the low- and high-Q ranges 
     265        inv.set_extrapolation(range='low', npts=20, function='guinier') 
     266        inv.set_extrapolation(range='high', npts=20, function='power_law', power=4) 
     267         
     268        # The version of the call without error 
     269        # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     270        qstar = inv.get_qstar(extrapolation='both') 
     271         
     272        # The version of the call with error 
     273        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='both') 
     274 
     275        # Get the volume fraction and surface 
     276        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     277        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     278         
     279        # Test results 
     280        self.assertAlmostEquals(qstar, 4.1534e-4,3) 
     281        self.assertAlmostEquals(v, 0.032164596) 
     282        self.assertAlmostEquals(s, 9.42e+2,2) 
     283   
     284class TestInvPinholeSmear(unittest.TestCase): 
     285    """ 
     286        Test pinhole smeared data for invariant computation 
     287    """ 
     288    def setUp(self): 
     289        # data with smear info 
     290        list = Loader().load("latex_smeared.xml") 
     291        self.data_q_smear = list[0] 
     292     
     293    def test_use_case_1(self): 
     294        """ 
     295            Invariant without extrapolation 
     296        """ 
     297        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
     298        qstar = inv.get_qstar() 
     299         
     300        volume_fraction = inv.get_volume_fraction(contrast=2.6e-6) 
     301        surface = inv.get_surface(contrast=2.6e-6, porod_const=2) 
     302        # Test results 
     303        self.assertAlmostEquals(qstar, 1.361677e-3) 
     304        self.assertAlmostEquals(v, 0.115352622) 
     305        self.assertAlmostEquals(s, 9.42e+2,2) 
     306         
     307    def test_use_case_2(self): 
     308        """ 
     309            Invariant without extrapolation. Invariant, volume fraction and surface  
     310            are given with errors. 
     311        """ 
     312        # Create invariant object. Background and scale left as defaults. 
     313        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
     314         
     315        # Get the invariant with errors 
     316        qstar, qstar_err = inv.get_qstar_with_error() 
     317        # Get the volume fraction and surface 
     318        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     319        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     320        # Test results 
     321        self.assertAlmostEquals(qstar, 1.361677e-3) 
     322        self.assertAlmostEquals(v, 0.115352622) 
     323        self.assertAlmostEquals(s, 9.42e+2,2) 
     324        
     325    def test_use_case_3(self): 
     326        """ 
     327            Invariant with low-Q extrapolation 
     328        """ 
     329        # Create invariant object. Background and scale left as defaults. 
     330        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
     331        # Set the extrapolation parameters for the low-Q range 
     332        inv.set_extrapolation(range='low', npts=20, function='guinier') 
     333        # The version of the call without error 
     334        qstar = inv.get_qstar(extrapolation='low') 
     335        # The version of the call with error 
     336        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') 
     337        # Get the volume fraction and surface 
     338        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     339        s, ds = inv.get_surface_with_error(contrast=1.0, porod_const=0.08) 
     340         
     341        # Test results 
     342        self.assertAlmostEquals(qstar, 0.002037677) 
     343        self.assertAlmostEquals(v, 0.115352622) 
     344        self.assertAlmostEquals(s, 9.42e+2,2) 
     345       
     346    def test_use_case_4(self): 
     347        """ 
     348            Invariant with high-Q extrapolation 
     349        """ 
     350        # Create invariant object. Background and scale left as defaults. 
     351        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
     352        # Set the extrapolation parameters for the high-Q range 
     353        inv.set_extrapolation(range='high', npts=20, function='power_law', power=4) 
     354        # The version of the call without error 
     355        qstar = inv.get_qstar(extrapolation='high') 
     356        # The version of the call with error 
     357        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='high') 
     358        # Get the volume fraction and surface 
     359        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     360        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     361         
     362        # Test results 
     363        self.assertAlmostEquals(qstar, 1.481677e-3) 
     364        self.assertAlmostEquals(v, 0.127225804) 
     365        self.assertAlmostEquals(s, 9.42e+2,2) 
     366        
     367    def test_use_case_5(self): 
     368        """ 
     369            Invariant with both high- and low-Q extrapolation 
     370        """ 
     371        # Create invariant object. Background and scale left as defaults. 
     372        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
     373        # Set the extrapolation parameters for the low- and high-Q ranges 
     374        inv.set_extrapolation(range='low', npts=20, function='guinier') 
     375        inv.set_extrapolation(range='high', npts=20, function='power_law', power=4) 
     376        # The version of the call without error 
     377        # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     378        qstar = inv.get_qstar(extrapolation='both') 
     379        # The version of the call with error 
     380        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='both') 
     381        # Get the volume fraction and surface 
     382        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
     383        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
     384         
     385        # Test results 
     386        self.assertAlmostEquals(qstar, 0.002157677) 
     387        self.assertAlmostEquals(v, 0.202846825) 
     388        self.assertAlmostEquals(s, 9.42e+2,2) 
Note: See TracChangeset for help on using the changeset viewer.