1 | """ |
---|
2 | Unit Tests for CorfuncCalculator class |
---|
3 | """ |
---|
4 | |
---|
5 | import unittest |
---|
6 | import time |
---|
7 | import numpy as np |
---|
8 | from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator |
---|
9 | from sas.sascalc.dataloader.data_info import Data1D |
---|
10 | |
---|
11 | |
---|
12 | class TestCalculator(unittest.TestCase): |
---|
13 | |
---|
14 | def setUp(self): |
---|
15 | self.data = load_data() |
---|
16 | self.calculator = CorfuncCalculator(data=self.data, lowerq=0.013, |
---|
17 | upperq=(0.15, 0.24)) |
---|
18 | self.extrapolation = None |
---|
19 | self.transformation = None |
---|
20 | |
---|
21 | def extrapolate(self): |
---|
22 | params, extrapolation = self.calculator.compute_extrapolation() |
---|
23 | |
---|
24 | # Check the extrapolation parameters |
---|
25 | self.assertAlmostEqual(params['A'], 4.19, places=2) |
---|
26 | self.assertAlmostEqual(params['B'], -25470, places=0) |
---|
27 | self.assertAlmostEqual(params['K'], 4.5e-5, places=2) |
---|
28 | self.assertAlmostEqual(params['sigma'], 2.2e-10, places=2) |
---|
29 | |
---|
30 | # Ensure the extraplation tends to the background value |
---|
31 | self.assertAlmostEqual(extrapolation.y[-1], self.calculator.background) |
---|
32 | |
---|
33 | # Test extrapolation for q values between 0.02 and 0.24 |
---|
34 | mask = np.logical_and(self.data.x > 0.02, self.data.x < 0.24) |
---|
35 | qs = self.data.x[mask] |
---|
36 | iqs = self.data.y[mask] |
---|
37 | |
---|
38 | for q, iq in zip(qs, iqs): |
---|
39 | # Find the q value in the extraplation nearest to the value in |
---|
40 | # the data |
---|
41 | q_extrap = min(extrapolation.x, key=lambda x:abs(x-q)) |
---|
42 | # Find the index of this value in the extrapolation |
---|
43 | index = list(extrapolation.x).index(q_extrap) |
---|
44 | # Find it's corresponding intensity value |
---|
45 | iq_extrap = extrapolation.y[index] |
---|
46 | # Check the extrapolation agrees to the data at this point to 1 d.p |
---|
47 | self.assertAlmostEqual(iq_extrap, iq, 1) |
---|
48 | |
---|
49 | self.extrapolation = extrapolation |
---|
50 | |
---|
51 | def transform(self): |
---|
52 | self.calculator.compute_transform(self.extrapolation, 'fourier', |
---|
53 | completefn=self.transform_callback) |
---|
54 | # Transform is performed asynchronously; give it time to run |
---|
55 | while True: |
---|
56 | time.sleep(0.001) |
---|
57 | if not self.calculator.transform_isrunning(): |
---|
58 | break |
---|
59 | |
---|
60 | def transform_callback(self, transform): |
---|
61 | self.assertIsNotNone(transform) |
---|
62 | self.assertAlmostEqual(transform.y[0], 1) |
---|
63 | self.assertAlmostEqual(transform.y[-1], 0, 5) |
---|
64 | self.transformation = transform |
---|
65 | |
---|
66 | def extract_params(self): |
---|
67 | params = self.calculator.extract_parameters(self.transformation) |
---|
68 | self.assertIsNotNone(params) |
---|
69 | self.assertEqual(len(params), 6) |
---|
70 | self.assertLess(abs(params['max']-75), 2.5) # L_p ~= 75 |
---|
71 | |
---|
72 | # Ensure tests are ran in correct order; |
---|
73 | # Each test depends on the one before it |
---|
74 | def test_calculator(self): |
---|
75 | steps = [self.extrapolate, self.transform, self.extract_params] |
---|
76 | for test in steps: |
---|
77 | try: |
---|
78 | test() |
---|
79 | except Exception as e: |
---|
80 | self.fail("{} failed ({}: {})".format(test, type(e), e)) |
---|
81 | |
---|
82 | |
---|
83 | def load_data(filename="98929.txt"): |
---|
84 | data = np.loadtxt(filename, dtype=np.float32) |
---|
85 | q = data[:,0] |
---|
86 | iq = data[:,1] |
---|
87 | return Data1D(x=q, y=iq) |
---|
88 | |
---|
89 | if __name__ == '__main__': |
---|
90 | unittest.main() |
---|