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
RevLine 
[46d50ca]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
[6939bd4]11import numpy, math
[46d50ca]12from DataLoader.loader import  Loader
13from DataLoader.data_info import Data1D
14from sans.invariant import invariant
[97603c0]15from DataLoader.qsmearing import smear_selection
[46d50ca]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.
[aafa962]34        fit = invariant.Extrapolator(data=self.data)
[46d50ca]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.
[aafa962]51        fit = invariant.Extrapolator(data=self.data)
[46d50ca]52        a,b = fit.fit()
53
54        # Test results
55        self.assertTrue(math.fabs(a-1.0)<0.05)
[6939bd4]56        self.assertTrue(math.fabs(b)<0.1)       
[46d50ca]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   
[6939bd4]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
[aafa962]116        self.rg = 30.0
[6939bd4]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)
[aafa962]132        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier)
[6939bd4]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
[aafa962]139        a, b = inv._fit(model=inv._low_extrapolation_function,
[6939bd4]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)
[aafa962]175        self.assertEqual(inv._low_extrapolation_function.__class__, invariant.PowerLaw)
[6939bd4]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
[aafa962]182        a, b = inv._fit(model=inv._low_extrapolation_function,
[6939bd4]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)
[aafa962]189       
190class TestLinearization(unittest.TestCase):
191   
192    def test_guinier_incompatible_length(self):
193        g = invariant.Guinier()
[76c1727]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)
[aafa962]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()
[76c1727]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
[aafa962]210        self.assertEqual(len(x_out), 3)
211        self.assertEqual(len(y_out), 3)
212        self.assertEqual(len(dy_out), 3)
[97603c0]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    """
[76c1727]267        for a smear data, test that the fitting go through
268        reel data for the 2 first points
[97603c0]269    """
270    def setUp(self):
271        """
[76c1727]272           Reel data containing slit smear information
273           .Use 2 points of data to fit with power_law when exptrapolating
[97603c0]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
[76c1727]279        self.npts = 2
[97603c0]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
[76c1727]288        inv.set_extrapolation(range='low', npts=self.npts, function='power_law')
[97603c0]289       
[76c1727]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)
[97603c0]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
[76c1727]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])
[97603c0]368       
[76c1727]369        for i in range(inv._low_extrapolation_npts):
[97603c0]370            value  = math.fabs(test_y[i]-reel_y[i])/reel_y[i]
371            self.assert_(value < 0.001)
372           
[76c1727]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)             
[97603c0]418           
[76c1727]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)   
[97603c0]518                   
[76c1727]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.