source: sasview/DataLoader/invariant.py @ 07e88d7

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 07e88d7 was 01fb70b, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

dataloader: remove buggy code that doesn't run.

  • Property mode set to 100644
File size: 7.5 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,contrast=None, pConst=None):
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        self.q_star = self.getQstar(data= data)
24        self.volume = self._getVolFrac(contrast= contrast)
25        self.surface= self._getSurface(pConst= pConst)
26       
27    def __call__(self, contrast, pConst):
28        """
29            @precondition: self.q_star has already been computed
30        """
31        self.volume = self._getVolFrac(contrast= contrast)
32        self.surface = self._getSurface(pConst= pConst)
33       
34        return self
35       
36    def getQstar(self, data):
37        """
38            @param data: data of type Data1D
39            @return invariant value
40        """
41        if not issubclass(data.__class__, LoaderData1D):
42            #Process only data that inherited from DataLoader.Data_info.Data1D
43            raise ValueError,"Data must be of type DataLoader.Data1D"
44        if data.dxl == None:
45            return self._getQStarUnsmear(data= data)
46        else:
47            return self._getQStarSmear(data= data)
48   
49           
50           
51    def _getQStarUnsmear(self, data):
52        """
53            @param data: data of type Data1D
54            Compute invariant given by
55            q_star= x0**2 *y0 *dx0 +x1**2 *y1 *dx1 + ..+ xn**2 *yn *dxn
56            where n= infinity
57            dxi = 1/2*(xi+1 - xi) + (xi - xi-1)
58            dx0 = x1 - x0
59            dxn = xn - xn-1
60        """
61        if len(data.x)<=1 or len(data.y)<=1 or len(data.x)!=len(data.y):
62            msg=  "Length x and y must be equal"
63            msg +=" and greater than 1; got x=%s, y=%s"%(len(data.x),
64                                                         len(data.y))
65            raise ValueError,msg
66        elif len(data.x)==1 and len(data.y)==1:
67            return 0
68   
69        else:
70            n= len(data.x)-1
71            #compute the first delta
72            dx0= data.x[1]- data.x[0]
73            #compute the last delta
74            dxn= data.x[n]- data.x[n-1]
75            sum = 0
76            sum += data.x[0]* data.x[0]* data.y[0]*dx0
77            sum += data.x[n]* data.x[n]* data.y[n]*dxn
78            if len(data.x)==2:
79                return sum
80            else:
81                #iterate between for element different from the first and the last
82                for i in xrange(1, n-1):
83                    dxi = (data.x[i+1] - data.x[i-1])/2
84                    sum += data.x[i]*data.x[i]* data.y[i]* dxi
85                return sum
86           
87               
88    def _getQStarSmear(self, data):
89        """
90            @param data: data of type Data1D
91            Compute invariant with smearing info
92            q_star= x0*dxl *y0 *dx0 + x1*dxl *y1 *dx1 + ..+ xn*dxl *yn *dxn
93            where n= infinity
94            dxi = 1/2*(xi+1 - xi) + (xi - xi-1)
95            dx0 = x1 - x0
96            dxn = xn - xn-1
97            dxl: slit smearing value
98        """
99        if data.dxl ==None:
100            msg = "Cannot compute Smear invariant dxl "
101            msg +="must be a list, got dx= %s"%str(data.dxl)
102            raise ValueError,msg
103
104        if len(data.x)<=1 or len(data.y)<=1 or len(data.x)!=len(data.y)\
105                or len(data.x)!= len(data.dxl):
106           
107            msg = "x, dxl, and y must be have the same length and greater than 1"
108            raise ValueError,msg
109        else:
110            n= len(data.x)-1
111            #compute the first delta
112            dx0= data.x[1]- data.x[0]
113            #compute the last delta
114            dxn= data.x[n]- data.x[n-1]
115            sum = 0
116            sum += data.x[0]* data.dxl[0]* data.y[0]*dx0
117            sum += data.x[n]* data.dxl[n]* data.y[n]*dxn
118            if len(data.x)==2:
119                return sum
120            else:
121                #iterate between for element different from the first and the last
122                for i in xrange(1, n-1):
123                    dxi = (data.x[i+1] - data.x[i-1])/2
124                    sum += data.x[i]* data.dxl[i]* data.y[i]* dxi
125                return sum
126       
127    def _getVolFrac(self,contrast):
128        """
129            Compute volume fraction is given by:
130           
131                q_star= 2*(pi*contrast)**2* volume( 1- volume)
132                for k = 10^(8)*q_star/(2*(pi*|contrast|)**2)
133                we get 2 values of volume:
134                     volume1 = (1- sqrt(1- 4*k))/2
135                     volume2 = (1+ sqrt(1- 4*k))/2
136                contrast unit is 1/A^(2)= 10^(16)cm^(2)
137                q_star unit  1/A^(3)*1/cm
138               
139            the result returned will be 0<= volume <= 1 or None
140           
141            @param contrast: contrast value provides by the user of type float
142            @return None : if the invariant Calculator does not a computed
143            q_star already  stored
144            @note: volume fraction must have no unit
145        """
146        if contrast ==None:
147            #No contrast value is provided for calculation then no calculation
148            return 
149        if contrast < 0:
150            raise ValueError, "contrast must be greater than zero" 
151       
152        if self.q_star ==None:
153            return 
154       
155        if self.q_star < 0:
156            raise ValueError, "invariant must be greater than zero"
157       
158        #compute intermediate constant
159        k =  1.e-8*self.q_star /(2*(math.pi* math.fabs(float(contrast)))**2)
160        #check discriminant value
161        discrim= 1 - 4*k
162        if discrim < 0:
163            return 
164        elif discrim ==0:
165            volume = 1/2
166            return volume
167        else:
168            # compute the volume
169            volume1 = 0.5 *(1 - math.sqrt(discrim))
170            volume2 = 0.5 *(1 + math.sqrt(discrim))
171            print "volume1",volume1
172            print "volume2",volume2
173           
174            if 0<= volume1 and volume1 <= 1:
175                return volume1
176            elif 0<= volume2 and volume2<= 1: 
177                return volume2
178            return 
179   
180    def _getSurface(self, pConst, volume=None):
181        """
182            Compute the surface given by:
183                surface = (2*pi *volume(1- volume)*pConst)/ q_star
184            @param volume : volume previously calculated
185            @return None: if volume used for computation equal None
186        """
187        #check if the user provides a value for volume
188        if volume != None:
189            self.volume = float(volume)
190       
191        #return None if volume or q_star is not computed
192        if self.q_star ==None or self.volume == None:
193            return 
194        if self.q_star ==0:
195            raise ZeroDivisionError, "invariant must be greater than zero"
196       
197        return 2*math.pi*self.volume*(1- self.volume)*float(pConst)/self.q_star
198       
199       
Note: See TracBrowser for help on using the repository browser.