source: sasview/DataLoader/invariant.py @ 255306e

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 255306e was 4026380, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

dataloader: improved invariant

  • Property mode set to 100644
File size: 7.1 KB
Line 
1"""
2    This module is responsible to compute invariant related computation.
3    @author: Gervaise B. Alina/UTK
4"""
5
6import math 
7from DataLoader.data_info import Data1D as LoaderData1D
8class InvariantCalculator(object):
9    """
10        Compute invariant if data is given.
11        Can provide volume fraction and surface area if the user provides
12        Porod constant  and contrast values.
13        @precondition:  the user must send a data of type DataLoader.Data1D
14        @note: The data boundaries are assumed as infinite range.
15    """
16    def __init__(self, data):
17        """
18            Initialize variables
19            @param data: data must be of type DataLoader.Data1D
20            @param contrast: contrast value of type float
21            @param pConst: Porod Constant of type float
22        """
23        ## Invariant
24        self.q_star = self._get_q_star(data= data)
25       
26    def _get_q_star(self, data):
27        """
28            @param data: data of type Data1D
29            @return invariant value
30        """
31        if not issubclass(data.__class__, LoaderData1D):
32            #Process only data that inherited from DataLoader.Data_info.Data1D
33            raise ValueError,"Data must be of type DataLoader.Data1D"
34       
35        # Check whether we have slit smearing information
36        if data.is_slit_smeared():
37            return self._get_qstar_unsmeared(data= data)
38        else:
39            return self._get_qstar_smeared(data= data)
40   
41           
42           
43    def _get_qstar_unsmeared(self, data):
44        """
45            @param data: data of type Data1D
46            Compute invariant given by
47            q_star= x0**2 *y0 *dx0 +x1**2 *y1 *dx1 + ..+ xn**2 *yn *dxn
48            where n= infinity
49            dxi = 1/2*(xi+1 - xi) + (xi - xi-1)
50            dx0 = x1 - x0
51            dxn = xn - xn-1
52        """
53        if len(data.x)<=1 or len(data.y)<=1 or len(data.x)!=len(data.y):
54            msg=  "Length x and y must be equal"
55            msg +=" and greater than 1; got x=%s, y=%s"%(len(data.x),
56                                                         len(data.y))
57            raise ValueError,msg
58        elif len(data.x)==1 and len(data.y)==1:
59            return 0
60   
61        else:
62            n= len(data.x)-1
63            #compute the first delta
64            dx0= data.x[1]- data.x[0]
65            #compute the last delta
66            dxn= data.x[n]- data.x[n-1]
67            sum = 0
68            sum += data.x[0]* data.x[0]* data.y[0]*dx0
69            sum += data.x[n]* data.x[n]* data.y[n]*dxn
70            if len(data.x)==2:
71                return sum
72            else:
73                #iterate between for element different from the first and the last
74                for i in xrange(1, n-1):
75                    dxi = (data.x[i+1] - data.x[i-1])/2
76                    sum += data.x[i]*data.x[i]* data.y[i]* dxi
77                return sum
78           
79               
80    def _get_qstar_smeared(self, data):
81        """
82            @param data: data of type Data1D
83            Compute invariant with slit smearing info
84            q_star= x0*dxl *y0 *dx0 + x1*dxl *y1 *dx1 + ..+ xn*dxl *yn *dxn
85            where n= infinity
86            dxi = 1/2*(xi+1 - xi) + (xi - xi-1)
87            dx0 = x1 - x0
88            dxn = xn - xn-1
89            dxl: slit smearing value
90        """
91        if data.dxl ==None:
92            msg = "Cannot compute Smear invariant dxl "
93            msg +="must be a list, got dx= %s"%str(data.dxl)
94            raise ValueError,msg
95
96        if len(data.x)<=1 or len(data.y)<=1 or len(data.x)!=len(data.y)\
97                or len(data.x)!= len(data.dxl):
98           
99            msg = "x, dxl, and y must be have the same length and greater than 1"
100            raise ValueError,msg
101        else:
102            n= len(data.x)-1
103            #compute the first delta
104            dx0= data.x[1]- data.x[0]
105            #compute the last delta
106            dxn= data.x[n]- data.x[n-1]
107            sum = 0
108            sum += data.x[0]* data.dxl[0]* data.y[0]*dx0
109            sum += data.x[n]* data.dxl[n]* data.y[n]*dxn
110            if len(data.x)==2:
111                return sum
112            else:
113                #iterate between for element different from the first and the last
114                for i in xrange(1, n-1):
115                    dxi = (data.x[i+1] - data.x[i-1])/2
116                    sum += data.x[i]* data.dxl[i]* data.y[i]* dxi
117                return sum
118       
119    def get_volume_fraction(self, contrast):
120        """
121            Compute volume fraction is given by:
122           
123                q_star= 2*(pi*contrast)**2* volume( 1- volume)
124                for k = 10^(8)*q_star/(2*(pi*|contrast|)**2)
125                we get 2 values of volume:
126                     volume1 = (1- sqrt(1- 4*k))/2
127                     volume2 = (1+ sqrt(1- 4*k))/2
128                contrast unit is 1/A^(2)= 10^(16)cm^(2)
129                q_star unit  1/A^(3)*1/cm
130               
131            the result returned will be 0<= volume <= 1
132           
133            @param contrast: contrast value provides by the user of type float
134            @return: volume fraction
135            @note: volume fraction must have no unit
136        """
137        if contrast < 0:
138            raise ValueError, "contrast must be greater than zero" 
139       
140        if self.q_star ==None:
141            raise RuntimeError, "Q_star is not defined"
142       
143        if self.q_star < 0:
144            raise ValueError, "invariant must be greater than zero. Q_star=%g" % self.q_star
145       
146        #compute intermediate constant
147        k =  1.e-8*self.q_star /(2*(math.pi* math.fabs(float(contrast)))**2)
148        #check discriminant value
149        discrim= 1 - 4*k
150        if discrim < 0:
151            raise RuntimeError, "could not compute the volume fraction: negative discriminant"
152        elif discrim ==0:
153            volume = 1/2
154            return volume
155        else:
156            # compute the volume
157            volume1 = 0.5 *(1 - math.sqrt(discrim))
158            volume2 = 0.5 *(1 + math.sqrt(discrim))
159           
160            if 0<= volume1 and volume1 <= 1:
161                return volume1
162            elif 0<= volume2 and volume2<= 1: 
163                return volume2
164            raise RuntimeError, "could not compute the volume fraction: inconsistent results"
165   
166    def get_surface(self, contrast, porod_const):
167        """
168            Compute the surface given by:
169                surface = (2*pi *volume(1- volume)*pConst)/ q_star
170               
171            @param contrast: contrast value provides by the user of type float
172            @param porod_const: Porod constant
173            @return: specific surface
174        """
175        # Compute the volume
176        volume = self.get_volume_fraction(contrast)
177       
178        # Check whether we have Q star
179        if self.q_star ==None:
180            raise RuntimeError, "Q_star is not defined"
181       
182        if self.q_star ==0:
183            raise ValueError, "invariant must be greater than zero. Q_star=%g" % self.q_star
184       
185        return 2*math.pi*volume*(1-volume)*float(porod_const)/self.q_star
186       
187       
Note: See TracBrowser for help on using the repository browser.