source: sasview/Invariant/test/utest_data_handling.py @ 91db958

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 91db958 was 76c1727, checked in by Gervaise Alina <gervyh@…>, 15 years ago

a fix for smear invariant

  • Property mode set to 100644
File size: 20.5 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2010, University of Tennessee
9"""
10import unittest
11import numpy, math
12from DataLoader.loader import  Loader
13from DataLoader.data_info import Data1D
14from sans.invariant import invariant
15from DataLoader.qsmearing import smear_selection
16   
17class TestLinearFit(unittest.TestCase):
18    """
19        Test Line fit
20    """
21    def setUp(self):
22        x = numpy.asarray([1.,2.,3.,4.,5.,6.,7.,8.,9.])
23        y = numpy.asarray([1.,2.,3.,4.,5.,6.,7.,8.,9.])
24        dy = y/10.0
25       
26        self.data = Data1D(x=x,y=y,dy=dy)
27       
28    def test_fit_linear_data(self):
29        """
30            Simple linear fit
31        """
32       
33        # Create invariant object. Background and scale left as defaults.
34        fit = invariant.Extrapolator(data=self.data)
35        a,b = fit.fit()
36
37        # Test results
38        self.assertAlmostEquals(a, 1.0, 5)
39        self.assertAlmostEquals(b, 0.0, 5)
40
41    def test_fit_linear_data_with_noise(self):
42        """
43            Simple linear fit with noise
44        """
45        import random, math
46       
47        for i in range(len(self.data.y)):
48            self.data.y[i] = self.data.y[i]+.1*random.random()
49           
50        # Create invariant object. Background and scale left as defaults.
51        fit = invariant.Extrapolator(data=self.data)
52        a,b = fit.fit()
53
54        # Test results
55        self.assertTrue(math.fabs(a-1.0)<0.05)
56        self.assertTrue(math.fabs(b)<0.1)       
57   
58   
59class TestInvariantCalculator(unittest.TestCase):
60    """
61        Test Line fit
62    """
63    def setUp(self):
64        self.data = Loader().load("latex_smeared.xml")[0]
65       
66    def test_initial_data_processing(self):
67        """
68            Test whether the background and scale are handled properly
69            when creating an InvariantCalculator object
70        """
71        length = len(self.data.x)
72        self.assertEqual(length, len(self.data.y))
73        inv = invariant.InvariantCalculator(self.data)
74       
75        self.assertEqual(length, len(inv._data.x))
76        self.assertEqual(inv._data.x[0], self.data.x[0])
77
78        # Now the same thing with a background value
79        bck = 0.1
80        inv = invariant.InvariantCalculator(self.data, background=bck)
81        self.assertEqual(inv._background, bck)
82       
83        self.assertEqual(length, len(inv._data.x))
84        self.assertEqual(inv._data.y[0]+bck, self.data.y[0])
85       
86        # Now the same thing with a scale value
87        scale = 0.1
88        inv = invariant.InvariantCalculator(self.data, scale=scale)
89        self.assertEqual(inv._scale, scale)
90       
91        self.assertEqual(length, len(inv._data.x))
92        self.assertAlmostEqual(inv._data.y[0]/scale, self.data.y[0],7)
93       
94   
95    def test_incompatible_data_class(self):
96        """
97            Check that only classes that inherit from Data1D are allowed as data.
98        """
99        class Incompatible():
100            pass
101        self.assertRaises(ValueError, invariant.InvariantCalculator, Incompatible())
102   
103   
104class TestGuinierExtrapolation(unittest.TestCase):
105    """
106        Generate a Guinier distribution and verify that the extrapolation
107        produce the correct ditribution.
108    """
109   
110    def setUp(self):
111        """
112            Generate a Guinier distribution. After extrapolating, we will
113            verify that we obtain the scale and rg parameters
114        """
115        self.scale = 1.5
116        self.rg = 30.0
117        x = numpy.arange(0.0001, 0.1, 0.0001)
118        y = numpy.asarray([self.scale * math.exp( -(q*self.rg)**2 / 3.0 ) for q in x])
119        dy = y*.1
120        self.data = Data1D(x=x, y=y, dy=dy)
121       
122    def test_low_q(self):
123        """
124            Invariant with low-Q extrapolation
125        """
126        # Create invariant object. Background and scale left as defaults.
127        inv = invariant.InvariantCalculator(data=self.data)
128        # Set the extrapolation parameters for the low-Q range
129        inv.set_extrapolation(range='low', npts=20, function='guinier')
130       
131        self.assertEqual(inv._low_extrapolation_npts, 20)
132        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier)
133       
134        # Data boundaries for fiiting
135        qmin = inv._data.x[0]
136        qmax = inv._data.x[inv._low_extrapolation_npts - 1]
137       
138        # Extrapolate the low-Q data
139        a, b = inv._fit(model=inv._low_extrapolation_function,
140                          qmin=qmin,
141                          qmax=qmax,
142                          power=inv._low_extrapolation_power)
143        self.assertAlmostEqual(self.scale, a, 6)
144        self.assertAlmostEqual(self.rg, b, 6)
145   
146
147class TestPowerLawExtrapolation(unittest.TestCase):
148    """
149        Generate a power law distribution and verify that the extrapolation
150        produce the correct ditribution.
151    """
152   
153    def setUp(self):
154        """
155            Generate a power law distribution. After extrapolating, we will
156            verify that we obtain the scale and m parameters
157        """
158        self.scale = 1.5
159        self.m = 3.0
160        x = numpy.arange(0.0001, 0.1, 0.0001)
161        y = numpy.asarray([self.scale * math.pow(q ,-1.0*self.m) for q in x])               
162        dy = y*.1
163        self.data = Data1D(x=x, y=y, dy=dy)
164       
165    def test_low_q(self):
166        """
167            Invariant with low-Q extrapolation
168        """
169        # Create invariant object. Background and scale left as defaults.
170        inv = invariant.InvariantCalculator(data=self.data)
171        # Set the extrapolation parameters for the low-Q range
172        inv.set_extrapolation(range='low', npts=20, function='power_law')
173       
174        self.assertEqual(inv._low_extrapolation_npts, 20)
175        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.PowerLaw)
176       
177        # Data boundaries for fitting
178        qmin = inv._data.x[0]
179        qmax = inv._data.x[inv._low_extrapolation_npts - 1]
180       
181        # Extrapolate the low-Q data
182        a, b = inv._fit(model=inv._low_extrapolation_function,
183                          qmin=qmin,
184                          qmax=qmax,
185                          power=inv._low_extrapolation_power)
186       
187        self.assertAlmostEqual(self.scale, a, 6)
188        self.assertAlmostEqual(self.m, b, 6)
189       
190class TestLinearization(unittest.TestCase):
191   
192    def test_guinier_incompatible_length(self):
193        g = invariant.Guinier()
194        data_in = Data1D(x=[1], y=[1,2], dy=None)
195        self.assertRaises(AssertionError, g.linearize_data, data_in)
196        data_in = Data1D(x=[1,1], y=[1,2], dy=[1])
197        self.assertRaises(AssertionError, g.linearize_data, data_in)
198   
199    def test_linearization(self):
200        """
201            Check that the linearization process filters out points
202            that can't be transformed
203        """
204        x = numpy.asarray(numpy.asarray([0,1,2,3]))
205        y = numpy.asarray(numpy.asarray([1,1,1,1]))
206        g = invariant.Guinier()
207        data_in = Data1D(x=x, y=y)
208        data_out = g.linearize_data(data_in)
209        x_out, y_out, dy_out = data_out.x, data_out.y, data_out.dy
210        self.assertEqual(len(x_out), 3)
211        self.assertEqual(len(y_out), 3)
212        self.assertEqual(len(dy_out), 3)
213
214   
215class TestDataExtraLow(unittest.TestCase):
216    """
217        Generate a Guinier distribution and verify that the extrapolation
218        produce the correct ditribution. Tested if the data generated by the
219        invariant calculator is correct
220    """
221   
222    def setUp(self):
223        """
224            Generate a Guinier distribution. After extrapolating, we will
225            verify that we obtain the scale and rg parameters
226        """
227        self.scale = 1.5
228        self.rg = 30.0
229        x = numpy.arange(0.0001, 0.1, 0.0001)
230        y = numpy.asarray([self.scale * math.exp( -(q*self.rg)**2 / 3.0 ) for q in x])
231        dy = y*.1
232        self.data = Data1D(x=x, y=y, dy=dy)
233       
234    def test_low_q(self):
235        """
236            Invariant with low-Q extrapolation with no slit smear
237        """
238        # Create invariant object. Background and scale left as defaults.
239        inv = invariant.InvariantCalculator(data=self.data)
240        # Set the extrapolation parameters for the low-Q range
241        inv.set_extrapolation(range='low', npts=20, function='guinier')
242       
243        self.assertEqual(inv._low_extrapolation_npts, 20)
244        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier)
245       
246        # Data boundaries for fiiting
247        qmin = inv._data.x[0]
248        qmax = inv._data.x[inv._low_extrapolation_npts - 1]
249       
250        # Extrapolate the low-Q data
251        a, b = inv._fit(model=inv._low_extrapolation_function,
252                          qmin=qmin,
253                          qmax=qmax,
254                          power=inv._low_extrapolation_power)
255        self.assertAlmostEqual(self.scale, a, 6)
256        self.assertAlmostEqual(self.rg, b, 6)
257       
258        qstar = inv.get_qstar(extrapolation='low')
259        reel_y = self.data.y
260        test_y = inv._low_extrapolation_function.evaluate_model(x=self.data.x)
261        for i in range(len(self.data.x)):
262            value  = math.fabs(test_y[i]-reel_y[i])/reel_y[i]
263            self.assert_(value < 0.001)
264           
265class TestDataExtraLowSlit(unittest.TestCase):
266    """
267        for a smear data, test that the fitting go through
268        reel data for the 2 first points
269    """
270    def setUp(self):
271        """
272           Reel data containing slit smear information
273           .Use 2 points of data to fit with power_law when exptrapolating
274        """
275        list = Loader().load("latex_smeared.xml")
276        self.data = list[0]
277        self.data.dxl = list[0].dxl
278        self.data.dxw = list[0].dxw
279        self.npts = 2
280       
281    def test_low_q(self):
282        """
283            Invariant with low-Q extrapolation with slit smear
284        """
285        # Create invariant object. Background and scale left as defaults.
286        inv = invariant.InvariantCalculator(data=self.data)
287        # Set the extrapolation parameters for the low-Q range
288        inv.set_extrapolation(range='low', npts=self.npts, function='power_law')
289       
290        self.assertEqual(inv._low_extrapolation_npts, self.npts)
291        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.PowerLaw)
292       
293        # Data boundaries for fiiting
294        qmin = inv._data.x[0]
295        qmax = inv._data.x[inv._low_extrapolation_npts - 1]
296       
297        # Extrapolate the low-Q data
298        a, b = inv._fit(model=inv._low_extrapolation_function,
299                          qmin=qmin,
300                          qmax=qmax,
301                          power=inv._low_extrapolation_power)
302     
303        qstar = inv.get_qstar(extrapolation='low')
304        reel_y = self.data.y
305        #Compution the y 's coming out of the invariant when computing extrapolated
306        #low data . expect the fit engine to have been already called and the guinier
307        # to have the radius and the scale fitted
308        test_y = inv._low_extrapolation_function.evaluate_model(x=self.data.x[:inv._low_extrapolation_npts])
309        #Check any points generated from the reel data and the extrapolation have
310        #very close value
311        self.assert_(len(test_y))== len(reel_y[:inv._low_extrapolation_npts])
312        for i in range(inv._low_extrapolation_npts):
313            value  = math.fabs(test_y[i]-reel_y[i])/reel_y[i]
314            self.assert_(value < 0.001)
315        data_out_range, data_in_range= inv.get_extra_data_low(npts_in=None)
316           
317class TestDataExtraLowSlitGuinier(unittest.TestCase):
318    """
319        for a smear data, test that the fitting go through
320        reel data for atleast the 2 first points
321    """
322   
323    def setUp(self):
324        """
325            Generate a Guinier distribution. After extrapolating, we will
326            verify that we obtain the scale and rg parameters
327        """
328        self.scale = 1.5
329        self.rg = 30.0
330        x = numpy.arange(0.0001, 0.1, 0.0001)
331        y = numpy.asarray([self.scale * math.exp( -(q*self.rg)**2 / 3.0 ) for q in x])
332        dy = y*.1
333        dxl = 0.117 * numpy.ones(len(x))
334        self.data = Data1D(x=x, y=y, dy=dy)
335        self.data.dxl = dxl
336        self.npts = len(x)-10
337       
338    def test_low_q(self):
339        """
340            Invariant with low-Q extrapolation with slit smear
341        """
342        # Create invariant object. Background and scale left as defaults.
343        inv = invariant.InvariantCalculator(data=self.data)
344        # Set the extrapolation parameters for the low-Q range
345        inv.set_extrapolation(range='low', npts=self.npts, function='guinier')
346       
347        self.assertEqual(inv._low_extrapolation_npts, self.npts)
348        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier)
349       
350        # Data boundaries for fiiting
351        qmin = inv._data.x[0]
352        qmax = inv._data.x[inv._low_extrapolation_npts - 1]
353       
354        # Extrapolate the low-Q data
355        a, b = inv._fit(model=inv._low_extrapolation_function,
356                          qmin=qmin,
357                          qmax=qmax,
358                          power=inv._low_extrapolation_power)
359     
360       
361        qstar = inv.get_qstar(extrapolation='low')
362        reel_y = self.data.y
363        #Compution the y 's coming out of the invariant when computing extrapolated
364        #low data . expect the fit engine to have been already called and the guinier
365        # to have the radius and the scale fitted
366        test_y = inv._low_extrapolation_function.evaluate_model(x=self.data.x[:inv._low_extrapolation_npts])
367        self.assert_(len(test_y))== len(reel_y[:inv._low_extrapolation_npts])
368       
369        for i in range(inv._low_extrapolation_npts):
370            value  = math.fabs(test_y[i]-reel_y[i])/reel_y[i]
371            self.assert_(value < 0.001)
372           
373    def test_low_data(self):
374        """
375            Invariant with low-Q extrapolation with slit smear
376        """
377        # Create invariant object. Background and scale left as defaults.
378        inv = invariant.InvariantCalculator(data=self.data)
379        # Set the extrapolation parameters for the low-Q range
380        inv.set_extrapolation(range='low', npts=self.npts, function='guinier')
381       
382        self.assertEqual(inv._low_extrapolation_npts, self.npts)
383        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier)
384       
385        # Data boundaries for fiiting
386        qmin = inv._data.x[0]
387        qmax = inv._data.x[inv._low_extrapolation_npts - 1]
388       
389        # Extrapolate the low-Q data
390        a, b = inv._fit(model=inv._low_extrapolation_function,
391                          qmin=qmin,
392                          qmax=qmax,
393                          power=inv._low_extrapolation_power)
394     
395       
396        qstar = inv.get_qstar(extrapolation='low')
397        reel_y = self.data.y
398        #Compution the y 's coming out of the invariant when computing extrapolated
399        #low data . expect the fit engine to have been already called and the guinier
400        # to have the radius and the scale fitted
401        data_out_range, data_in_range= inv.get_extra_data_low() 
402        test_y = data_in_range.y
403        self.assert_(len(test_y))== len(reel_y[:inv._low_extrapolation_npts])
404        for i in range(inv._low_extrapolation_npts):
405            value  = math.fabs(test_y[i]-reel_y[i])/reel_y[i]
406            self.assert_(value < 0.001)   
407                   
408        data_out_range, data_in_range= inv.get_extra_data_low(npts_in= 2, nsteps=10,
409                                                               q_start= 1e-4) 
410        test_y = data_in_range.y
411        self.assert_(len(test_y))== len(reel_y[:2])
412        for i in range(2):
413            value  = math.fabs(test_y[i]-reel_y[i])/reel_y[i]
414            self.assert_(value < 0.001) 
415        #test the data out of range         
416        test_out_y = data_out_range.y
417        self.assertEqual(len(test_out_y), 10)             
418           
419class TestDataExtraHighSlitPowerLaw(unittest.TestCase):
420    """
421        for a smear data, test that the fitting go through
422        reel data for atleast the 2 first points
423    """
424   
425    def setUp(self):
426        """
427            Generate a Guinier distribution. After extrapolating, we will
428            verify that we obtain the scale and rg parameters
429        """
430        self.scale = 1.5
431        self.m = 3.0
432        x = numpy.arange(0.0001, 0.1, 0.0001)
433        y = numpy.asarray([self.scale * math.pow(q ,-1.0*self.m) for q in x])               
434        dy = y*.1
435        self.data = Data1D(x=x, y=y, dy=dy)
436        dxl = 0.117 * numpy.ones(len(x))
437        self.data.dxl = dxl
438        self.npts = 20
439       
440    def test_high_q(self):
441        """
442            Invariant with high-Q extrapolation with slit smear
443        """
444        # Create invariant object. Background and scale left as defaults.
445        inv = invariant.InvariantCalculator(data=self.data)
446        # Set the extrapolation parameters for the low-Q range
447        inv.set_extrapolation(range='high', npts=self.npts, function='power_law')
448       
449        self.assertEqual(inv._high_extrapolation_npts, self.npts)
450        self.assertEqual(inv._high_extrapolation_function.__class__, invariant.PowerLaw)
451       
452        # Data boundaries for fiiting
453        xlen = len(self.data.x)
454        start =  xlen - inv._high_extrapolation_npts
455        qmin = inv._data.x[start]
456        qmax = inv._data.x[xlen-1]
457       
458        # Extrapolate the high-Q data
459        a, b = inv._fit(model=inv._high_extrapolation_function,
460                          qmin=qmin,
461                          qmax=qmax,
462                          power=inv._high_extrapolation_power)
463     
464       
465        qstar = inv.get_qstar(extrapolation='high')
466        reel_y = self.data.y
467        #Compution the y 's coming out of the invariant when computing extrapolated
468        #low data . expect the fit engine to have been already called and the power law
469        # to have the radius and the scale fitted
470       
471       
472        test_y = inv._high_extrapolation_function.evaluate_model(x=self.data.x[start: ])
473        self.assert_(len(test_y))== len(reel_y[start:])
474       
475        for i in range(len(self.data.x[start:])):
476            value  = math.fabs(test_y[i]-reel_y[start+i])/reel_y[start+i]
477            self.assert_(value < 0.001)
478           
479    def test_high_data(self):
480        """
481            Invariant with low-Q extrapolation with slit smear
482        """
483        # Create invariant object. Background and scale left as defaults.
484        inv = invariant.InvariantCalculator(data=self.data)
485        # Set the extrapolation parameters for the low-Q range
486        inv.set_extrapolation(range='high', npts=self.npts, function='power_law')
487       
488        self.assertEqual(inv._high_extrapolation_npts, self.npts)
489        self.assertEqual(inv._high_extrapolation_function.__class__, invariant.PowerLaw)
490       
491        # Data boundaries for fiiting
492        xlen = len(self.data.x)
493        start =  xlen - inv._high_extrapolation_npts
494        qmin = inv._data.x[start]
495        qmax = inv._data.x[xlen-1]
496       
497        # Extrapolate the high-Q data
498        a, b = inv._fit(model=inv._high_extrapolation_function,
499                          qmin=qmin,
500                          qmax=qmax,
501                          power=inv._high_extrapolation_power)
502     
503       
504        qstar = inv.get_qstar(extrapolation='high')
505        reel_y = self.data.y
506        #Compution the y 's coming out of the invariant when computing extrapolated
507        #low data . expect the fit engine to have been already called and the power law
508        # to have the radius and the scale fitted
509       
510        data_out_range, data_in_range= inv.get_extra_data_high() 
511        test_y = data_in_range.y
512        self.assert_(len(test_y))== len(reel_y[start:])
513        temp = reel_y[start:]
514       
515        for i in range(len(self.data.x[start:])):
516            value  = math.fabs(test_y[i]- temp[i])/temp[i]
517            self.assert_(value < 0.001)   
518                   
519        data_out_range, data_in_range= inv.get_extra_data_high(npts_in=5, nsteps=10,
520                                                               q_end= 2) 
521        test_y = data_in_range.y
522        self.assert_(len(test_y)==5)
523        temp = reel_y[start:start+5]
524       
525        for i in range(len(self.data.x[start:start+5])):
526         
527            value  = math.fabs(test_y[i]- temp[i])/temp[i]
528            self.assert_(value < 0.06)   
529        #test the data out of range         
530        test_out_y = data_out_range.y
531        self.assertEqual(len(test_out_y), 10)             
532                     
Note: See TracBrowser for help on using the repository browser.