[0bc0683] | 1 | """ |
---|
| 2 | Unit Tests for CorfuncCalculator class |
---|
| 3 | """ |
---|
[86ba9d6] | 4 | from __future__ import division, print_function |
---|
[0bc0683] | 5 | |
---|
| 6 | import unittest |
---|
| 7 | import time |
---|
[86ba9d6] | 8 | |
---|
[0bc0683] | 9 | import numpy as np |
---|
[86ba9d6] | 10 | |
---|
[0bc0683] | 11 | from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator |
---|
| 12 | from sas.sascalc.dataloader.data_info import Data1D |
---|
[253eb6c6] | 13 | |
---|
[0bc0683] | 14 | |
---|
| 15 | class TestCalculator(unittest.TestCase): |
---|
| 16 | |
---|
| 17 | def setUp(self): |
---|
| 18 | self.data = load_data() |
---|
[1f21a43] | 19 | # Note: to generate target values from the GUI: |
---|
| 20 | # * load the data from test/corfunc/test/98929.txt |
---|
| 21 | # * set qrange to (0, 0.013), (0.15, 0.24) |
---|
| 22 | # * select fourier transform type |
---|
| 23 | # * click Calculate Bg |
---|
| 24 | # * click Extrapolate |
---|
| 25 | # * click Compute Parameters |
---|
| 26 | # * copy the Guinier and Porod values to the extrapolate function |
---|
| 27 | # * for each graph, grab the data from DataInfo and store it in _out.txt |
---|
[0bc0683] | 28 | self.calculator = CorfuncCalculator(data=self.data, lowerq=0.013, |
---|
| 29 | upperq=(0.15, 0.24)) |
---|
[1f21a43] | 30 | self.calculator.background = 0.3 |
---|
[0bc0683] | 31 | self.extrapolation = None |
---|
[968d67e] | 32 | self.transformation = None |
---|
[1f21a43] | 33 | self.results = [np.loadtxt(filename+"_out.txt").T[2] |
---|
| 34 | for filename in ("gamma1", "gamma3", "idf")] |
---|
[0bc0683] | 35 | |
---|
| 36 | def extrapolate(self): |
---|
[be51cf6] | 37 | params, extrapolation, s2 = self.calculator.compute_extrapolation() |
---|
[acefa2b] | 38 | # Check the extrapolation parameters |
---|
[1f21a43] | 39 | self.assertAlmostEqual(params['A'], 4.18970, places=5) |
---|
| 40 | self.assertAlmostEqual(params['B'], -25469.9, places=1) |
---|
| 41 | self.assertAlmostEqual(params['K'], 4.44660e-5, places=10) |
---|
[86ba9d6] | 42 | #self.assertAlmostEqual(params['sigma'], 1.70181e-10, places=15) |
---|
[0bc0683] | 43 | |
---|
| 44 | # Ensure the extraplation tends to the background value |
---|
| 45 | self.assertAlmostEqual(extrapolation.y[-1], self.calculator.background) |
---|
| 46 | |
---|
| 47 | # Test extrapolation for q values between 0.02 and 0.24 |
---|
| 48 | mask = np.logical_and(self.data.x > 0.02, self.data.x < 0.24) |
---|
| 49 | qs = self.data.x[mask] |
---|
| 50 | iqs = self.data.y[mask] |
---|
| 51 | |
---|
| 52 | for q, iq in zip(qs, iqs): |
---|
| 53 | # Find the q value in the extraplation nearest to the value in |
---|
| 54 | # the data |
---|
| 55 | q_extrap = min(extrapolation.x, key=lambda x:abs(x-q)) |
---|
| 56 | # Find the index of this value in the extrapolation |
---|
| 57 | index = list(extrapolation.x).index(q_extrap) |
---|
| 58 | # Find it's corresponding intensity value |
---|
| 59 | iq_extrap = extrapolation.y[index] |
---|
| 60 | # Check the extrapolation agrees to the data at this point to 1 d.p |
---|
| 61 | self.assertAlmostEqual(iq_extrap, iq, 1) |
---|
| 62 | |
---|
| 63 | self.extrapolation = extrapolation |
---|
| 64 | |
---|
| 65 | def transform(self): |
---|
| 66 | self.calculator.compute_transform(self.extrapolation, 'fourier', |
---|
| 67 | completefn=self.transform_callback) |
---|
| 68 | # Transform is performed asynchronously; give it time to run |
---|
| 69 | while True: |
---|
| 70 | time.sleep(0.001) |
---|
| 71 | if not self.calculator.transform_isrunning(): |
---|
| 72 | break |
---|
| 73 | |
---|
[be51cf6] | 74 | def transform_callback(self, transforms): |
---|
| 75 | transform1, transform3, idf = transforms |
---|
| 76 | self.assertIsNotNone(transform1) |
---|
| 77 | self.assertAlmostEqual(transform1.y[0], 1) |
---|
| 78 | self.assertAlmostEqual(transform1.y[-1], 0, 5) |
---|
[1f21a43] | 79 | self.transformation = transforms |
---|
[0bc0683] | 80 | |
---|
| 81 | def extract_params(self): |
---|
[1f21a43] | 82 | params = self.calculator.extract_parameters(self.transformation[0]) |
---|
[0bc0683] | 83 | self.assertIsNotNone(params) |
---|
| 84 | self.assertEqual(len(params), 6) |
---|
| 85 | self.assertLess(abs(params['max']-75), 2.5) # L_p ~= 75 |
---|
| 86 | |
---|
[1f21a43] | 87 | def check_transforms(self): |
---|
| 88 | gamma1, gamma3, idf = self.transformation |
---|
| 89 | gamma1_out, gamma3_out, idf_out = self.results |
---|
| 90 | def compare(a, b): |
---|
| 91 | return max(abs((a-b)/b)) |
---|
[86ba9d6] | 92 | #print("gamma1 diff", compare(gamma1.y[gamma1.x<=200.], gamma1_out)) |
---|
| 93 | #print("gamma3 diff", compare(gamma3.y[gamma3.x<=200.], gamma3_out)) |
---|
| 94 | #print("idf diff", compare(idf.y[idf.x<=200.], idf_out)) |
---|
| 95 | #self.assertLess(compare(gamma1.y[gamma1.x<=200.], gamma1_out), 1e-10) |
---|
| 96 | #self.assertLess(compare(gamma3.y[gamma3.x<=200.], gamma3_out), 1e-10) |
---|
| 97 | #self.assertLess(compare(idf.y[idf.x<=200.], idf_out), 1e-10) |
---|
[1f21a43] | 98 | |
---|
[0bc0683] | 99 | # Ensure tests are ran in correct order; |
---|
| 100 | # Each test depends on the one before it |
---|
| 101 | def test_calculator(self): |
---|
[1f21a43] | 102 | steps = [self.extrapolate, self.transform, self.extract_params, self.check_transforms] |
---|
[0bc0683] | 103 | for test in steps: |
---|
| 104 | try: |
---|
| 105 | test() |
---|
| 106 | except Exception as e: |
---|
[be51cf6] | 107 | raise |
---|
[0bc0683] | 108 | self.fail("{} failed ({}: {})".format(test, type(e), e)) |
---|
| 109 | |
---|
| 110 | |
---|
| 111 | def load_data(filename="98929.txt"): |
---|
[1f21a43] | 112 | data = np.loadtxt(filename, dtype=np.float64) |
---|
[0bc0683] | 113 | q = data[:,0] |
---|
| 114 | iq = data[:,1] |
---|
| 115 | return Data1D(x=q, y=iq) |
---|
| 116 | |
---|
| 117 | if __name__ == '__main__': |
---|
| 118 | unittest.main() |
---|