source: sasview/test/sasrealspace/test/utest_realspace.py @ 88d2e70

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1249
Last change on this file since 88d2e70 was 88d2e70, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

support for py37 in unit tests

  • Property mode set to 100644
File size: 12.4 KB
Line 
1"""
2    Unit tests for specific models
3    @author: Mathieu Doucet / UTK
4"""
5from __future__ import print_function
6
7import unittest, math, time
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
16from sasmodels.sasview_model import _make_standard_model
17EllipsoidModel = _make_standard_model('ellipsoid')
18SphereModel = _make_standard_model('sphere')
19CylinderModel = _make_standard_model('cylinder')
20CoreShellModel = _make_standard_model('core_shell_sphere')
21
22import sas.sascalc.realspace.VolumeCanvas as VolumeCanvas
23
24class TestRealSpaceModel(unittest.TestCase):
25    """ Unit tests for sphere model """
26
27    def setUp(self):
28        self.model = VolumeCanvas.VolumeCanvas()
29        self.model.add('cylinder', 'cyl')
30        self.model.add('sphere', 'sph')
31        self.model.add('ellipsoid', 'elli')
32        self.model.add('singlehelix', 'shelix')
33
34    def testAdding(self):
35        self.assertEqual('cyl', self.model.add('cylinder', 'cyl'))
36
37    def testDeleting(self):
38        self.model.add('ellipsoid','elli2')
39        self.model.delete('elli2')
40        self.assertTrue('elli2' not in self.model.getShapeList())
41
42    def testsetParam(self):
43        self.model.setParam('q_max', 0.2)
44        self.model.setParam('shelix.radius_helix', 12)
45
46    def testgetParamList(self):
47        #print self.model.getParamList()
48        #print self.model.getParamList('shelix')
49        pass
50
51    def testPr_Iq(self):
52        self.model.getPr()
53        #print "pr is calculated", self.model.hasPr
54        result = self.model.getIq(0.1)
55        #print "I(0.1) is calculated: ", result
56
57class TestSphere(unittest.TestCase):
58    """ Unit tests for sphere model """
59
60    def setUp(self):
61        self.canvas = VolumeCanvas.VolumeCanvas()
62
63
64    def testSetQmax(self):
65        old_value = self.canvas.getParam('q_max')
66        new_value = old_value + 0.1
67        self.canvas.setParam('q_max', new_value)
68        self.assertEqual(self.canvas.getParam("Q_MAx"), new_value)
69
70    def testSetDensity(self):
71        self.canvas.setParam('lores_density', 0.1)
72        handle = self.canvas.add('sphere')
73        self.canvas.setParam("%s.radius" % handle, 5.0)
74        vol = 4/3*math.pi*5*5*5
75        npts_1 = vol/0.1
76        value_1 = self.canvas.getIq(0.001)
77
78        # Change density, the answer should be the same
79        self.canvas.setParam('lores_density', 0.2)
80        npts_2 = vol/0.2
81        value_2 = self.canvas.getIq(0.001)
82
83        self.assertTrue( (value_1-value_2)/value_1 < 0.1)
84
85    def testSetDensityTiming(self):
86        """Testing change in computation time with density"""
87        handle = self.canvas.add('sphere')
88        self.canvas.setParam("%s.radius" % handle, 15.0)
89
90        self.canvas.setParam('lores_density', 0.6)
91        t_0 = time.time()
92        self.canvas.getIq(0.001)
93        t_1 = time.time()-t_0
94
95        # Change density, the answer should be the same
96        self.canvas.setParam('lores_density', 0.1)
97        t_0 = time.time()
98        self.canvas.getIq(0.001)
99        t_2 = time.time()-t_0
100
101        self.assertTrue( t_2 < t_1 and (t_1-t_2)/t_2 > 2)
102
103    def testGetParamList(self):
104        """ Test GetParamList on empty canvas"""
105        self.assertTrue('lores_density' in self.canvas.getParamList())
106        handle = self.canvas.add('sphere')
107
108    def testGetParamListWithShape(self):
109        """ Test GetParamList on filled canvas"""
110        self.canvas.add('sphere')
111        self.assertTrue('lores_density' in self.canvas.getParamList())
112
113    def testAdd(self):
114        handle = "s1"
115        self.assertEqual(handle, self.canvas.add('sphere', handle))
116
117        #TODO: test for current list of shape
118        self.assertEqual( [handle] , self.canvas.getShapeList())
119
120    def testSetRadius(self):
121        handle = self.canvas.add('sphere')
122        self.canvas.setParam("%s.radius" % handle, 24.0)
123        self.assertEqual(self.canvas.getParam("%s.radius" % handle), 24.0)
124
125    def testGetIq(self):
126        """ Test the output of I(q) to the analytical solution
127            If the normalization is wrong, we will have to fix it.
128
129            getIq() should call getPr() behind the scenes so that
130            the user doesnt have to do it if he doesn't need to.
131        """
132        sphere = SphereModel()
133        sphere.setParam('scale', 1.0)
134        sphere.setParam('background', 0.0)
135        sphere.setParam('sld', 1.0)
136        sphere.setParam('sld_solvent', 0.0)
137        sphere.setParam('radius', 10.0)
138
139        handle = self.canvas.add('sphere')
140        self.canvas.setParam('%s.radius' % handle, 10.0)
141        self.canvas.setParam('%s.contrast' % handle, 1.0)
142
143
144        sim_1 = self.canvas.getIq(0.001)
145        ana_1 = sphere.run(0.001)
146        sim_2 = self.canvas.getIq(0.01)
147        ana_2 = sphere.run(0.01)
148
149        # test the shape of the curve (calculate relative error
150        # on the output and it should be compatible with zero
151        # THIS WILL DEPEND ON THE NUMBER OF SPACE POINTS:
152        # that why we need some error analysis.
153        self.assertTrue( (sim_2*ana_1/sim_1 - ana_2)/ana_2 < 0.1)
154
155        # test the absolute amplitude
156        self.assertTrue( math.fabs(sim_2-ana_2)/ana_2 < 0.1)
157
158    def testGetIq2(self):
159        """ Test two different q values
160        """
161        handle = self.canvas.add('sphere')
162        self.canvas.setParam('%s.radius' % handle, 10.0)
163
164        sim_1 = self.canvas.getIq(0.001)
165        sim_2 = self.canvas.getIq(0.01)
166
167        self.assertNotAlmostEqual(sim_2, sim_1, 3)
168
169    def testGetIq_Identical(self):
170        """ Test for identical model / no param change
171        """
172        handle = self.canvas.add('sphere')
173        self.canvas.setParam('%s.radius' % handle, 10.0)
174
175        sim_1 = self.canvas.getIq(0.01)
176        sim_2 = self.canvas.getIq(0.01)
177
178        self.assertEqual(sim_2, sim_1)
179
180    def testGetIq_Identical2(self):
181        """ Test for identical model after a parameter change
182            Should be different only of the space points
183            are regenerated and the random seed is different
184        """
185        handle = self.canvas.add('sphere')
186        self.canvas.setParam('%s.radius' % handle, 10.0)
187
188        self.canvas.setParam('lores_density', 0.1)
189        sim_1 = self.canvas.getIq(0.01)
190
191        # Try to fool the code by changing to a different value
192        self.canvas.setParam('lores_density', 0.2)
193        self.canvas.getIq(0.01)
194
195        self.canvas.setParam('lores_density', 0.1)
196        sim_2 = self.canvas.getIq(0.01)
197
198        self.assertTrue((sim_2-sim_1)/sim_1<0.05)
199
200    def testGetIq_time(self):
201        """ Time profile
202        """
203        handle = self.canvas.add('sphere')
204        self.canvas.setParam('%s.radius' % handle, 15.0)
205
206
207        self.canvas.setParam('lores_density', 0.1)
208        t_0 = time.time()
209        sim_1 = self.canvas.getIq(0.01)
210        delta_1 = time.time()-t_0
211
212        self.canvas.setParam('lores_density', 0.1)
213
214        t_0 = time.time()
215        sim_2 = self.canvas.getIq(0.01)
216        delta_2 = time.time()-t_0
217
218        self.assertTrue((delta_2-delta_1)/delta_1<0.05)
219
220
221    def testGetPr(self):
222        """Compare the output of P(r) to the theoretical value"""
223        #TODO: find a way to compare you P(r) to the known
224        # analytical value.
225        pass
226
227    def testLogic1(self):
228        """ Test that the internal logic is set so that the user
229            get the right output after changing a parameter
230        """
231
232        handle = self.canvas.add('sphere')
233        self.canvas.setParam('%s.radius' % handle, 10.0)
234        result_1 = self.canvas.getIq(0.1)
235        self.canvas.setParam('%s.radius' % handle, 20.0)
236        result_2 = self.canvas.getIq(0.1)
237        self.assertNotAlmostEqual(result_1, result_2, 2)
238
239class TestCanvas(unittest.TestCase):
240    """ Unit tests for all shapes in canvas model """
241
242    def setUp(self):
243        self.canvas = VolumeCanvas.VolumeCanvas()
244        self.canvas.params['lores_density'] = 0.05
245
246    def testGetIq_cylinder(self):
247        handle = self.canvas.add('cylinder','cyl')
248        self.canvas.setParam('%s.radius' % handle, 15.0)
249        self.canvas.setParam('%s.length' % handle, 50.0)
250        self.assertEqual(50,self.canvas.getParam('%s.length'%handle))
251        result_1 = self.canvas.getIq(0.1)
252        result_2 = self.canvas.getIq(0.1)
253        self.assertEqual(result_1,result_2)
254
255        self.canvas.delete(handle)
256        handle2 = self.canvas.add('cylinder','cyl2')
257        self.assertEqual(40,self.canvas.getParam('%s.length'%handle2))
258        result_3 = self.canvas.getIq(0.1)
259        self.assertNotEqual(result_1, result_3)
260
261    def testGetIq_ellipsoid(self):
262        handle = self.canvas.add('ellipsoid','elli')
263        self.canvas.setParam('%s.radius_x' % handle, 35)
264        self.canvas.setParam('%s.radius_y' % handle, 20)
265        self.canvas.setParam('%s.radius_z' % handle, 10)
266        result_1 = self.canvas.getIq(0.1)
267        result_2 = self.canvas.getIq(0.1)
268        self.assertEqual(result_1,result_2)
269
270        self.canvas.delete(handle)
271        self.assertEqual(False,self.canvas.hasPr)
272        handle2 = self.canvas.add('ellipsoid','elli2')
273        result_3 = self.canvas.getIq(0.1)
274        self.assertNotEqual(result_1, result_3)
275
276    def testGetIq_singlehelix(self):
277        handle = self.canvas.add('singlehelix','shelix')
278        self.canvas.setParam('%s.radius_helix' % handle, 11)
279        self.canvas.setParam('%s.radius_tube' % handle, 4)
280        self.canvas.setParam('%s.pitch' % handle, 30)
281        self.canvas.setParam('%s.turns' % handle, 3.2)
282        result_1 = self.canvas.getIq(0.1)
283        result_2 = self.canvas.getIq(0.1)
284        self.assertEqual(result_1,result_2)
285
286        self.canvas.delete(handle)
287        self.assertEqual(False,self.canvas.hasPr)
288        handle2 = self.canvas.add('singlehelix','shelix2')
289        result_3 = self.canvas.getIq(0.1)
290        self.assertNotEqual(result_1, result_3)
291
292class TestOrdering(unittest.TestCase):
293    """ Unit tests for all shapes in canvas model """
294
295    def setUp(self):
296        radius = 15
297        thickness = 5
298        core_vol = 4.0/3.0*math.pi*radius*radius*radius
299        outer_radius = radius+thickness
300        shell_vol = 4.0/3.0*math.pi*outer_radius*outer_radius*outer_radius - core_vol
301        self.shell_sld = -1.0*core_vol/shell_vol
302
303        self.canvas = VolumeCanvas.VolumeCanvas()
304        self.canvas.params['lores_density'] = 0.1
305
306        # Core shell model
307        sphere = CoreShellModel()
308        sphere.setParam('scale', 1.0)
309        sphere.setParam('background', 0.0)
310        sphere.setParam('sld_core', 1.0)
311        sphere.setParam('sld_shell', self.shell_sld)
312        sphere.setParam('sld_solvent', 0.0)
313        # Core radius
314        sphere.setParam('radius', radius)
315        # Shell thickness
316        sphere.setParam('thickness', thickness)
317        self.sphere = sphere
318        self.radius = radius
319        self.outer_radius = outer_radius
320
321    def set_coreshell_on_canvas(self, order1=None, order2=None):
322
323        handle = self.canvas.add('sphere')
324        self.canvas.setParam('scale' , 1.0)
325        self.canvas.setParam('background' , 0.0)
326
327        self.canvas.setParam('%s.radius' % handle, self.outer_radius)
328        self.canvas.setParam('%s.contrast' % handle, self.shell_sld)
329        if order1 is not None:
330            self.canvas.setParam('%s.order' % handle, order1)
331
332        handle2 = self.canvas.add('sphere')
333        self.canvas.setParam('%s.radius' % handle2, self.radius)
334        self.canvas.setParam('%s.contrast' % handle2, 1.0)
335        if order2 is not None:
336            self.canvas.setParam('%s.order' % handle2, order2)
337
338
339    def testDefaultOrder(self):
340        self.set_coreshell_on_canvas()
341
342        ana = self.sphere.run(0.05)
343        val, err = self.canvas.getIqError(0.05)
344        self.assertTrue(math.fabs(ana-val)<2.0*err)
345
346    def testRightOrder(self):
347        self.set_coreshell_on_canvas(3.0, 6.0)
348
349        ana = self.sphere.run(0.05)
350        val, err = self.canvas.getIqError(0.05)
351        #print 'right', ana, val, err
352        self.assertTrue(math.fabs(ana-val)/ana < 1.1)
353
354    def testWrongOrder(self):
355        self.set_coreshell_on_canvas(1, 0)
356
357        sphere = SphereModel()
358        sphere.setParam('scale', 1.0)
359        sphere.setParam('background', 0.0)
360        sphere.setParam('radius', self.outer_radius)
361        sphere.setParam('sld', self.shell_sld)
362        sphere.setParam('sld_solvent', 0.0)
363
364        ana = sphere.run(0.05)
365        val, err = self.canvas.getIqError(0.05)
366        #print 'wrong', ana, val, err
367        self.assertTrue(math.fabs(ana-val)/ana < 1.1)
368
369
370if __name__ == '__main__':
371    unittest.main()
Note: See TracBrowser for help on using the repository browser.