source: sasview/sansmodels/test/utest_nonshape.py @ e173956

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 e173956 was f1e0c1eb, checked in by Kieran Campbell <kieranrcampbell@…>, 12 years ago

Added basic unit tests for star polymer model

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