Changes in / [3c26102:b22e23e] in sasview
- Files:
-
- 3 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sascalc/corfunc/corfunc_calculator.py
ra859f99 rff11b21 34 34 35 35 def __call__(self, x): 36 # If input is a single number, evaluate the function at that number 37 # and return a single number 38 if type(x) == float or type(x) == int: 39 return self._smoothed_function(np.array([x]))[0] 40 # If input is a list, and is different to the last input, evaluate 41 # the function at each point. If the input is the same as last time 42 # the function was called, return the result that was calculated 43 # last time instead of explicity evaluating the function again. 44 elif self._lastx == [] or x.tolist() != self._lastx.tolist(): 36 if self._lastx == [] or x.tolist() != self._lastx.tolist(): 45 37 self._lasty = self._smoothed_function(x) 46 38 self._lastx = x … … 129 121 extrapolation = Data1D(qs, iqs) 130 122 131 return params, extrapolation , s2123 return params, extrapolation 132 124 133 125 def compute_transform(self, extrapolation, trans_type, background=None, … … 139 131 :param background: The background value (if not provided, previously 140 132 calculated value will be used) 141 :param extrap_fn: A callable function representing the extraoplated data142 133 :param completefn: The function to call when the transform calculation 143 is complete 134 is complete` 144 135 :param updatefn: The function to call to update the GUI with the status 145 136 of the transform calculation … … 153 144 if trans_type == 'fourier': 154 145 self._transform_thread = FourierThread(self._data, extrapolation, 155 background, completefn=completefn, 156 updatefn=updatefn) 146 background, completefn=completefn, updatefn=updatefn) 157 147 elif trans_type == 'hilbert': 158 148 self._transform_thread = HilbertThread(self._data, extrapolation, -
src/sas/sascalc/corfunc/transform_thread.py
ra859f99 rd03228e 2 2 from sas.sascalc.dataloader.data_info import Data1D 3 3 from scipy.fftpack import dct 4 from scipy.integrate import trapz, cumtrapz5 4 import numpy as np 6 5 from time import sleep … … 14 13 self.extrapolation = extrapolated_data 15 14 16 def check_if_cancelled(self):17 if self.isquit():18 self.update("Fourier transform cancelled.")19 self.complete(transforms=None)20 return True21 return False22 23 15 def compute(self): 24 16 qs = self.extrapolation.x … … 27 19 background = self.background 28 20 29 xs = np.pi*np.arange(len(qs),dtype=np.float32)/(q[1]-q[0])/len(qs)30 31 21 self.ready(delay=0.0) 32 self.update(msg=" Fourier transform in progress.")22 self.update(msg="Starting Fourier transform.") 33 23 self.ready(delay=0.0) 34 35 if self.check_if_cancelled():return24 if self.isquit(): 25 return 36 26 try: 37 # ----- 1D Correlation Function ----- 38 gamma1 = dct((iqs-background)*qs**2) 39 Q = gamma1.max() 40 gamma1 /= Q 41 42 if self.check_if_cancelled(): return 43 44 # ----- 3D Correlation Function ----- 45 # gamma3(R) = 1/R int_{0}^{R} gamma1(x) dx 46 # trapz uses the trapezium rule to calculate the integral 47 mask = xs <= 200.0 # Only calculate gamma3 up to x=200 (as this is all that's plotted) 48 # gamma3 = [trapz(gamma1[:n], xs[:n])/xs[n-1] for n in range(2, len(xs[mask]) + 1)]j 49 # gamma3.insert(0, 1.0) # Gamma_3(0) is defined as 1 50 n = len(xs[mask]) 51 gamma3 = cumtrapz(gamma1[:n], xs[:n])/xs[1:n] 52 gamma3 = np.hstack((1.0, gamma3)) # Gamma_3(0) is defined as 1 53 54 if self.check_if_cancelled(): return 55 56 # ----- Interface Distribution function ----- 57 idf = dct(-qs**4 * (iqs-background)) 58 59 if self.check_if_cancelled(): return 60 61 # Manually calculate IDF(0.0), since scipy DCT tends to give us a 62 # very large negative value. 63 # IDF(x) = int_0^inf q^4 * I(q) * cos(q*x) * dq 64 # => IDF(0) = int_0^inf q^4 * I(q) * dq 65 idf[0] = trapz(-qs**4 * (iqs-background), qs) 66 idf /= Q # Normalise using scattering invariant 67 68 except Exception as e: 69 import logging 70 logger = logging.getLogger(__name__) 71 logger.error(e) 72 27 gamma = dct((iqs-background)*qs**2) 28 gamma = gamma / gamma.max() 29 except: 73 30 self.update(msg="Fourier transform failed.") 74 self.complete(transform s=None)31 self.complete(transform=None) 75 32 return 76 33 if self.isquit(): … … 78 35 self.update(msg="Fourier transform completed.") 79 36 80 transform1 = Data1D(xs, gamma1) 81 transform3 = Data1D(xs[xs <= 200], gamma3) 82 idf = Data1D(xs, idf) 37 xs = np.pi*np.arange(len(qs),dtype=np.float32)/(q[1]-q[0])/len(qs) 38 transform = Data1D(xs, gamma) 83 39 84 transforms = (transform1, transform3, idf) 85 86 self.complete(transforms=transforms) 40 self.complete(transform=transform) 87 41 88 42 class HilbertThread(CalcThread): … … 110 64 self.update(msg="Hilbert transform completed.") 111 65 112 self.complete(transform s=None)66 self.complete(transform=None) -
src/sas/sasgui/perspectives/corfunc/corfunc.py
r9b90bf8 r463e7ffc 189 189 # Show the transformation as a curve instead of points 190 190 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 191 elif label == IDF_LABEL:192 new_plot.xaxis("{x}", 'A')193 new_plot.yaxis("{g_1}", '')194 # Linear scale195 new_plot.xtransform = 'x'196 new_plot.ytransform = 'y'197 group_id = GROUP_ID_IDF198 # Show IDF as a curve instead of points199 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM200 191 new_plot.id = label 201 192 new_plot.name = label -
src/sas/sasgui/perspectives/corfunc/corfunc_panel.py
r9b90bf8 r7432acb 55 55 self._data = data # The data to be analysed (corrected fr background) 56 56 self._extrapolated_data = None # The extrapolated data set 57 # Callable object of class CorfuncCalculator._Interpolator representing58 # the extrapolated and interpolated data59 self._extrapolated_fn = None60 57 self._transformed_data = None # Fourier trans. of the extrapolated data 61 58 self._calculator = CorfuncCalculator() … … 221 218 222 219 try: 223 params, self._extrapolated_data, self._extrapolated_fn = \ 224 self._calculator.compute_extrapolation() 220 params, self._extrapolated_data = self._calculator.compute_extrapolation() 225 221 except Exception as e: 226 222 msg = "Error extrapolating data:\n" … … 261 257 StatusEvent(status=msg)) 262 258 263 def transform_complete(self, transform s=None):259 def transform_complete(self, transform=None): 264 260 """ 265 261 Called from FourierThread when calculation has completed 266 262 """ 267 263 self._transform_btn.SetLabel("Transform") 268 if transform sis None:264 if transform is None: 269 265 msg = "Error calculating Transform." 270 266 if self.transform_type == 'hilbert': … … 274 270 self._extract_btn.Disable() 275 271 return 276 277 self._transformed_data = transforms 278 (transform1, transform3, idf) = transforms 279 plot_x = transform1.x[transform1.x <= 200] 280 plot_y = transform1.y[transform1.x <= 200] 272 self._transformed_data = transform 273 import numpy as np 274 plot_x = transform.x[np.where(transform.x <= 200)] 275 plot_y = transform.y[np.where(transform.x <= 200)] 281 276 self._manager.show_data(Data1D(plot_x, plot_y), TRANSFORM_LABEL1) 282 # No need to shorten gamma3 as it's only calculated up to x=200283 self._manager.show_data(transform3, TRANSFORM_LABEL3)284 285 plot_x = idf.x[idf.x <= 200]286 plot_y = idf.y[idf.x <= 200]287 self._manager.show_data(Data1D(plot_x, plot_y), IDF_LABEL)288 289 277 # Only enable extract params button if a fourier trans. has been done 290 278 if self.transform_type == 'fourier': … … 298 286 """ 299 287 try: 300 params = self._calculator.extract_parameters(self._transformed_data [0])288 params = self._calculator.extract_parameters(self._transformed_data) 301 289 except: 302 290 params = None -
src/sas/sasgui/perspectives/corfunc/corfunc_state.py
r457f735 r7432acb 59 59 self.q = None 60 60 self.iq = None 61 # TODO: Add extrapolated data and transformed data (when implemented) 61 62 62 63 def __str__(self): -
src/sas/sasgui/perspectives/corfunc/media/corfunc_help.rst
rd78b5cb r1404cce 10 10 11 11 This performs a correlation function analysis of one-dimensional 12 SAXS/SANS data, or generates a model-independent volume fraction 12 SAXS/SANS data, or generates a model-independent volume fraction 13 13 profile from the SANS from an adsorbed polymer/surfactant layer. 14 14 15 A correlation function may be interpreted in terms of an imaginary rod moving 16 through the structure of the material. Î\ :sub:`1D`\ (R) is the probability that 17 a rod of length R moving through the material has equal electron/neutron scattering 18 length density at either end. Hence a frequently occurring spacing within a structure 15 A correlation function may be interpreted in terms of an imaginary rod moving 16 through the structure of the material. Î\ :sub:`1D`\ (R) is the probability that 17 a rod of length R moving through the material has equal electron/neutron scattering 18 length density at either end. Hence a frequently occurring spacing within a structure 19 19 manifests itself as a peak. 20 20 … … 30 30 * Fourier / Hilbert Transform of the smoothed data to give the correlation 31 31 function / volume fraction profile, respectively 32 * (Optional) Interpretation of the 1D correlation function based on an ideal 32 * (Optional) Interpretation of the 1D correlation function based on an ideal 33 33 lamellar morphology 34 34 … … 74 74 :align: center 75 75 76 76 77 77 Smoothing 78 78 --------- 79 79 80 The extrapolated data set consists of the Guinier back-extrapolation from Q~0 80 The extrapolated data set consists of the Guinier back-extrapolation from Q~0 81 81 up to the lowest Q value in the original data, then the original scattering data, and the Porod tail-fit beyond this. The joins between the original data and the Guinier/Porod fits are smoothed using the algorithm below to avoid the formation of ripples in the transformed data. 82 82 … … 93 93 h_i = \frac{1}{1 + \frac{(x_i-b)^2}{(x_i-a)^2}} 94 94 95 95 96 96 Transform 97 97 --------- … … 102 102 If "Fourier" is selected for the transform type, the analysis will perform a 103 103 discrete cosine transform on the extrapolated data in order to calculate the 104 1D correlation function: 104 correlation function 105 105 106 106 .. math:: … … 115 115 \left(n + \frac{1}{2} \right) k \right] } \text{ for } k = 0, 1, \ldots, 116 116 N-1, N 117 118 The 3D correlation function is also calculated:119 120 .. math::121 \Gamma _{3D}(R) = \frac{1}{Q^{*}} \int_{0}^{\infty}I(q) q^{2}122 \frac{sin(qR)}{qR} dq123 117 124 118 Hilbert … … 171 165 .. figure:: profile1.png 172 166 :align: center 173 167 174 168 .. figure:: profile2.png 175 169 :align: center 176 170 177 171 178 172 References … … 197 191 ----- 198 192 Upon sending data for correlation function analysis, it will be plotted (minus 199 the background value), along with a *red* bar indicating the *upper end of the 193 the background value), along with a *red* bar indicating the *upper end of the 200 194 low-Q range* (used for back-extrapolation), and 2 *purple* bars indicating the range to be used for forward-extrapolation. These bars may be moved my clicking and 201 195 dragging, or by entering appropriate values in the Q range input boxes. … … 227 221 :align: center 228 222 229 223 230 224 .. note:: 231 225 This help document was last changed by Steve King, 08Oct2016 -
src/sas/sasgui/perspectives/corfunc/plot_labels.py
r7dda833 r1dc8ec9 4 4 5 5 GROUP_ID_TRANSFORM = r"$\Gamma(x)$" 6 TRANSFORM_LABEL1 = r"$\Gamma_1(x)$" 7 TRANSFORM_LABEL3 = r"$\Gamma_3(x)$" 8 9 GROUP_ID_IDF = r"$g_1(x)$" 10 IDF_LABEL = r"$g_1(x)$" 6 TRANSFORM_LABEL1 = r"$\Gamma1(x)$" 7 TRANSFORM_LABEL3 = r"$\Gamma3(x)$" -
test/corfunc/test/utest_corfunc.py
r86ba9d6 r968d67e 2 2 Unit Tests for CorfuncCalculator class 3 3 """ 4 from __future__ import division, print_function5 4 6 5 import unittest 7 6 import time 8 9 7 import numpy as np 10 11 8 from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator 12 9 from sas.sascalc.dataloader.data_info import Data1D … … 17 14 def setUp(self): 18 15 self.data = load_data() 19 # Note: to generate target values from the GUI:20 # * load the data from test/corfunc/test/98929.txt21 # * set qrange to (0, 0.013), (0.15, 0.24)22 # * select fourier transform type23 # * click Calculate Bg24 # * click Extrapolate25 # * click Compute Parameters26 # * copy the Guinier and Porod values to the extrapolate function27 # * for each graph, grab the data from DataInfo and store it in _out.txt28 16 self.calculator = CorfuncCalculator(data=self.data, lowerq=0.013, 29 17 upperq=(0.15, 0.24)) 30 self.calculator.background = 0.331 18 self.extrapolation = None 32 19 self.transformation = None 33 self.results = [np.loadtxt(filename+"_out.txt").T[2]34 for filename in ("gamma1", "gamma3", "idf")]35 20 36 21 def extrapolate(self): 37 params, extrapolation, s2 = self.calculator.compute_extrapolation() 22 params, extrapolation = self.calculator.compute_extrapolation() 23 38 24 # Check the extrapolation parameters 39 self.assertAlmostEqual(params['A'], 4.1 8970, places=5)40 self.assertAlmostEqual(params['B'], -254 69.9, places=1)41 self.assertAlmostEqual(params['K'], 4. 44660e-5, places=10)42 #self.assertAlmostEqual(params['sigma'], 1.70181e-10, places=15)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) 43 29 44 30 # Ensure the extraplation tends to the background value … … 72 58 break 73 59 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) 79 self.transformation = transforms 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 80 65 81 66 def extract_params(self): 82 params = self.calculator.extract_parameters(self.transformation [0])67 params = self.calculator.extract_parameters(self.transformation) 83 68 self.assertIsNotNone(params) 84 69 self.assertEqual(len(params), 6) 85 70 self.assertLess(abs(params['max']-75), 2.5) # L_p ~= 75 86 71 87 def check_transforms(self):88 gamma1, gamma3, idf = self.transformation89 gamma1_out, gamma3_out, idf_out = self.results90 def compare(a, b):91 return max(abs((a-b)/b))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)98 99 72 # Ensure tests are ran in correct order; 100 73 # Each test depends on the one before it 101 74 def test_calculator(self): 102 steps = [self.extrapolate, self.transform, self.extract_params , self.check_transforms]75 steps = [self.extrapolate, self.transform, self.extract_params] 103 76 for test in steps: 104 77 try: 105 78 test() 106 79 except Exception as e: 107 raise108 80 self.fail("{} failed ({}: {})".format(test, type(e), e)) 109 81 110 82 111 83 def load_data(filename="98929.txt"): 112 data = np.loadtxt(filename, dtype=np.float 64)84 data = np.loadtxt(filename, dtype=np.float32) 113 85 q = data[:,0] 114 86 iq = data[:,1] -
test/utest_sasview.py
rbe51cf6 rb54440d 62 62 proc = subprocess.Popen(code, shell=True, stdout=subprocess.PIPE, stderr = subprocess.STDOUT) 63 63 std_out, std_err = proc.communicate() 64 #print (">>>>>> standard out", file_path, "\n", std_out, "\n>>>>>>>>> end stdout", file_path)64 #print std_out 65 65 #sys.exit() 66 66 m = re.search("Ran ([0-9]+) test", std_out) … … 82 82 failed += 1 83 83 print("Result for %s (%s): FAILED" % (module_name, module_dir)) 84 #print(std_out)84 print(std_out) 85 85 else: 86 86 passed += 1
Note: See TracChangeset
for help on using the changeset viewer.