source: sasview/pr_inversion/test/utest_invertor.py @ 34ae302

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

Added P(r) fit test

  • Property mode set to 100644
File size: 8.0 KB
Line 
1"""
2    Unit tests for Invertor class
3"""
4# Disable "missing docstring" complaint
5# pylint: disable-msg=C0111
6# Disable "too many methods" complaint
7# pylint: disable-msg=R0904
8
9
10import unittest, math, numpy, pylab
11from sans.pr.invertor import Invertor
12       
13class TestBasicComponent(unittest.TestCase):
14   
15    def setUp(self):
16        self.invertor = Invertor()
17        self.invertor.d_max = 100.0
18       
19        # Test array
20        self.ntest = 5
21        self.x_in = numpy.ones(self.ntest)
22        for i in range(self.ntest):
23            self.x_in[i] = 1.0*(i+1)
24
25
26    def testset_dmax(self):
27        """
28            Set and read d_max
29        """
30        value = 15.0
31        self.invertor.d_max = value
32        self.assertEqual(self.invertor.d_max, value)
33       
34    def testset_alpha(self):
35        """
36            Set and read alpha
37        """
38        value = 15.0
39        self.invertor.alpha = value
40        self.assertEqual(self.invertor.alpha, value)
41       
42    def testset_x_1(self):
43        """
44            Setting and reading the x array the hard way
45        """
46        # Set x
47        self.invertor.x = self.x_in
48       
49        # Read it back
50        npts = self.invertor.get_nx()
51        x_out = numpy.ones(npts)
52       
53        self.invertor.get_x(x_out)
54
55        for i in range(self.ntest):
56            self.assertEqual(self.x_in[i], x_out[i])
57           
58    def testset_x_2(self):
59        """
60            Setting and reading the x array the easy way
61        """
62        # Set x
63        self.invertor.x = self.x_in
64       
65        # Read it back
66        x_out = self.invertor.x
67       
68        for i in range(self.ntest):
69            self.assertEqual(self.x_in[i], x_out[i])
70       
71    def testset_y(self):
72        """
73            Setting and reading the y array the easy way
74        """
75        # Set y
76        self.invertor.y = self.x_in
77       
78        # Read it back
79        y_out = self.invertor.y
80       
81        for i in range(self.ntest):
82            self.assertEqual(self.x_in[i], y_out[i])
83       
84    def testset_err(self):
85        """
86            Setting and reading the err array the easy way
87        """
88        # Set err
89        self.invertor.err = self.x_in
90       
91        # Read it back
92        err_out = self.invertor.err
93       
94        for i in range(self.ntest):
95            self.assertEqual(self.x_in[i], err_out[i])
96       
97    def test_iq(self):
98        """
99            Test iq calculation
100        """
101        q = 0.11
102        v1 = 8.0*math.pi**2/q * self.invertor.d_max *math.sin(q*self.invertor.d_max)
103        v1 /= ( math.pi**2 - (q*self.invertor.d_max)**2.0 )
104       
105        pars = numpy.ones(1)
106        self.assertAlmostEqual(self.invertor.iq(pars, q), v1, 2)
107       
108    def test_pr(self):
109        """
110            Test pr calculation
111        """
112        r = 10.0
113        v1 = 2.0*r*math.sin(math.pi*r/self.invertor.d_max)
114        pars = numpy.ones(1)
115        self.assertAlmostEqual(self.invertor.pr(pars, r), v1, 2)
116       
117    def test_getsetters(self):
118        self.invertor.new_data = 1.0
119        self.assertEqual(self.invertor.new_data, 1.0)
120       
121        self.assertEqual(self.invertor.test_no_data, None)
122       
123    def test_inversion(self):
124        """
125            Test an inversion for which we know the answer
126        """
127        x, y, err = load("sphere_80.txt")
128
129        # Choose the right d_max...
130        self.invertor.d_max = 160.0
131        # Set a small alpha
132        self.invertor.alpha = 1e-7
133        # Set data
134        self.invertor.x   = x
135        self.invertor.y   = y
136        self.invertor.err = err
137        # Perform inversion
138        out, cov = self.invertor.invert(10)
139        # This is a very specific case
140        # We should make sure it always passes
141        self.assertTrue(self.invertor.chi2/len(x)<200.00)
142       
143        # Check the computed P(r) with the theory
144        # for shpere of radius 80
145        x = pylab.arange(0.01, self.invertor.d_max, self.invertor.d_max/51.0)
146        y = numpy.zeros(len(x))
147        dy = numpy.zeros(len(x))
148        y_true = numpy.zeros(len(x))
149
150        sum = 0.0
151        sum_true = 0.0
152        for i in range(len(x)):
153            #y[i] = self.invertor.pr(out, x[i])
154            (y[i], dy[i]) = self.invertor.pr_err(out, cov, x[i])
155            sum += y[i]
156            if x[i]<80.0:
157                y_true[i] = pr_theory(x[i], 80.0)
158            else:
159                y_true[i] = 0
160            sum_true += y_true[i]
161           
162        y = y/sum*self.invertor.d_max/len(x)
163        dy = dy/sum*self.invertor.d_max/len(x)
164        y_true = y_true/sum_true*self.invertor.d_max/len(x)
165       
166        chi2 = 0.0
167        for i in range(len(x)):
168            res = (y[i]-y_true[i])/dy[i]
169            chi2 += res*res
170           
171        try:
172            self.assertTrue(chi2/51.0<10.0)
173        except:
174            print "chi2 =", chi2/51.0
175            raise
176           
177    def test_q_zero(self):
178        """
179            Test error condition where a point has q=0
180        """
181        x, y, err = load("sphere_80.txt")
182        x[0] = 0.0
183       
184        # Choose the right d_max...
185        self.invertor.d_max = 160.0
186        # Set a small alpha
187        self.invertor.alpha = 1e-7
188        # Set data
189        def doit():
190            self.invertor.x   = x
191        self.assertRaises(ValueError, doit)
192       
193                           
194    def test_q_neg(self):
195        """
196            Test error condition where a point has q<0
197        """
198        x, y, err = load("sphere_80.txt")
199        x[0] = -0.2
200       
201        # Choose the right d_max...
202        self.invertor.d_max = 160.0
203        # Set a small alpha
204        self.invertor.alpha = 1e-7
205        # Set data
206        self.invertor.x   = x
207        self.invertor.y   = y
208        self.invertor.err = err
209        # Perform inversion
210        out, cov = self.invertor.invert(4)
211       
212        try:
213            self.assertTrue(self.invertor.chi2>0)
214        except:
215            print "Chi2 =", self.invertor.chi2
216            raise
217                           
218    def test_Iq_zero(self):
219        """
220            Test error condition where a point has q<0
221        """
222        x, y, err = load("sphere_80.txt")
223        y[0] = 0.0
224       
225        # Choose the right d_max...
226        self.invertor.d_max = 160.0
227        # Set a small alpha
228        self.invertor.alpha = 1e-7
229        # Set data
230        self.invertor.x   = x
231        self.invertor.y   = y
232        self.invertor.err = err
233        # Perform inversion
234        out, cov = self.invertor.invert(4)
235       
236        try:
237            self.assertTrue(self.invertor.chi2>0)
238        except:
239            print "Chi2 =", self.invertor.chi2
240            raise
241                           
242       
243
244def pr_theory(r, R):
245    """
246       P(r) for a sphere
247    """
248    if r<=2*R:
249        return 12.0* ((0.5*r/R)**2) * ((1.0-0.5*r/R)**2) * ( 2.0 + 0.5*r/R )
250    else:
251        return 0.0
252   
253def load(path = "sphere_60_q0_2.txt"):
254    import numpy, math, sys
255    # Read the data from the data file
256    data_x   = numpy.zeros(0)
257    data_y   = numpy.zeros(0)
258    data_err = numpy.zeros(0)
259    if not path == None:
260        input_f = open(path,'r')
261        buff    = input_f.read()
262        lines   = buff.split('\n')
263        for line in lines:
264            try:
265                toks = line.split()
266                x = float(toks[0])
267                y = float(toks[1])
268                data_x = numpy.append(data_x, x)
269                data_y = numpy.append(data_y, y)
270                # Set the error of the first point to 5%
271                # to make theory look like data
272                scale = 0.1/math.sqrt(data_x[0])
273                data_err = numpy.append(data_err, scale*math.sqrt(y))
274            except:
275                pass
276               
277    return data_x, data_y, data_err
278       
279if __name__ == '__main__':
280    unittest.main()
Note: See TracBrowser for help on using the repository browser.