""" Unit Tests for CorfuncCalculator class """ from __future__ import division, print_function import os.path import unittest import time import numpy as np from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator from sas.sascalc.dataloader.data_info import Data1D def find(filename): return os.path.join(os.path.dirname(__file__), filename) class TestCalculator(unittest.TestCase): def setUp(self): self.data = load_data() # Note: to generate target values from the GUI: # * load the data from test/corfunc/test/98929.txt # * set qrange to (0, 0.013), (0.15, 0.24) # * select fourier transform type # * click Calculate Bg # * click Extrapolate # * click Compute Parameters # * copy the Guinier and Porod values to the extrapolate function # * for each graph, grab the data from DataInfo and store it in _out.txt self.calculator = CorfuncCalculator(data=self.data, lowerq=0.013, upperq=(0.15, 0.24)) self.calculator.background = 0.3 self.extrapolation = None self.transformation = None self.results = [np.loadtxt(find(filename+"_out.txt")).T[2] for filename in ("gamma1", "gamma3", "idf")] def extrapolate(self): params, extrapolation, s2 = self.calculator.compute_extrapolation() # Check the extrapolation parameters self.assertAlmostEqual(params['A'], 4.18970, places=5) self.assertAlmostEqual(params['B'], -25469.9, places=1) self.assertAlmostEqual(params['K'], 4.44660e-5, places=10) #self.assertAlmostEqual(params['sigma'], 1.70181e-10, places=15) # Ensure the extraplation tends to the background value self.assertAlmostEqual(extrapolation.y[-1], self.calculator.background) # Test extrapolation for q values between 0.02 and 0.24 mask = np.logical_and(self.data.x > 0.02, self.data.x < 0.24) qs = self.data.x[mask] iqs = self.data.y[mask] for q, iq in zip(qs, iqs): # Find the q value in the extraplation nearest to the value in # the data q_extrap = min(extrapolation.x, key=lambda x:abs(x-q)) # Find the index of this value in the extrapolation index = list(extrapolation.x).index(q_extrap) # Find it's corresponding intensity value iq_extrap = extrapolation.y[index] # Check the extrapolation agrees to the data at this point to 1 d.p self.assertAlmostEqual(iq_extrap, iq, 1) self.extrapolation = extrapolation def transform(self): self.calculator.compute_transform(self.extrapolation, 'fourier', completefn=self.transform_callback) # Transform is performed asynchronously; give it time to run while True: time.sleep(0.001) if (not self.calculator.transform_isrunning() and self.transformation is not None): break transform1, transform3, idf = self.transformation self.assertIsNotNone(transform1) self.assertAlmostEqual(transform1.y[0], 1) self.assertAlmostEqual(transform1.y[-1], 0, 5) def transform_callback(self, transforms): self.transformation = transforms def extract_params(self): params = self.calculator.extract_parameters(self.transformation[0]) self.assertIsNotNone(params) self.assertEqual(len(params), 6) self.assertLess(abs(params['max']-75), 2.5) # L_p ~= 75 def check_transforms(self): gamma1, gamma3, idf = self.transformation gamma1_out, gamma3_out, idf_out = self.results def compare(a, b): return max(abs((a-b)/b)) #print("gamma1 diff", compare(gamma1.y[gamma1.x<=200.], gamma1_out)) #print("gamma3 diff", compare(gamma3.y[gamma3.x<=200.], gamma3_out)) #print("idf diff", compare(idf.y[idf.x<=200.], idf_out)) #self.assertLess(compare(gamma1.y[gamma1.x<=200.], gamma1_out), 1e-10) #self.assertLess(compare(gamma3.y[gamma3.x<=200.], gamma3_out), 1e-10) #self.assertLess(compare(idf.y[idf.x<=200.], idf_out), 1e-10) # Ensure tests are ran in correct order; # Each test depends on the one before it def test_calculator(self): steps = [self.extrapolate, self.transform, self.extract_params, self.check_transforms] for test in steps: try: test() except Exception as e: raise self.fail("{} failed ({}: {})".format(test, type(e), e)) def load_data(filename="98929.txt"): data = np.loadtxt(find(filename), dtype=np.float64) q = data[:,0] iq = data[:,1] return Data1D(x=q, y=iq) if __name__ == '__main__': unittest.main()