source: sasview/sansmodels/src/sans/models/test/utest_nonshape.py @ f629e346

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 f629e346 was f629e346, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Updated tests to reflect proper math (took test funcs from Igor). Still need to look into incoherence btw Igor docs and Igor code!

  • Property mode set to 100644
File size: 15.5 KB
Line 
1"""
2    Unit tests for non shape based model (Task 8.2.1)
3    These tests are part of the requirements
4"""
5
6import unittest, time, math
7from scipy.special import erf,gammaln
8
9# Disable "missing docstring" complaint
10# pylint: disable-msg=C0111
11# Disable "too many methods" complaint
12# pylint: disable-msg=R0904
13# Disable "could be a function" complaint
14# pylint: disable-msg=R0201
15
16import scipy 
17class TestGuinier(unittest.TestCase):
18    """
19        Unit tests for Guinier function
20       
21        F(x) = exp[ [A] + [B]*Q**2 ]
22       
23        The model has two parameters: A and B
24    """
25    def _func(self, a, b, x):
26        return a*math.exp(-(b*x)**2/3.0)
27   
28    def setUp(self):
29        from sans.models.GuinierModel import GuinierModel
30        self.model= GuinierModel()
31       
32    def test1D(self):
33        self.model.setParam('scale', 2.0)
34        self.model.setParam('rg', 1.0)
35       
36        self.assertEqual(self.model.run(0.0), 2.0)
37        self.assertEqual(self.model.run(2.0), 2.0*math.exp(-(1.0*2.0)**2/3.0))
38       
39    def test2D(self):
40        self.model.setParam('scale', 2.0)
41        self.model.setParam('rg', 1.0)
42       
43        value = self._func(2.0, 1.0, 1.0)*self._func(2.0, 1.0, 2.0)
44        self.assertEqual(self.model.runXY([0.0,0.0]), 2.0*2.0)
45        self.assertEqual(self.model.runXY([1.0,2.0]), value)
46       
47    def test2Dphi(self):
48        self.model.setParam('scale', 2.0)
49        self.model.setParam('rg', 1.0)
50       
51        x = 1.0
52        y = 2.0
53        r = math.sqrt(x**2 + y**2)
54        phi = math.atan2(y, x)
55       
56        value = self._func(2.0, 1.0, x)*self._func(2.0, 1.0, y)
57       
58        #self.assertEqual(self.model.run([r, phi]), value)
59        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
60       
61       
62class TestPorod(unittest.TestCase):
63    """
64        Unit tests for Porod function
65       
66        F(x) = C/Q**4
67       
68        The model has one parameter: C
69    """
70    def _func(self, c, x):
71        return c/(x**4)
72   
73    def setUp(self):
74        from sans.models.PorodModel import PorodModel
75        self.model= PorodModel()
76        self.model.setParam('scale', 2.0)       
77       
78    def test1D(self):
79        value = self._func(2.0, 3.0)
80        self.assertEqual(self.model.run(3.0), value)
81       
82    def test2D(self):
83        value = self._func(2.0, 1.0)*self._func(2.0, 2.0)
84        self.assertEqual(self.model.runXY([1.0,2.0]), value)
85       
86    def test2Dphi(self):
87        x = 1.0
88        y = 2.0
89        r = math.sqrt(x**2 + y**2)
90        phi = math.atan2(y, x)
91       
92        value = self._func(2.0, 1.0)*self._func(2.0, 2.0)
93        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
94       
95class TestDebye(unittest.TestCase):
96    """
97        Unit tests for Debye function
98       
99        F(x) = 2( exp(-x)+x -1 )/x**2
100       
101        The model has three parameters:
102            Rg     =  radius of gyration
103            scale  =  scale factor
104            bkd    =  Constant background
105    """
106    def _func(self, Rg, scale, bkg, x):
107        y = (Rg * x)**2
108        return scale * (2*(math.exp(-y) + y -1)/y**2) + bkg
109   
110    def setUp(self):
111        from sans.models.DebyeModel import DebyeModel
112        self.model= DebyeModel()
113        self.model.setParam('Rg', 50.0)   
114        self.model.setParam('scale',1.0) 
115        self.model.setParam('background',0.001)   
116       
117    def test1D(self):
118        value = self._func(50.0, 1.0, 0.001, 2.0)
119        self.assertEqual(self.model.run(2.0), value)
120       
121        # User enter zero as a value of x
122        # An exceptio is raised
123        self.assertRaises(ZeroDivisionError, self.model.run, 0.0)
124       
125    def test2D(self):
126        value = self._func(50.0, 1.0, 0.001, 1.0)*self._func(50.0, 1.0, 0.001, 2.0)
127        self.assertEqual(self.model.runXY([1.0,2.0]), value)
128       
129    def test2Dphi(self):
130        x = 1.0
131        y = 2.0
132        r = math.sqrt(x**2 + y**2)
133        phi = math.atan2(y, x)
134       
135        value = self._func(50.0, 1.0, 0.001, 1.0)*self._func(50.0, 1.0, 0.001, 2.0)
136        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
137       
138       
139class TestLorentz(unittest.TestCase):
140    """
141        Unit tests for Lorentz function
142       
143         F(x) = scale/( 1 + (x*L)^2 ) + bkd
144       
145        The model has three parameters:
146            L     =  screen Length
147            scale  =  scale factor
148            bkd    =  incoherent background
149    """
150    def _func(self, I0 , L, bgd, qval):
151        return I0/(1.0 + (qval*L)*(qval*L)) + bgd
152   
153    def setUp(self):
154        from sans.models.LorentzModel import LorentzModel
155        self.model= LorentzModel()
156       
157    def test1D(self):
158        self.model.setParam('scale', 100.0)
159        self.model.setParam('Length', 50.0)
160        self.model.setParam('background', 1.0)
161       
162        self.assertEqual(self.model.run(0.0), 101.0)
163        self.assertEqual(self.model.run(2.0), self._func(100.0, 50.0, 1.0, 2.0))
164       
165    def test2D(self):
166        self.model.setParam('scale', 100.0)
167        self.model.setParam('Length', 50.0)
168        self.model.setParam('background', 1.0)
169       
170        value = self._func(100.0, 50.0, 1.0, 1.0)*self._func(100.0, 50.0, 1.0, 2.0)   
171        self.assertEqual(self.model.runXY([1.0,2.0]), value)
172       
173    def test2Dphi(self):
174        self.model.setParam('scale', 100.0)
175        self.model.setParam('Length', 50.0)
176        self.model.setParam('background', 1.0)
177       
178        x = 1.0
179        y = 2.0
180        r = math.sqrt(x**2 + y**2)
181        phi = math.atan2(y, x)
182       
183        value = self._func(100.0, 50.0, 1.0, x)*self._func(100.0, 50.0, 1.0, y)
184        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
185       
186class TestDAB(unittest.TestCase):
187    """
188        Unit tests for DAB function
189       
190         F(x) = scale/( 1 + (x*L)^2 )^(2) + bkd
191       
192        The model has three parameters:
193            L      =  Correlation Length
194            scale  =  scale factor
195            bkd    =  incoherent background
196    """
197    def _func(self, Izero, range, incoh, qval):
198        return Izero/pow((1.0 + (qval*range)*(qval*range)),2) + incoh
199   
200    def setUp(self):
201        from sans.models.DABModel import DABModel
202        self.model= DABModel()
203       
204    def test1D(self):
205        self.model.setParam('scale', 10.0)
206        self.model.setParam('Length', 40.0)
207        self.model.setParam('background', 0.0)
208       
209        self.assertEqual(self.model.run(0.0), 10.0)
210        self.assertEqual(self.model.run(2.0), self._func(10.0, 40.0, 0.0, 2.0))
211       
212    def test2D(self):
213        self.model.setParam('scale', 10.0)
214        self.model.setParam('Length', 40.0)
215        self.model.setParam('background', 0.0)
216       
217        value = self._func(10.0, 40.0, 0.0, 1.0)*self._func(10.0, 40.0, 0.0, 2.0)   
218        self.assertEqual(self.model.runXY([1.0,2.0]), value)
219       
220    def test2Dphi(self):
221        self.model.setParam('scale', 10.0)
222        self.model.setParam('Length', 40.0)
223        self.model.setParam('background', 0.0)
224       
225        x = 1.0
226        y = 2.0
227        r = math.sqrt(x**2 + y**2)
228        phi = math.atan2(y, x)
229       
230        value = self._func(10.0, 40.0, 0.0, x)*self._func(10.0, 40.0, 0.0, y)
231        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
232       
233class TestPowerLaw(unittest.TestCase):
234    """
235        Unit tests for PowerLaw function
236
237        F(x) = scale* (x)^(m) + bkd
238       
239        The model has three parameters:
240            m     =  power
241            scale  =  scale factor
242            bkd    =  incoherent background
243    """
244    def _func(self, a, m, bgd, qval):
245        return a*math.pow(qval,-m) + bgd
246   
247   
248    def setUp(self):
249        from sans.models.PowerLawModel import PowerLawModel
250        self.model= PowerLawModel()
251       
252    def test1D(self):
253        self.model.setParam('scale', math.exp(-6))
254        self.model.setParam('m', 4.0)
255        self.model.setParam('background', 1.0)
256       
257        #self.assertEqual(self.model.run(0.0), 1.0)
258        self.assertEqual(self.model.run(2.0), self._func(math.exp(-6), 4.0, 1.0, 2.0))
259   
260    def testlimit(self):
261        self.model.setParam('scale', math.exp(-6))
262        self.model.setParam('m', -4.0)
263        self.model.setParam('background', 1.0)
264       
265        self.assertEqual(self.model.run(0.0), 1.0)
266       
267    def test2D(self):
268        self.model.setParam('scale', math.exp(-6))
269        self.model.setParam('m', 4.0)
270        self.model.setParam('background', 1.0)
271       
272        value = self._func(math.exp(-6), 4.0, 1.0, 1.0)\
273        *self._func(math.exp(-6), 4.0, 1.0, 2.0)   
274       
275        self.assertEqual(self.model.runXY([1.0,2.0]), value)
276       
277    def test2Dphi(self):
278        self.model.setParam('scale', math.exp(-6))
279        self.model.setParam('m', 4.0)
280        self.model.setParam('background', 1.0)
281       
282        x = 1.0
283        y = 2.0
284        r = math.sqrt(x**2 + y**2)
285        phi = math.atan2(y, x)
286       
287        value = self._func(math.exp(-6), 4.0, 1.0, x)\
288        *self._func(math.exp(-6), 4.0, 1.0, y)
289        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
290               
291class TestTeubnerStrey(unittest.TestCase):
292    """
293        Unit tests for PowerLaw function
294
295        F(x) = 1/( scale + c1*(x)^(2)+  c2*(x)^(4)) + bkd
296       
297        The model has Four parameters:
298            scale  =  scale factor
299            c1     =  constant
300            c2     =  constant
301            bkd    =  incoherent background
302    """
303    def _func(self, scale, c1, c2, bck, q):
304       
305        q2 = q*q;
306        q4 = q2*q2;
307   
308        return 1.0/(scale + c1*q2+c2*q4) + bck
309   
310    def setUp(self):
311        from sans.models.TeubnerStreyModel import TeubnerStreyModel
312        self.model= TeubnerStreyModel()
313       
314    def test1D(self):
315       
316        self.model.setParam('c1', -30.0) 
317        self.model.setParam('c2', 5000.0) 
318        self.model.setParam('scale', 0.1)
319        self.model.setParam('background', 0.1)
320        #self.assertEqual(1/(math.sqrt(4)), math.pow(4,-1/2))
321        #self.assertEqual(self.model.TeubnerStreyLengths(),False )
322       
323        self.assertEqual(self.model.run(0.0), 10.1)
324        self.assertEqual(self.model.run(2.0), self._func(0.1,-30.0,5000.0,0.1,2.0))
325       
326    def test2D(self):
327        self.model.setParam('c1', -30.0) 
328        self.model.setParam('c2', 5000.0) 
329        self.model.setParam('scale', 0.1)
330        self.model.setParam('background', 0.1)
331        value = self._func(0.1,-30.0,5000.0,0.1, 1.0)\
332        *self._func(0.1,-30.0,5000.0,0.1, 2.0)   
333       
334        self.assertEqual(self.model.runXY([1.0,2.0]), value)
335       
336    def test2Dphi(self):
337        self.model.setParam('c1', -30.0) 
338        self.model.setParam('c2', 5000.0) 
339        self.model.setParam('scale', 0.1)
340        self.model.setParam('background', 0.1)
341       
342        x = 1.0
343        y = 2.0
344        r = math.sqrt(x**2 + y**2)
345        phi = math.atan2(y, x)
346       
347        value = self._func(0.1,-30.0,5000.0,0.1, x)\
348        *self._func(0.1,-30.0,5000.0,0.1, y)
349        self.assertAlmostEquals(self.model.run([r, phi]), value,1)
350       
351class TestBEPolyelectrolyte(unittest.TestCase):
352    """
353        Unit tests for  BEPolyelectrolyte function
354       
355        F(x) = K*1/(4*pi()*Lb*(alpha)^(2)*(q^(2)+k2)/(1+(r02)^(2))*(q^(2)+k2)\
356                       *(q^(2)-(12*h*C/b^(2)))
357       
358        The model has Eight parameters:
359            K        =  Constrast factor of the polymer
360            Lb       =  Bjerrum length
361            H        =  virial parameter
362            B        =  monomer length
363            Cs       =  Concentration of monovalent salt
364            alpha    =  ionazation degree
365            C        = polymer molar concentration
366            bkd      = background
367    """
368    def _func(self, K, Lb, H, B, Cs, alpha, C, bkd, r02, k2,  x):
369        return (K /( (4*math.pi *Lb*(alpha**2)*(x**2 +k2)) *( (1 +(r02**2))  \
370                    *((x**2) + k2)*((x**2) -(12 * H * C/(B**2))) )))+ bkd
371   
372    def setUp(self):
373        from sans.models.BEPolyelectrolyte import BEPolyelectrolyte
374        self.model= BEPolyelectrolyte()
375       
376        self.K = 10.0
377        self.Lb = 6.5
378        self.h = 11
379        self.b = 13
380        self.Cs = 0.1
381        self.alpha = 0.05
382        self.= .7
383        self.Bkd =0.01
384       
385        self.model.setParam('K', self.K) 
386        self.model.setParam('Lb', self.Lb) 
387        self.model.setParam('H', self.h)
388        self.model.setParam('B', self.b)
389        self.model.setParam('Cs',self.Cs) 
390        self.model.setParam('alpha', self.alpha) 
391        self.model.setParam('C', self.C)
392        self.model.setParam('background', self.Bkd)
393       
394    def _func(self, q):
395       
396        Ca = self.C *6.022136e-4         
397        Csa = self.Cs * 6.022136e-4       
398        k2= 4*math.pi*self.Lb*(2*self.Cs+self.alpha*Ca)   
399
400        r02 = 1./self.alpha / Ca**0.5*( self.b / (48*math.pi*self.Lb)**0.5 )
401        q2 = q**2   
402        Sq = self.K*1./(4*math.pi*self.Lb*self.alpha**2) * (q2 + k2)  /  (1+(r02**2) * (q2+k2) * (q2- (12*self.h*Ca/self.b**2)) ) + self.Bkd
403        return Sq
404       
405    def test1D(self):
406       
407       
408        q = 0.001
409   
410        self.assertEqual(self.model.run(q), self._func(q))
411         
412    def test2D(self):
413        self.assertAlmostEquals(self.model.runXY([1.0,2.0]), self._func(1.0)*self._func(2.0), 8)
414       
415    def test2Dphi(self):
416
417        x = 1.0
418        y = 2.0
419        r = math.sqrt(x**2 + y**2)
420        phi = math.atan2(y, x)
421       
422        self.assertAlmostEquals(self.model.run([r, phi]), self._func(x)*self._func(y), 8)
423       
424class TestFractalModel(unittest.TestCase):
425    """
426        Unit tests for  Number Density Fractal function   
427        F(x)= P(x)*S(x) + bkd
428        The model has Seven parameters:
429            scale   =  Volume fraction
430            Radius  =  Block radius
431            Fdim    =  Fractal dimension
432            L       =  correlation Length
433            SDLB    =  SDL block
434            SDLS    =  SDL solvent
435            bkd     =  background
436    """
437    def setUp(self):
438        from sans.models.FractalModel import FractalModel
439        self.model= FractalModel()
440       
441    def test1D(self):
442        r0 = 5.0
443        sldp = 2.0e-6
444        sldm = 6.35e-6
445        phi = 0.05
446        Df = 2
447        corr = 100.0
448        bck = 1.0
449       
450        x = 0.001
451       
452        self.model.setParam('scale', phi) 
453        self.model.setParam('Radius', r0) 
454        self.model.setParam('fractal_dim',Df)
455        self.model.setParam('corr_length', corr)
456        self.model.setParam('block_sld', sldp) 
457        self.model.setParam('solvent_sld', sldm) 
458        self.model.setParam('background', bck)
459       
460        pq = 1.0e8*phi*4.0/3.0*math.pi*r0*r0*r0*(sldp-sldm)*(sldp-sldm)*math.pow((3*(math.sin(x*r0) - x*r0*math.cos(x*r0))/math.pow((x*r0),3)),2);
461       
462        sq = Df*math.exp(gammaln(Df-1.0))*math.sin((Df-1.0)*math.atan(x*corr));
463        sq /= math.pow((x*r0),Df) * math.pow((1.0 + 1.0/(x*corr)/(x*corr)),((Df-1.0)/2.0));
464        sq += 1.0;
465       
466        self.assertAlmostEqual(self.model._scatterRanDom(x),pq, 8 )
467       
468        self.assertEqual(self.model._Block(x),sq )
469       
470        self.assertEqual(self.model.run(x), pq*sq+bck)
471       
472if __name__ == '__main__':
473    unittest.main()
Note: See TracBrowser for help on using the repository browser.