Changeset 9e2535e in sasview
- Timestamp:
- May 18, 2017 3:21:33 PM (8 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 8de66b6
- Parents:
- e0ebd56 (diff), 7132e49 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 29 added
- 1 deleted
- 11 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
run.py
rf36e01f rf94a935 51 51 def import_package(modname, path): 52 52 """Import a package into a particular point in the python namespace""" 53 #logger.debug("Dynamicly importing: %s", path) 53 54 mod = imp.load_source(modname, abspath(joinpath(path, '__init__.py'))) 54 55 sys.modules[modname] = mod -
sasview/test/sesans_data/sphere2micron.ses
r2a2b43a rd3bce8c 1 DataFileTitle "Polystyrene of Markus Strobl, Full Sine, ++ only " 2 Sample "Polystyrene 2 um in 53% H2O, 47% D2O " 3 Settings "D1=D2=20x8 mm,Ds = 16x10 mm (WxH), GF1 =scanning, GF2 = 2.5 A. 2 um polystyrene in 53% H2O, 47% D2O; 8.55% contrast " 4 Operator CPD 5 Date do 10 jul 2014 16:37:30 6 ScanType sine one element scan 7 Thickness [cm] 2.00E-01 8 Q_zmax [\A^-1] 0.05 9 Q_ymax [\A^-1] 0.05 10 11 spin echo length [A] Depolarisation [A-2 cm-1] error depol [A-2 cm-1] error SEL [A] wavelength [A] error wavelength [A] polarisation error pol 12 391.56 0.0041929 0.0036894 19.578 2.11 0.1055 1.0037 0.0032974 13 1564 -0.0046571 0.0038185 78.2 2.11 0.1055 0.99586 0.003386 14 2735.6 -0.017007 0.0038132 136.78 2.11 0.1055 0.98497 0.0033444 15 3907.9 -0.033462 0.0035068 195.39 2.11 0.1055 0.97064 0.0030309 16 5080.2 -0.047483 0.0038208 254.01 2.11 0.1055 0.9586 0.0032613 17 6251.8 -0.070375 0.00376 312.59 2.11 0.1055 0.93926 0.0031446 18 7423.2 -0.092217 0.0037927 371.16 2.11 0.1055 0.92117 0.0031108 19 8595.5 -0.10238 0.004006 429.77 2.11 0.1055 0.91287 0.0032562 20 9767.7 -0.12672 0.0038534 488.39 2.11 0.1055 0.8933 0.0030651 21 10940 -0.1374 0.004243 546.98 2.11 0.1055 0.88484 0.003343 22 12112 -0.16072 0.0045837 605.58 2.11 0.1055 0.86666 0.0035372 23 13284 -0.16623 0.0045613 664.2 2.11 0.1055 0.86242 0.0035027 24 14456 -0.18468 0.0044918 722.79 2.11 0.1055 0.84837 0.0033931 25 15628 -0.19143 0.0048967 781.38 2.11 0.1055 0.84328 0.0036768 26 16800 -0.20029 0.0045421 840.02 2.11 0.1055 0.83666 0.0033837 27 17971 -0.19798 0.0046642 898.56 2.11 0.1055 0.83838 0.0034819 28 19143 -0.21442 0.0047052 957.17 2.11 0.1055 0.82619 0.0034614 29 20316 -0.20885 0.0044931 1015.8 2.11 0.1055 0.8303 0.0033218 30 21488 -0.21393 0.0049186 1074.4 2.11 0.1055 0.82655 0.00362 31 22660 -0.20685 0.004423 1133 2.11 0.1055 0.83179 0.0032758 32 23832 -0.20802 0.0046979 1191.6 2.11 0.1055 0.83092 0.0034758 33 25003 -0.19848 0.0045953 1250.2 2.11 0.1055 0.838 0.0034289 34 26175 -0.21117 0.0044567 1308.8 2.11 0.1055 0.82859 0.0032881 35 27347 -0.21283 0.004137 1367.4 2.11 0.1055 0.82736 0.0030477 36 28520 -0.2042 0.0044587 1426 2.11 0.1055 0.83375 0.0033101 37 29692 -0.2112 0.0042852 1484.6 2.11 0.1055 0.82857 0.0031615 38 30864 -0.20319 0.0043483 1543.2 2.11 0.1055 0.8345 0.003231 39 32036 -0.20752 0.0044297 1601.8 2.11 0.1055 0.83129 0.0032788 40 33207 -0.20654 0.0043188 1660.4 2.11 0.1055 0.83201 0.0031995 41 34380 -0.20126 0.0046375 1719 2.11 0.1055 0.83593 0.0034518 42 35551 -0.20924 0.0042871 1777.6 2.11 0.1055 0.83001 0.0031684 43 36724 -0.21323 0.0045471 1836.2 2.11 0.1055 0.82707 0.0033487 44 37895 -0.21324 0.0045354 1894.7 2.11 0.1055 0.82706 0.00334 45 39067 -0.19905 0.0044141 1953.4 2.11 0.1055 0.83758 0.003292 46 40239 -0.1991 0.0047441 2012 2.11 0.1055 0.83754 0.003538 47 41411 -0.20359 0.0050136 2070.5 2.11 0.1055 0.8342 0.003724 48 42583 -0.21032 0.0049474 2129.1 2.11 0.1055 0.82922 0.0036529 49 43755 -0.20689 0.0048203 2187.8 2.11 0.1055 0.83176 0.00357 50 44927 -0.21075 0.0052337 2246.4 2.11 0.1055 0.8289 0.0038628 51 46099 -0.19956 0.0047827 2304.9 2.11 0.1055 0.8372 0.0035653 1 FileFormatVersion 1.0 2 DataFileTitle Polystyrene of Markus Strobl, Full Sine, ++ only 3 Sample Polystyrene 2 um in 53% H2O, 47% D2O 4 Settings D1=D2=20x8 mm,Ds = 16x10 mm (WxH), GF1 =scanning, GF2 = 2.5 A. 2 um polystyrene in 53% H2O, 47% D2O; 8.55% contrast 5 Operator CPD 6 Date do 10 jul 2014 16:37:30 7 ScanType sine one element scan 8 Thickness 2.00E-01 9 Thickness_unit cm 10 Theta_zmax 0.0168 11 Theta_zmax_unit radians 12 Theta_ymax 0.0168 13 Theta_ymax_unit radians 14 Orientation Z 15 SpinEchoLength_unit A 16 Depolarisation_unit A-2 cm-1 17 Wavelength_unit A 18 19 BEGIN_DATA 20 SpinEchoLength Depolarisation Depolarisation_error SpinEchoLength_error Wavelength Wavelength_error Polarisation Polarisation_error 21 391.56 0.0041929 0.0036894 19.578 2.11 0.1055 1.0037 0.0032974 22 1564 -0.0046571 0.0038185 78.2 2.11 0.1055 0.99586 0.003386 23 2735.6 -0.017007 0.0038132 136.78 2.11 0.1055 0.98497 0.0033444 24 3907.9 -0.033462 0.0035068 195.39 2.11 0.1055 0.97064 0.0030309 25 5080.2 -0.047483 0.0038208 254.01 2.11 0.1055 0.9586 0.0032613 26 6251.8 -0.070375 0.00376 312.59 2.11 0.1055 0.93926 0.0031446 27 7423.2 -0.092217 0.0037927 371.16 2.11 0.1055 0.92117 0.0031108 28 8595.5 -0.10238 0.004006 429.77 2.11 0.1055 0.91287 0.0032562 29 9767.7 -0.12672 0.0038534 488.39 2.11 0.1055 0.8933 0.0030651 30 10940 -0.1374 0.004243 546.98 2.11 0.1055 0.88484 0.003343 31 12112 -0.16072 0.0045837 605.58 2.11 0.1055 0.86666 0.0035372 32 13284 -0.16623 0.0045613 664.2 2.11 0.1055 0.86242 0.0035027 33 14456 -0.18468 0.0044918 722.79 2.11 0.1055 0.84837 0.0033931 34 15628 -0.19143 0.0048967 781.38 2.11 0.1055 0.84328 0.0036768 35 16800 -0.20029 0.0045421 840.02 2.11 0.1055 0.83666 0.0033837 36 17971 -0.19798 0.0046642 898.56 2.11 0.1055 0.83838 0.0034819 37 19143 -0.21442 0.0047052 957.17 2.11 0.1055 0.82619 0.0034614 38 20316 -0.20885 0.0044931 1015.8 2.11 0.1055 0.8303 0.0033218 39 21488 -0.21393 0.0049186 1074.4 2.11 0.1055 0.82655 0.00362 40 22660 -0.20685 0.004423 1133 2.11 0.1055 0.83179 0.0032758 41 23832 -0.20802 0.0046979 1191.6 2.11 0.1055 0.83092 0.0034758 42 25003 -0.19848 0.0045953 1250.2 2.11 0.1055 0.838 0.0034289 43 26175 -0.21117 0.0044567 1308.8 2.11 0.1055 0.82859 0.0032881 44 27347 -0.21283 0.004137 1367.4 2.11 0.1055 0.82736 0.0030477 45 28520 -0.2042 0.0044587 1426 2.11 0.1055 0.83375 0.0033101 46 29692 -0.2112 0.0042852 1484.6 2.11 0.1055 0.82857 0.0031615 47 30864 -0.20319 0.0043483 1543.2 2.11 0.1055 0.8345 0.003231 48 32036 -0.20752 0.0044297 1601.8 2.11 0.1055 0.83129 0.0032788 49 33207 -0.20654 0.0043188 1660.4 2.11 0.1055 0.83201 0.0031995 50 34380 -0.20126 0.0046375 1719 2.11 0.1055 0.83593 0.0034518 51 35551 -0.20924 0.0042871 1777.6 2.11 0.1055 0.83001 0.0031684 52 36724 -0.21323 0.0045471 1836.2 2.11 0.1055 0.82707 0.0033487 53 37895 -0.21324 0.0045354 1894.7 2.11 0.1055 0.82706 0.00334 54 39067 -0.19905 0.0044141 1953.4 2.11 0.1055 0.83758 0.003292 55 40239 -0.1991 0.0047441 2012 2.11 0.1055 0.83754 0.003538 56 41411 -0.20359 0.0050136 2070.5 2.11 0.1055 0.8342 0.003724 57 42583 -0.21032 0.0049474 2129.1 2.11 0.1055 0.82922 0.0036529 58 43755 -0.20689 0.0048203 2187.8 2.11 0.1055 0.83176 0.00357 59 44927 -0.21075 0.0052337 2246.4 2.11 0.1055 0.8289 0.0038628 60 46099 -0.19956 0.0047827 2304.9 2.11 0.1055 0.8372 0.0035653 -
src/sas/sascalc/data_util/nxsunit.py
rb699768 r8e9536f 136 136 sld = { '10^-6 Angstrom^-2': 1e-6, 'Angstrom^-2': 1 } 137 137 Q = { 'invA': 1, 'invAng': 1, 'invAngstroms': 1, '1/A': 1, 138 '10^-3 Angstrom^-1': 1e-3, '1/cm': 1e-8, 138 '10^-3 Angstrom^-1': 1e-3, '1/cm': 1e-8, '1/m': 1e-10, 139 139 'nm^-1': 0.1, '1/nm': 0.1, 'n_m^-1': 0.1 } 140 140 … … 195 195 _check(1,Converter('n_m^-1')(10,'invA')) # 10 nm^-1 = 1 inv Angstroms 196 196 _check(2,Converter('mm')(2000,'m')) # 2000 mm -> 2 m 197 _check(2.011e10,Converter('1/A')(2.011,"1/m")) # 2.011 1/A -> 2.011 * 10^10 1/m 197 198 _check(0.003,Converter('microseconds')(3,units='ms')) # 3 us -> 0.003 ms 198 199 _check(45,Converter('nanokelvin')(45)) # 45 nK -> 45 nK -
src/sas/sascalc/data_util/qsmearing.py
r235f514 r8938502 65 65 raise ValueError('one or more of your dx values are negative, please check the data file!') 66 66 67 if _found_sesans == True: 68 #Pre-compute the Hankel matrix (H) 69 qmax, qunits = data.sample.zacceptance 67 if _found_sesans: 68 # Pre-compute the Hankel matrix (H) 70 69 SElength = Converter(data._xunit)(data.x, "A") 71 zaccept = Converter(qunits)(qmax, "1/A"), 70 71 theta_max = Converter("radians")(data.sample.zacceptance)[0] 72 q_max = 2 * np.pi / np.max(data.source.wavelength) * np.sin(theta_max) 73 zaccept = Converter("1/A")(q_max, "1/" + data.source.wavelength_unit), 74 72 75 Rmax = 10000000 73 hankel = SesansTransform(data.x, SElength, zaccept, Rmax) 76 hankel = SesansTransform(data.x, SElength, 77 data.source.wavelength, 78 zaccept, Rmax) 74 79 # Then return the actual transform, as if it were a smearing function 75 80 return PySmear(hankel, model, offset=0) -
src/sas/sascalc/dataloader/manipulations.py
re0ebd56 r46cd1c3 1 from __future__ import division 1 2 """ 2 3 Data manipulations for 2D data sets. 3 4 Using the meta data information, various types of averaging 4 5 are performed in Q-space 6 7 To test this module use: 8 ``` 9 cd test 10 PYTHONPATH=../src/ python2 -m sasdataloader.test.utest_averaging DataInfoTests.test_sectorphi_quarter 11 ``` 5 12 """ 6 13 ##################################################################### 7 # This software was developed by the University of Tennessee as part of the8 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE)9 # project funded by the US National Science Foundation.10 # See the license text in license.txt11 # copyright 2008, University of Tennessee14 # This software was developed by the University of Tennessee as part of the 15 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 16 # project funded by the US National Science Foundation. 17 # See the license text in license.txt 18 # copyright 2008, University of Tennessee 12 19 ###################################################################### 13 20 14 #TODO: copy the meta data from the 2D object to the resulting 1D object 21 22 # TODO: copy the meta data from the 2D object to the resulting 1D object 15 23 import math 16 24 import numpy as np 25 import sys 17 26 18 27 #from data_info import plottable_2D … … 70 79 return phi_out 71 80 72 73 def reader2D_converter(data2d=None):74 """75 convert old 2d format opened by IhorReader or danse_reader76 to new Data2D format77 78 :param data2d: 2d array of Data2D object79 :return: 1d arrays of Data2D object80 81 """82 if data2d.data is None or data2d.x_bins is None or data2d.y_bins is None:83 raise ValueError, "Can't convert this data: data=None..."84 new_x = np.tile(data2d.x_bins, (len(data2d.y_bins), 1))85 new_y = np.tile(data2d.y_bins, (len(data2d.x_bins), 1))86 new_y = new_y.swapaxes(0, 1)87 88 new_data = data2d.data.flatten()89 qx_data = new_x.flatten()90 qy_data = new_y.flatten()91 q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data)92 if data2d.err_data is None or np.any(data2d.err_data <= 0):93 new_err_data = np.sqrt(np.abs(new_data))94 else:95 new_err_data = data2d.err_data.flatten()96 mask = np.ones(len(new_data), dtype=bool)97 98 #TODO: make sense of the following two lines...99 #from sas.sascalc.dataloader.data_info import Data2D100 #output = Data2D()101 output = data2d102 output.data = new_data103 output.err_data = new_err_data104 output.qx_data = qx_data105 output.qy_data = qy_data106 output.q_data = q_data107 output.mask = mask108 109 return output110 111 112 class _Slab(object):113 """114 Compute average I(Q) for a region of interest115 """116 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0,117 y_max=0.0, bin_width=0.001):118 # Minimum Qx value [A-1]119 self.x_min = x_min120 # Maximum Qx value [A-1]121 self.x_max = x_max122 # Minimum Qy value [A-1]123 self.y_min = y_min124 # Maximum Qy value [A-1]125 self.y_max = y_max126 # Bin width (step size) [A-1]127 self.bin_width = bin_width128 # If True, I(|Q|) will be return, otherwise,129 # negative q-values are allowed130 self.fold = False131 132 def __call__(self, data2D):133 return NotImplemented134 135 def _avg(self, data2D, maj):136 """137 Compute average I(Q_maj) for a region of interest.138 The major axis is defined as the axis of Q_maj.139 The minor axis is the axis that we average over.140 141 :param data2D: Data2D object142 :param maj_min: min value on the major axis143 :return: Data1D object144 """145 if len(data2D.detector) > 1:146 msg = "_Slab._avg: invalid number of "147 msg += " detectors: %g" % len(data2D.detector)148 raise RuntimeError, msg149 150 # Get data151 data = data2D.data[np.isfinite(data2D.data)]152 err_data = data2D.err_data[np.isfinite(data2D.data)]153 qx_data = data2D.qx_data[np.isfinite(data2D.data)]154 qy_data = data2D.qy_data[np.isfinite(data2D.data)]155 156 # Build array of Q intervals157 if maj == 'x':158 if self.fold:159 x_min = 0160 else:161 x_min = self.x_min162 nbins = int(math.ceil((self.x_max - x_min) / self.bin_width))163 elif maj == 'y':164 if self.fold:165 y_min = 0166 else:167 y_min = self.y_min168 nbins = int(math.ceil((self.y_max - y_min) / self.bin_width))169 else:170 raise RuntimeError, "_Slab._avg: unrecognized axis %s" % str(maj)171 172 x = np.zeros(nbins)173 y = np.zeros(nbins)174 err_y = np.zeros(nbins)175 y_counts = np.zeros(nbins)176 177 # Average pixelsize in q space178 for npts in range(len(data)):179 # default frac180 frac_x = 0181 frac_y = 0182 # get ROI183 if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]:184 frac_x = 1185 if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]:186 frac_y = 1187 frac = frac_x * frac_y188 189 if frac == 0:190 continue191 # binning: find axis of q192 if maj == 'x':193 q_value = qx_data[npts]194 min_value = x_min195 if maj == 'y':196 q_value = qy_data[npts]197 min_value = y_min198 if self.fold and q_value < 0:199 q_value = -q_value200 # bin201 i_q = int(math.ceil((q_value - min_value) / self.bin_width)) - 1202 203 # skip outside of max bins204 if i_q < 0 or i_q >= nbins:205 continue206 207 #TODO: find better definition of x[i_q] based on q_data208 # min_value + (i_q + 1) * self.bin_width / 2.0209 x[i_q] += frac * q_value210 y[i_q] += frac * data[npts]211 212 if err_data is None or err_data[npts] == 0.0:213 if data[npts] < 0:214 data[npts] = -data[npts]215 err_y[i_q] += frac * frac * data[npts]216 else:217 err_y[i_q] += frac * frac * err_data[npts] * err_data[npts]218 y_counts[i_q] += frac219 220 # Average the sums221 for n in range(nbins):222 err_y[n] = math.sqrt(err_y[n])223 224 err_y = err_y / y_counts225 y = y / y_counts226 x = x / y_counts227 idx = (np.isfinite(y) & np.isfinite(x))228 229 if not idx.any():230 msg = "Average Error: No points inside ROI to average..."231 raise ValueError, msg232 return Data1D(x=x[idx], y=y[idx], dy=err_y[idx])233 234 235 class SlabY(_Slab):236 """237 Compute average I(Qy) for a region of interest238 """239 def __call__(self, data2D):240 """241 Compute average I(Qy) for a region of interest242 243 :param data2D: Data2D object244 :return: Data1D object245 """246 return self._avg(data2D, 'y')247 248 249 class SlabX(_Slab):250 """251 Compute average I(Qx) for a region of interest252 """253 def __call__(self, data2D):254 """255 Compute average I(Qx) for a region of interest256 :param data2D: Data2D object257 :return: Data1D object258 """259 return self._avg(data2D, 'x')260 261 262 class Boxsum(object):263 """264 Perform the sum of counts in a 2D region of interest.265 """266 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):267 # Minimum Qx value [A-1]268 self.x_min = x_min269 # Maximum Qx value [A-1]270 self.x_max = x_max271 # Minimum Qy value [A-1]272 self.y_min = y_min273 # Maximum Qy value [A-1]274 self.y_max = y_max275 276 def __call__(self, data2D):277 """278 Perform the sum in the region of interest279 280 :param data2D: Data2D object281 :return: number of counts, error on number of counts,282 number of points summed283 """284 y, err_y, y_counts = self._sum(data2D)285 286 # Average the sums287 counts = 0 if y_counts == 0 else y288 error = 0 if y_counts == 0 else math.sqrt(err_y)289 290 # Added y_counts to return, SMK & PDB, 04/03/2013291 return counts, error, y_counts292 293 def _sum(self, data2D):294 """295 Perform the sum in the region of interest296 297 :param data2D: Data2D object298 :return: number of counts,299 error on number of counts, number of entries summed300 """301 if len(data2D.detector) > 1:302 msg = "Circular averaging: invalid number "303 msg += "of detectors: %g" % len(data2D.detector)304 raise RuntimeError, msg305 # Get data306 data = data2D.data[np.isfinite(data2D.data)]307 err_data = data2D.err_data[np.isfinite(data2D.data)]308 qx_data = data2D.qx_data[np.isfinite(data2D.data)]309 qy_data = data2D.qy_data[np.isfinite(data2D.data)]310 311 y = 0.0312 err_y = 0.0313 y_counts = 0.0314 315 # Average pixelsize in q space316 for npts in range(len(data)):317 # default frac318 frac_x = 0319 frac_y = 0320 321 # get min and max at each points322 qx = qx_data[npts]323 qy = qy_data[npts]324 325 # get the ROI326 if self.x_min <= qx and self.x_max > qx:327 frac_x = 1328 if self.y_min <= qy and self.y_max > qy:329 frac_y = 1330 #Find the fraction along each directions331 frac = frac_x * frac_y332 if frac == 0:333 continue334 y += frac * data[npts]335 if err_data is None or err_data[npts] == 0.0:336 if data[npts] < 0:337 data[npts] = -data[npts]338 err_y += frac * frac * data[npts]339 else:340 err_y += frac * frac * err_data[npts] * err_data[npts]341 y_counts += frac342 return y, err_y, y_counts343 344 345 class Boxavg(Boxsum):346 """347 Perform the average of counts in a 2D region of interest.348 """349 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0):350 super(Boxavg, self).__init__(x_min=x_min, x_max=x_max,351 y_min=y_min, y_max=y_max)352 353 def __call__(self, data2D):354 """355 Perform the sum in the region of interest356 357 :param data2D: Data2D object358 :return: average counts, error on average counts359 360 """361 y, err_y, y_counts = self._sum(data2D)362 363 # Average the sums364 counts = 0 if y_counts == 0 else y / y_counts365 error = 0 if y_counts == 0 else math.sqrt(err_y) / y_counts366 367 return counts, error368 369 370 81 def get_pixel_fraction_square(x, xmin, xmax): 371 82 """ … … 390 101 return 1.0 391 102 392 393 class CircularAverage(object): 394 """ 395 Perform circular averaging on 2D data 396 397 The data returned is the distribution of counts 398 as a function of Q 399 """ 400 def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005): 401 # Minimum radius included in the average [A-1] 402 self.r_min = r_min 403 # Maximum radius included in the average [A-1] 404 self.r_max = r_max 405 # Bin width (step size) [A-1] 406 self.bin_width = bin_width 407 408 def __call__(self, data2D, ismask=False): 409 """ 410 Perform circular averaging on the data 411 412 :param data2D: Data2D object 413 :return: Data1D object 414 """ 415 # Get data W/ finite values 416 data = data2D.data[np.isfinite(data2D.data)] 417 q_data = data2D.q_data[np.isfinite(data2D.data)] 418 err_data = data2D.err_data[np.isfinite(data2D.data)] 419 mask_data = data2D.mask[np.isfinite(data2D.data)] 420 421 dq_data = None 422 423 # Get the dq for resolution averaging 424 if data2D.dqx_data is not None and data2D.dqy_data is not None: 425 # The pinholes and det. pix contribution present 426 # in both direction of the 2D which must be subtracted when 427 # converting to 1D: dq_overlap should calculated ideally at 428 # q = 0. Note This method works on only pinhole geometry. 429 # Extrapolate dqx(r) and dqy(phi) at q = 0, and take an average. 430 z_max = max(data2D.q_data) 431 z_min = min(data2D.q_data) 432 x_max = data2D.dqx_data[data2D.q_data[z_max]] 433 x_min = data2D.dqx_data[data2D.q_data[z_min]] 434 y_max = data2D.dqy_data[data2D.q_data[z_max]] 435 y_min = data2D.dqy_data[data2D.q_data[z_min]] 436 # Find qdx at q = 0 437 dq_overlap_x = ((x_min * z_max - x_max * z_min) / 438 (z_max - z_min)) 439 # when extrapolation goes wrong 440 if dq_overlap_x > min(data2D.dqx_data): 441 dq_overlap_x = min(data2D.dqx_data) 442 dq_overlap_x *= dq_overlap_x 443 # Find qdx at q = 0 444 dq_overlap_y = ((y_min * z_max - y_max * z_min) / 445 (z_max - z_min)) 446 # when extrapolation goes wrong 447 if dq_overlap_y > min(data2D.dqy_data): 448 dq_overlap_y = min(data2D.dqy_data) 449 # get dq at q=0. 450 dq_overlap_y *= dq_overlap_y 451 452 dq_overlap = np.sqrt((dq_overlap_x + dq_overlap_y) / 2.0) 453 # Final protection of dq 454 if dq_overlap < 0: 455 dq_overlap = y_min 456 dqx_data = data2D.dqx_data[np.isfinite(data2D.data)] 457 dqy_data = data2D.dqy_data[np.isfinite(data2D.data)] - dq_overlap 458 # def; dqx_data = dq_r dqy_data = dq_phi 459 # Convert dq 2D to 1D here 460 dqx = dqx_data * dqx_data 461 dqy = dqy_data * dqy_data 462 dq_data = np.add(dqx, dqy) 463 dq_data = np.sqrt(dq_data) 464 465 #q_data_max = np.max(q_data) 466 if len(data2D.q_data) is None: 467 msg = "Circular averaging: invalid q_data: %g" % data2D.q_data 468 raise RuntimeError, msg 469 470 # Build array of Q intervals 471 nbins = int(math.ceil((self.r_max - self.r_min) / self.bin_width)) 472 473 x = np.zeros(nbins) 474 y = np.zeros(nbins) 475 err_y = np.zeros(nbins) 476 err_x = np.zeros(nbins) 477 y_counts = np.zeros(nbins) 478 479 for npt in range(len(data)): 480 481 if ismask and not mask_data[npt]: 482 continue 483 484 frac = 0 485 486 # q-value at the pixel (j,i) 487 q_value = q_data[npt] 488 data_n = data[npt] 489 490 ## No need to calculate the frac when all data are within range 491 if self.r_min >= self.r_max: 492 raise ValueError, "Limit Error: min > max" 493 494 if self.r_min <= q_value and q_value <= self.r_max: 495 frac = 1 496 if frac == 0: 497 continue 498 i_q = int(math.floor((q_value - self.r_min) / self.bin_width)) 499 500 # Take care of the edge case at phi = 2pi. 501 if i_q == nbins: 502 i_q = nbins - 1 503 y[i_q] += frac * data_n 504 # Take dqs from data to get the q_average 505 x[i_q] += frac * q_value 506 if err_data is None or err_data[npt] == 0.0: 507 if data_n < 0: 508 data_n = -data_n 509 err_y[i_q] += frac * frac * data_n 510 else: 511 err_y[i_q] += frac * frac * err_data[npt] * err_data[npt] 512 if dq_data is not None: 513 # To be consistent with dq calculation in 1d reduction, 514 # we need just the averages (not quadratures) because 515 # it should not depend on the number of the q points 516 # in the qr bins. 517 err_x[i_q] += frac * dq_data[npt] 518 else: 519 err_x = None 520 y_counts[i_q] += frac 521 522 # Average the sums 523 for n in range(nbins): 524 if err_y[n] < 0: 525 err_y[n] = -err_y[n] 526 err_y[n] = math.sqrt(err_y[n]) 527 #if err_x is not None: 528 # err_x[n] = math.sqrt(err_x[n]) 529 530 err_y = err_y / y_counts 531 err_y[err_y == 0] = np.average(err_y) 532 y = y / y_counts 533 x = x / y_counts 534 idx = (np.isfinite(y)) & (np.isfinite(x)) 535 536 if err_x is not None: 537 d_x = err_x[idx] / y_counts[idx] 538 else: 539 d_x = None 540 541 if not idx.any(): 542 msg = "Average Error: No points inside ROI to average..." 543 raise ValueError, msg 544 545 return Data1D(x=x[idx], y=y[idx], dy=err_y[idx], dx=d_x) 546 547 548 class Ring(object): 549 """ 550 Defines a ring on a 2D data set. 551 The ring is defined by r_min, r_max, and 552 the position of the center of the ring. 553 554 The data returned is the distribution of counts 555 around the ring as a function of phi. 556 557 Phi_min and phi_max should be defined between 0 and 2*pi 558 in anti-clockwise starting from the x- axis on the left-hand side 559 """ 560 #Todo: remove center. 561 def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0, nbins=36): 562 # Minimum radius 563 self.r_min = r_min 564 # Maximum radius 565 self.r_max = r_max 566 # Center of the ring in x 567 self.center_x = center_x 568 # Center of the ring in y 569 self.center_y = center_y 570 # Number of angular bins 571 self.nbins_phi = nbins 572 573 574 def __call__(self, data2D): 575 """ 576 Apply the ring to the data set. 577 Returns the angular distribution for a given q range 578 579 :param data2D: Data2D object 580 581 :return: Data1D object 582 """ 583 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 584 raise RuntimeError, "Ring averaging only take plottable_2D objects" 585 586 Pi = math.pi 587 588 # Get data 589 data = data2D.data[np.isfinite(data2D.data)] 590 q_data = data2D.q_data[np.isfinite(data2D.data)] 591 err_data = data2D.err_data[np.isfinite(data2D.data)] 592 qx_data = data2D.qx_data[np.isfinite(data2D.data)] 593 qy_data = data2D.qy_data[np.isfinite(data2D.data)] 594 595 # Set space for 1d outputs 596 phi_bins = np.zeros(self.nbins_phi) 597 phi_counts = np.zeros(self.nbins_phi) 598 phi_values = np.zeros(self.nbins_phi) 599 phi_err = np.zeros(self.nbins_phi) 600 601 # Shift to apply to calculated phi values in order 602 # to center first bin at zero 603 phi_shift = Pi / self.nbins_phi 604 605 for npt in range(len(data)): 606 frac = 0 607 # q-value at the point (npt) 608 q_value = q_data[npt] 609 data_n = data[npt] 610 611 # phi-value at the point (npt) 612 phi_value = math.atan2(qy_data[npt], qx_data[npt]) + Pi 613 614 if self.r_min <= q_value and q_value <= self.r_max: 615 frac = 1 616 if frac == 0: 617 continue 618 # binning 619 i_phi = int(math.floor((self.nbins_phi) * \ 620 (phi_value + phi_shift) / (2 * Pi))) 621 622 # Take care of the edge case at phi = 2pi. 623 if i_phi >= self.nbins_phi: 624 i_phi = 0 625 phi_bins[i_phi] += frac * data[npt] 626 627 if err_data is None or err_data[npt] == 0.0: 628 if data_n < 0: 629 data_n = -data_n 630 phi_err[i_phi] += frac * frac * math.fabs(data_n) 631 else: 632 phi_err[i_phi] += frac * frac * err_data[npt] * err_data[npt] 633 phi_counts[i_phi] += frac 634 635 for i in range(self.nbins_phi): 636 phi_bins[i] = phi_bins[i] / phi_counts[i] 637 phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i] 638 phi_values[i] = 2.0 * math.pi / self.nbins_phi * (1.0 * i) 639 640 idx = (np.isfinite(phi_bins)) 641 642 if not idx.any(): 643 msg = "Average Error: No points inside ROI to average..." 644 raise ValueError, msg 645 #elif len(phi_bins[idx])!= self.nbins_phi: 646 # print "resulted",self.nbins_phi- len(phi_bins[idx]) 647 #,"empty bin(s) due to tight binning..." 648 return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx]) 649 103 def get_intercept(q, q_0, q_1): 104 """ 105 Returns the fraction of the side at which the 106 q-value intercept the pixel, None otherwise. 107 The values returned is the fraction ON THE SIDE 108 OF THE LOWEST Q. :: 109 110 A B 111 +-----------+--------+ <--- pixel size 112 0 1 113 Q_0 -------- Q ----- Q_1 <--- equivalent Q range 114 if Q_1 > Q_0, A is returned 115 if Q_1 < Q_0, B is returned 116 if Q is outside the range of [Q_0, Q_1], None is returned 117 118 """ 119 if q_1 > q_0: 120 if q > q_0 and q <= q_1: 121 return (q - q_0) / (q_1 - q_0) 122 else: 123 if q > q_1 and q <= q_0: 124 return (q - q_1) / (q_0 - q_1) 125 return None 650 126 651 127 def get_pixel_fraction(qmax, q_00, q_01, q_10, q_11): … … 712 188 return frac_max 713 189 714 715 def get_intercept(q, q_0, q_1): 716 """ 717 Returns the fraction of the side at which the 718 q-value intercept the pixel, None otherwise. 719 The values returned is the fraction ON THE SIDE 720 OF THE LOWEST Q. :: 721 722 A B 723 +-----------+--------+ <--- pixel size 724 0 1 725 Q_0 -------- Q ----- Q_1 <--- equivalent Q range 726 if Q_1 > Q_0, A is returned 727 if Q_1 < Q_0, B is returned 728 if Q is outside the range of [Q_0, Q_1], None is returned 729 730 """ 731 if q_1 > q_0: 732 if q > q_0 and q <= q_1: 733 return (q - q_0) / (q_1 - q_0) 190 def get_dq_data(data2D): 191 ''' 192 Get the dq for resolution averaging 193 The pinholes and det. pix contribution present 194 in both direction of the 2D which must be subtracted when 195 converting to 1D: dq_overlap should calculated ideally at 196 q = 0. Note This method works on only pinhole geometry. 197 Extrapolate dqx(r) and dqy(phi) at q = 0, and take an average. 198 ''' 199 z_max = max(data2D.q_data) 200 z_min = min(data2D.q_data) 201 x_max = data2D.dqx_data[data2D.q_data[z_max]] 202 x_min = data2D.dqx_data[data2D.q_data[z_min]] 203 y_max = data2D.dqy_data[data2D.q_data[z_max]] 204 y_min = data2D.dqy_data[data2D.q_data[z_min]] 205 # Find qdx at q = 0 206 dq_overlap_x = (x_min * z_max - x_max * z_min) / (z_max - z_min) 207 # when extrapolation goes wrong 208 if dq_overlap_x > min(data2D.dqx_data): 209 dq_overlap_x = min(data2D.dqx_data) 210 dq_overlap_x *= dq_overlap_x 211 # Find qdx at q = 0 212 dq_overlap_y = (y_min * z_max - y_max * z_min) / (z_max - z_min) 213 # when extrapolation goes wrong 214 if dq_overlap_y > min(data2D.dqy_data): 215 dq_overlap_y = min(data2D.dqy_data) 216 # get dq at q=0. 217 dq_overlap_y *= dq_overlap_y 218 219 dq_overlap = np.sqrt((dq_overlap_x + dq_overlap_y) / 2.0) 220 # Final protection of dq 221 if dq_overlap < 0: 222 dq_overlap = y_min 223 dqx_data = data2D.dqx_data[np.isfinite(data2D.data)] 224 dqy_data = data2D.dqy_data[np.isfinite( 225 data2D.data)] - dq_overlap 226 # def; dqx_data = dq_r dqy_data = dq_phi 227 # Convert dq 2D to 1D here 228 dq_data = np.sqrt(dqx_data**2 + dqx_data**2) 229 return dq_data 230 231 ################################################################################ 232 233 def reader2D_converter(data2d=None): 234 """ 235 convert old 2d format opened by IhorReader or danse_reader 236 to new Data2D format 237 This is mainly used by the Readers 238 239 :param data2d: 2d array of Data2D object 240 :return: 1d arrays of Data2D object 241 242 """ 243 if data2d.data is None or data2d.x_bins is None or data2d.y_bins is None: 244 raise ValueError("Can't convert this data: data=None...") 245 new_x = np.tile(data2d.x_bins, (len(data2d.y_bins), 1)) 246 new_y = np.tile(data2d.y_bins, (len(data2d.x_bins), 1)) 247 new_y = new_y.swapaxes(0, 1) 248 249 new_data = data2d.data.flatten() 250 qx_data = new_x.flatten() 251 qy_data = new_y.flatten() 252 q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data) 253 if data2d.err_data is None or np.any(data2d.err_data <= 0): 254 new_err_data = np.sqrt(np.abs(new_data)) 734 255 else: 735 if q > q_1 and q <= q_0: 736 return (q - q_1) / (q_0 - q_1) 737 return None 256 new_err_data = data2d.err_data.flatten() 257 mask = np.ones(len(new_data), dtype=bool) 258 259 # TODO: make sense of the following two lines... 260 #from sas.sascalc.dataloader.data_info import Data2D 261 #output = Data2D() 262 output = data2d 263 output.data = new_data 264 output.err_data = new_err_data 265 output.qx_data = qx_data 266 output.qy_data = qy_data 267 output.q_data = q_data 268 output.mask = mask 269 270 return output 271 272 ################################################################################ 273 274 class Binning(object): 275 ''' 276 This class just creates a binning object 277 either linear or log 278 ''' 279 280 def __init__(self, min_value, max_value, n_bins, base=None): 281 ''' 282 if base is None: Linear binning 283 ''' 284 self.min = min_value if min_value > 0 else 0.0001 285 self.max = max_value 286 self.n_bins = n_bins 287 self.base = base 288 289 def get_bin_index(self, value): 290 ''' 291 The general formula logarithm binning is: 292 bin = floor(N * (log(x) - log(min)) / (log(max) - log(min))) 293 ''' 294 if self.base: 295 temp_x = self.n_bins * (math.log(value, self.base) - math.log(self.min, self.base)) 296 temp_y = math.log(self.max, self.base) - math.log(self.min, self.base) 297 else: 298 temp_x = self.n_bins * (value - self.min) 299 temp_y = self.max - self.min 300 # Bin index calulation 301 return int(math.floor(temp_x / temp_y)) 302 303 304 ################################################################################ 305 306 class _Slab(object): 307 """ 308 Compute average I(Q) for a region of interest 309 """ 310 311 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, 312 y_max=0.0, bin_width=0.001): 313 # Minimum Qx value [A-1] 314 self.x_min = x_min 315 # Maximum Qx value [A-1] 316 self.x_max = x_max 317 # Minimum Qy value [A-1] 318 self.y_min = y_min 319 # Maximum Qy value [A-1] 320 self.y_max = y_max 321 # Bin width (step size) [A-1] 322 self.bin_width = bin_width 323 # If True, I(|Q|) will be return, otherwise, 324 # negative q-values are allowed 325 self.fold = False 326 327 def __call__(self, data2D): 328 return NotImplemented 329 330 def _avg(self, data2D, maj): 331 """ 332 Compute average I(Q_maj) for a region of interest. 333 The major axis is defined as the axis of Q_maj. 334 The minor axis is the axis that we average over. 335 336 :param data2D: Data2D object 337 :param maj_min: min value on the major axis 338 :return: Data1D object 339 """ 340 if len(data2D.detector) > 1: 341 msg = "_Slab._avg: invalid number of " 342 msg += " detectors: %g" % len(data2D.detector) 343 raise RuntimeError(msg) 344 345 # Get data 346 data = data2D.data[np.isfinite(data2D.data)] 347 err_data = data2D.err_data[np.isfinite(data2D.data)] 348 qx_data = data2D.qx_data[np.isfinite(data2D.data)] 349 qy_data = data2D.qy_data[np.isfinite(data2D.data)] 350 351 # Build array of Q intervals 352 if maj == 'x': 353 if self.fold: 354 x_min = 0 355 else: 356 x_min = self.x_min 357 nbins = int(math.ceil((self.x_max - x_min) / self.bin_width)) 358 elif maj == 'y': 359 if self.fold: 360 y_min = 0 361 else: 362 y_min = self.y_min 363 nbins = int(math.ceil((self.y_max - y_min) / self.bin_width)) 364 else: 365 raise RuntimeError("_Slab._avg: unrecognized axis %s" % str(maj)) 366 367 x = np.zeros(nbins) 368 y = np.zeros(nbins) 369 err_y = np.zeros(nbins) 370 y_counts = np.zeros(nbins) 371 372 # Average pixelsize in q space 373 for npts in range(len(data)): 374 # default frac 375 frac_x = 0 376 frac_y = 0 377 # get ROI 378 if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]: 379 frac_x = 1 380 if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]: 381 frac_y = 1 382 frac = frac_x * frac_y 383 384 if frac == 0: 385 continue 386 # binning: find axis of q 387 if maj == 'x': 388 q_value = qx_data[npts] 389 min_value = x_min 390 if maj == 'y': 391 q_value = qy_data[npts] 392 min_value = y_min 393 if self.fold and q_value < 0: 394 q_value = -q_value 395 # bin 396 i_q = int(math.ceil((q_value - min_value) / self.bin_width)) - 1 397 398 # skip outside of max bins 399 if i_q < 0 or i_q >= nbins: 400 continue 401 402 # TODO: find better definition of x[i_q] based on q_data 403 # min_value + (i_q + 1) * self.bin_width / 2.0 404 x[i_q] += frac * q_value 405 y[i_q] += frac * data[npts] 406 407 if err_data is None or err_data[npts] == 0.0: 408 if data[npts] < 0: 409 data[npts] = -data[npts] 410 err_y[i_q] += frac * frac * data[npts] 411 else: 412 err_y[i_q] += frac * frac * err_data[npts] * err_data[npts] 413 y_counts[i_q] += frac 414 415 # Average the sums 416 for n in range(nbins): 417 err_y[n] = math.sqrt(err_y[n]) 418 419 err_y = err_y / y_counts 420 y = y / y_counts 421 x = x / y_counts 422 idx = (np.isfinite(y) & np.isfinite(x)) 423 424 if not idx.any(): 425 msg = "Average Error: No points inside ROI to average..." 426 raise ValueError(msg) 427 return Data1D(x=x[idx], y=y[idx], dy=err_y[idx]) 428 429 430 class SlabY(_Slab): 431 """ 432 Compute average I(Qy) for a region of interest 433 """ 434 435 def __call__(self, data2D): 436 """ 437 Compute average I(Qy) for a region of interest 438 439 :param data2D: Data2D object 440 :return: Data1D object 441 """ 442 return self._avg(data2D, 'y') 443 444 445 class SlabX(_Slab): 446 """ 447 Compute average I(Qx) for a region of interest 448 """ 449 450 def __call__(self, data2D): 451 """ 452 Compute average I(Qx) for a region of interest 453 :param data2D: Data2D object 454 :return: Data1D object 455 """ 456 return self._avg(data2D, 'x') 457 458 ################################################################################ 459 460 class Boxsum(object): 461 """ 462 Perform the sum of counts in a 2D region of interest. 463 """ 464 465 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 466 # Minimum Qx value [A-1] 467 self.x_min = x_min 468 # Maximum Qx value [A-1] 469 self.x_max = x_max 470 # Minimum Qy value [A-1] 471 self.y_min = y_min 472 # Maximum Qy value [A-1] 473 self.y_max = y_max 474 475 def __call__(self, data2D): 476 """ 477 Perform the sum in the region of interest 478 479 :param data2D: Data2D object 480 :return: number of counts, error on number of counts, 481 number of points summed 482 """ 483 y, err_y, y_counts = self._sum(data2D) 484 485 # Average the sums 486 counts = 0 if y_counts == 0 else y 487 error = 0 if y_counts == 0 else math.sqrt(err_y) 488 489 # Added y_counts to return, SMK & PDB, 04/03/2013 490 return counts, error, y_counts 491 492 def _sum(self, data2D): 493 """ 494 Perform the sum in the region of interest 495 496 :param data2D: Data2D object 497 :return: number of counts, 498 error on number of counts, number of entries summed 499 """ 500 if len(data2D.detector) > 1: 501 msg = "Circular averaging: invalid number " 502 msg += "of detectors: %g" % len(data2D.detector) 503 raise RuntimeError(msg) 504 # Get data 505 data = data2D.data[np.isfinite(data2D.data)] 506 err_data = data2D.err_data[np.isfinite(data2D.data)] 507 qx_data = data2D.qx_data[np.isfinite(data2D.data)] 508 qy_data = data2D.qy_data[np.isfinite(data2D.data)] 509 510 y = 0.0 511 err_y = 0.0 512 y_counts = 0.0 513 514 # Average pixelsize in q space 515 for npts in range(len(data)): 516 # default frac 517 frac_x = 0 518 frac_y = 0 519 520 # get min and max at each points 521 qx = qx_data[npts] 522 qy = qy_data[npts] 523 524 # get the ROI 525 if self.x_min <= qx and self.x_max > qx: 526 frac_x = 1 527 if self.y_min <= qy and self.y_max > qy: 528 frac_y = 1 529 # Find the fraction along each directions 530 frac = frac_x * frac_y 531 if frac == 0: 532 continue 533 y += frac * data[npts] 534 if err_data is None or err_data[npts] == 0.0: 535 if data[npts] < 0: 536 data[npts] = -data[npts] 537 err_y += frac * frac * data[npts] 538 else: 539 err_y += frac * frac * err_data[npts] * err_data[npts] 540 y_counts += frac 541 return y, err_y, y_counts 542 543 544 class Boxavg(Boxsum): 545 """ 546 Perform the average of counts in a 2D region of interest. 547 """ 548 549 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 550 super(Boxavg, self).__init__(x_min=x_min, x_max=x_max, 551 y_min=y_min, y_max=y_max) 552 553 def __call__(self, data2D): 554 """ 555 Perform the sum in the region of interest 556 557 :param data2D: Data2D object 558 :return: average counts, error on average counts 559 560 """ 561 y, err_y, y_counts = self._sum(data2D) 562 563 # Average the sums 564 counts = 0 if y_counts == 0 else y / y_counts 565 error = 0 if y_counts == 0 else math.sqrt(err_y) / y_counts 566 567 return counts, error 568 569 ################################################################################ 570 571 class CircularAverage(object): 572 """ 573 Perform circular averaging on 2D data 574 575 The data returned is the distribution of counts 576 as a function of Q 577 """ 578 579 def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005): 580 # Minimum radius included in the average [A-1] 581 self.r_min = r_min 582 # Maximum radius included in the average [A-1] 583 self.r_max = r_max 584 # Bin width (step size) [A-1] 585 self.bin_width = bin_width 586 587 def __call__(self, data2D, ismask=False): 588 """ 589 Perform circular averaging on the data 590 591 :param data2D: Data2D object 592 :return: Data1D object 593 """ 594 # Get data W/ finite values 595 data = data2D.data[np.isfinite(data2D.data)] 596 q_data = data2D.q_data[np.isfinite(data2D.data)] 597 err_data = data2D.err_data[np.isfinite(data2D.data)] 598 mask_data = data2D.mask[np.isfinite(data2D.data)] 599 600 dq_data = None 601 if data2D.dqx_data is not None and data2D.dqy_data is not None: 602 dq_data = get_dq_data(data2D) 603 604 if len(q_data) == 0: 605 msg = "Circular averaging: invalid q_data: %g" % data2D.q_data 606 raise RuntimeError(msg) 607 608 # Build array of Q intervals 609 nbins = int(math.ceil((self.r_max - self.r_min) / self.bin_width)) 610 611 x = np.zeros(nbins) 612 y = np.zeros(nbins) 613 err_y = np.zeros(nbins) 614 err_x = np.zeros(nbins) 615 y_counts = np.zeros(nbins) 616 617 for npt in range(len(data)): 618 619 if ismask and not mask_data[npt]: 620 continue 621 622 frac = 0 623 624 # q-value at the pixel (j,i) 625 q_value = q_data[npt] 626 data_n = data[npt] 627 628 # No need to calculate the frac when all data are within range 629 if self.r_min >= self.r_max: 630 raise ValueError("Limit Error: min > max") 631 632 if self.r_min <= q_value and q_value <= self.r_max: 633 frac = 1 634 if frac == 0: 635 continue 636 i_q = int(math.floor((q_value - self.r_min) / self.bin_width)) 637 638 # Take care of the edge case at phi = 2pi. 639 if i_q == nbins: 640 i_q = nbins - 1 641 y[i_q] += frac * data_n 642 # Take dqs from data to get the q_average 643 x[i_q] += frac * q_value 644 if err_data is None or err_data[npt] == 0.0: 645 if data_n < 0: 646 data_n = -data_n 647 err_y[i_q] += frac * frac * data_n 648 else: 649 err_y[i_q] += frac * frac * err_data[npt] * err_data[npt] 650 if dq_data is not None: 651 # To be consistent with dq calculation in 1d reduction, 652 # we need just the averages (not quadratures) because 653 # it should not depend on the number of the q points 654 # in the qr bins. 655 err_x[i_q] += frac * dq_data[npt] 656 else: 657 err_x = None 658 y_counts[i_q] += frac 659 660 # Average the sums 661 for n in range(nbins): 662 if err_y[n] < 0: 663 err_y[n] = -err_y[n] 664 err_y[n] = math.sqrt(err_y[n]) 665 # if err_x is not None: 666 # err_x[n] = math.sqrt(err_x[n]) 667 668 err_y = err_y / y_counts 669 err_y[err_y == 0] = np.average(err_y) 670 y = y / y_counts 671 x = x / y_counts 672 idx = (np.isfinite(y)) & (np.isfinite(x)) 673 674 if err_x is not None: 675 d_x = err_x[idx] / y_counts[idx] 676 else: 677 d_x = None 678 679 if not idx.any(): 680 msg = "Average Error: No points inside ROI to average..." 681 raise ValueError(msg) 682 683 return Data1D(x=x[idx], y=y[idx], dy=err_y[idx], dx=d_x) 684 685 ################################################################################ 686 687 class Ring(object): 688 """ 689 Defines a ring on a 2D data set. 690 The ring is defined by r_min, r_max, and 691 the position of the center of the ring. 692 693 The data returned is the distribution of counts 694 around the ring as a function of phi. 695 696 Phi_min and phi_max should be defined between 0 and 2*pi 697 in anti-clockwise starting from the x- axis on the left-hand side 698 """ 699 # Todo: remove center. 700 701 def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0, nbins=36): 702 # Minimum radius 703 self.r_min = r_min 704 # Maximum radius 705 self.r_max = r_max 706 # Center of the ring in x 707 self.center_x = center_x 708 # Center of the ring in y 709 self.center_y = center_y 710 # Number of angular bins 711 self.nbins_phi = nbins 712 713 def __call__(self, data2D): 714 """ 715 Apply the ring to the data set. 716 Returns the angular distribution for a given q range 717 718 :param data2D: Data2D object 719 720 :return: Data1D object 721 """ 722 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 723 raise RuntimeError("Ring averaging only take plottable_2D objects") 724 725 Pi = math.pi 726 727 # Get data 728 data = data2D.data[np.isfinite(data2D.data)] 729 q_data = data2D.q_data[np.isfinite(data2D.data)] 730 err_data = data2D.err_data[np.isfinite(data2D.data)] 731 qx_data = data2D.qx_data[np.isfinite(data2D.data)] 732 qy_data = data2D.qy_data[np.isfinite(data2D.data)] 733 734 # Set space for 1d outputs 735 phi_bins = np.zeros(self.nbins_phi) 736 phi_counts = np.zeros(self.nbins_phi) 737 phi_values = np.zeros(self.nbins_phi) 738 phi_err = np.zeros(self.nbins_phi) 739 740 # Shift to apply to calculated phi values in order 741 # to center first bin at zero 742 phi_shift = Pi / self.nbins_phi 743 744 for npt in range(len(data)): 745 frac = 0 746 # q-value at the point (npt) 747 q_value = q_data[npt] 748 data_n = data[npt] 749 750 # phi-value at the point (npt) 751 phi_value = math.atan2(qy_data[npt], qx_data[npt]) + Pi 752 753 if self.r_min <= q_value and q_value <= self.r_max: 754 frac = 1 755 if frac == 0: 756 continue 757 # binning 758 i_phi = int(math.floor((self.nbins_phi) * 759 (phi_value + phi_shift) / (2 * Pi))) 760 761 # Take care of the edge case at phi = 2pi. 762 if i_phi >= self.nbins_phi: 763 i_phi = 0 764 phi_bins[i_phi] += frac * data[npt] 765 766 if err_data is None or err_data[npt] == 0.0: 767 if data_n < 0: 768 data_n = -data_n 769 phi_err[i_phi] += frac * frac * math.fabs(data_n) 770 else: 771 phi_err[i_phi] += frac * frac * err_data[npt] * err_data[npt] 772 phi_counts[i_phi] += frac 773 774 for i in range(self.nbins_phi): 775 phi_bins[i] = phi_bins[i] / phi_counts[i] 776 phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i] 777 phi_values[i] = 2.0 * math.pi / self.nbins_phi * (1.0 * i) 778 779 idx = (np.isfinite(phi_bins)) 780 781 if not idx.any(): 782 msg = "Average Error: No points inside ROI to average..." 783 raise ValueError(msg) 784 # elif len(phi_bins[idx])!= self.nbins_phi: 785 # print "resulted",self.nbins_phi- len(phi_bins[idx]) 786 #,"empty bin(s) due to tight binning..." 787 return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx]) 738 788 739 789 … … 750 800 starting from the x- axis on the left-hand side 751 801 """ 752 def __init__(self, r_min, r_max, phi_min=0, phi_max=2 * math.pi, nbins=20): 802 803 def __init__(self, r_min, r_max, phi_min=0, phi_max=2 * math.pi, nbins=20, 804 base=None): 805 ''' 806 :param base: must be a valid base for an algorithm, i.e., 807 a positive number 808 ''' 753 809 self.r_min = r_min 754 810 self.r_max = r_max … … 756 812 self.phi_max = phi_max 757 813 self.nbins = nbins 814 self.base = base 758 815 759 816 def _agv(self, data2D, run='phi'): … … 767 824 """ 768 825 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 769 raise RuntimeError, "Ring averaging only take plottable_2D objects" 770 Pi = math.pi 826 raise RuntimeError("Ring averaging only take plottable_2D objects") 771 827 772 828 # Get the all data & info … … 776 832 qx_data = data2D.qx_data[np.isfinite(data2D.data)] 777 833 qy_data = data2D.qy_data[np.isfinite(data2D.data)] 834 778 835 dq_data = None 779 780 # Get the dq for resolution averaging781 836 if data2D.dqx_data is not None and data2D.dqy_data is not None: 782 # The pinholes and det. pix contribution present 783 # in both direction of the 2D which must be subtracted when 784 # converting to 1D: dq_overlap should calculated ideally at 785 # q = 0. 786 # Extrapolate dqy(perp) at q = 0 787 z_max = max(data2D.q_data) 788 z_min = min(data2D.q_data) 789 x_max = data2D.dqx_data[data2D.q_data[z_max]] 790 x_min = data2D.dqx_data[data2D.q_data[z_min]] 791 y_max = data2D.dqy_data[data2D.q_data[z_max]] 792 y_min = data2D.dqy_data[data2D.q_data[z_min]] 793 # Find qdx at q = 0 794 dq_overlap_x = ((x_min * z_max - x_max * z_min) / 795 (z_max - z_min)) 796 # when extrapolation goes wrong 797 if dq_overlap_x > min(data2D.dqx_data): 798 dq_overlap_x = min(data2D.dqx_data) 799 dq_overlap_x *= dq_overlap_x 800 # Find qdx at q = 0 801 dq_overlap_y = ((y_min * z_max - y_max * z_min) / 802 (z_max - z_min)) 803 # when extrapolation goes wrong 804 if dq_overlap_y > min(data2D.dqy_data): 805 dq_overlap_y = min(data2D.dqy_data) 806 # get dq at q=0. 807 dq_overlap_y *= dq_overlap_y 808 809 dq_overlap = np.sqrt((dq_overlap_x + dq_overlap_y) / 2.0) 810 if dq_overlap < 0: 811 dq_overlap = y_min 812 dqx_data = data2D.dqx_data[np.isfinite(data2D.data)] 813 dqy_data = data2D.dqy_data[np.isfinite(data2D.data)] - dq_overlap 814 # def; dqx_data = dq_r dqy_data = dq_phi 815 # Convert dq 2D to 1D here 816 dqx = dqx_data * dqx_data 817 dqy = dqy_data * dqy_data 818 dq_data = np.add(dqx, dqy) 819 dq_data = np.sqrt(dq_data) 820 821 #set space for 1d outputs 837 dq_data = get_dq_data(data2D) 838 839 # set space for 1d outputs 822 840 x = np.zeros(self.nbins) 823 841 y = np.zeros(self.nbins) 824 842 y_err = np.zeros(self.nbins) 825 843 x_err = np.zeros(self.nbins) 826 y_counts = np.zeros(self.nbins) 844 y_counts = np.zeros(self.nbins) # Cycle counts (for the mean) 827 845 828 846 # Get the min and max into the region: 0 <= phi < 2Pi … … 830 848 phi_max = flip_phi(self.phi_max) 831 849 850 # binning object 851 if run.lower() == 'phi': 852 binning = Binning(self.phi_min, self.phi_max, self.nbins, self.base) 853 else: 854 binning = Binning(self.r_min, self.r_max, self.nbins, self.base) 855 832 856 for n in range(len(data)): 833 frac = 0834 857 835 858 # q-value at the pixel (j,i) … … 841 864 842 865 # phi-value of the pixel (j,i) 843 phi_value = math.atan2(qy_data[n], qx_data[n]) + Pi 844 845 ## No need to calculate the frac when all data are within range 846 if self.r_min <= q_value and q_value <= self.r_max: 847 frac = 1 848 if frac == 0: 866 phi_value = math.atan2(qy_data[n], qx_data[n]) + math.pi 867 868 # No need to calculate: data outside of the radius 869 if self.r_min > q_value or q_value > self.r_max: 849 870 continue 850 #In case of two ROIs (symmetric major and minor regions)(for 'q2') 871 872 # In case of two ROIs (symmetric major and minor regions)(for 'q2') 851 873 if run.lower() == 'q2': 852 # #For minor sector wing874 # For minor sector wing 853 875 # Calculate the minor wing phis 854 phi_min_minor = flip_phi(phi_min - Pi)855 phi_max_minor = flip_phi(phi_max - Pi)876 phi_min_minor = flip_phi(phi_min - math.pi) 877 phi_max_minor = flip_phi(phi_max - math.pi) 856 878 # Check if phis of the minor ring is within 0 to 2pi 857 879 if phi_min_minor > phi_max_minor: 858 is_in = (phi_value > phi_min_minor or \859 880 is_in = (phi_value > phi_min_minor or 881 phi_value < phi_max_minor) 860 882 else: 861 is_in = (phi_value > phi_min_minor and \862 863 864 # For all cases(i.e.,for 'q', 'q2', and 'phi')865 # Find pixels within ROI883 is_in = (phi_value > phi_min_minor and 884 phi_value < phi_max_minor) 885 886 # For all cases(i.e.,for 'q', 'q2', and 'phi') 887 # Find pixels within ROI 866 888 if phi_min > phi_max: 867 is_in = is_in or (phi_value > phi_min or \868 889 is_in = is_in or (phi_value > phi_min or 890 phi_value < phi_max) 869 891 else: 870 is_in = is_in or (phi_value >= phi_min and \ 871 phi_value < phi_max) 872 892 is_in = is_in or (phi_value >= phi_min and 893 phi_value < phi_max) 894 895 # data oustide of the phi range 873 896 if not is_in: 874 frac = 0875 if frac == 0:876 897 continue 877 # Check which type of averaging we need 898 899 # Get the binning index 878 900 if run.lower() == 'phi': 879 temp_x = (self.nbins) * (phi_value - self.phi_min) 880 temp_y = (self.phi_max - self.phi_min) 881 i_bin = int(math.floor(temp_x / temp_y)) 901 i_bin = binning.get_bin_index(phi_value) 882 902 else: 883 temp_x = (self.nbins) * (q_value - self.r_min) 884 temp_y = (self.r_max - self.r_min) 885 i_bin = int(math.floor(temp_x / temp_y)) 903 i_bin = binning.get_bin_index(q_value) 886 904 887 905 # Take care of the edge case at phi = 2pi. … … 889 907 i_bin = self.nbins - 1 890 908 891 # #Get the total y892 y[i_bin] += frac *data_n893 x[i_bin] += frac *q_value909 # Get the total y 910 y[i_bin] += data_n 911 x[i_bin] += q_value 894 912 if err_data[n] is None or err_data[n] == 0.0: 895 913 if data_n < 0: 896 914 data_n = -data_n 897 y_err[i_bin] += frac * frac *data_n915 y_err[i_bin] += data_n 898 916 else: 899 y_err[i_bin] += frac * frac * err_data[n] * err_data[n]917 y_err[i_bin] += err_data[n]**2 900 918 901 919 if dq_data is not None: … … 904 922 # it should not depend on the number of the q points 905 923 # in the qr bins. 906 x_err[i_bin] += frac *dq_data[n]924 x_err[i_bin] += dq_data[n] 907 925 else: 908 926 x_err = None 909 y_counts[i_bin] += frac927 y_counts[i_bin] += 1 910 928 911 929 # Organize the results … … 922 940 # We take the center of ring area, not radius. 923 941 # This is more accurate than taking the radial center of ring. 924 # delta_r = (self.r_max - self.r_min) / self.nbins925 # r_inner = self.r_min + delta_r * i926 # r_outer = r_inner + delta_r927 # x[i] = math.sqrt((r_inner * r_inner + r_outer * r_outer) / 2)942 # delta_r = (self.r_max - self.r_min) / self.nbins 943 # r_inner = self.r_min + delta_r * i 944 # r_outer = r_inner + delta_r 945 # x[i] = math.sqrt((r_inner * r_inner + r_outer * r_outer) / 2) 928 946 x[i] = x[i] / y_counts[i] 929 947 y_err[y_err == 0] = np.average(y_err) … … 935 953 if not idx.any(): 936 954 msg = "Average Error: No points inside sector of ROI to average..." 937 raise ValueError , msg938 # elif len(y[idx])!= self.nbins:955 raise ValueError(msg) 956 # elif len(y[idx])!= self.nbins: 939 957 # print "resulted",self.nbins- len(y[idx]), 940 # "empty bin(s) due to tight binning..."958 # "empty bin(s) due to tight binning..." 941 959 return Data1D(x=x[idx], y=y[idx], dy=y_err[idx], dx=d_x) 942 960 … … 950 968 The number of bin in phi also has to be defined. 951 969 """ 970 952 971 def __call__(self, data2D): 953 972 """ … … 969 988 The number of bin in Q also has to be defined. 970 989 """ 990 971 991 def __call__(self, data2D): 972 992 """ … … 979 999 return self._agv(data2D, 'q2') 980 1000 1001 ################################################################################ 981 1002 982 1003 class Ringcut(object): … … 991 1012 in anti-clockwise starting from the x- axis on the left-hand side 992 1013 """ 1014 993 1015 def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0): 994 1016 # Minimum radius … … 1011 1033 """ 1012 1034 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 1013 raise RuntimeError , "Ring cut only take plottable_2D objects"1035 raise RuntimeError("Ring cut only take plottable_2D objects") 1014 1036 1015 1037 # Get data … … 1022 1044 return out 1023 1045 1046 ################################################################################ 1024 1047 1025 1048 class Boxcut(object): … … 1027 1050 Find a rectangular 2D region of interest. 1028 1051 """ 1052 1029 1053 def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 1030 1054 # Minimum Qx value [A-1] … … 1059 1083 """ 1060 1084 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 1061 raise RuntimeError , "Boxcut take only plottable_2D objects"1085 raise RuntimeError("Boxcut take only plottable_2D objects") 1062 1086 # Get qx_ and qy_data 1063 1087 qx_data = data2D.qx_data … … 1070 1094 return outx & outy 1071 1095 1096 ################################################################################ 1072 1097 1073 1098 class Sectorcut(object): … … 1081 1106 and (phi_max-phi_min) should not be larger than pi 1082 1107 """ 1108 1083 1109 def __init__(self, phi_min=0, phi_max=math.pi): 1084 1110 self.phi_min = phi_min … … 1110 1136 """ 1111 1137 if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 1112 raise RuntimeError , "Sectorcut take only plottable_2D objects"1138 raise RuntimeError("Sectorcut take only plottable_2D objects") 1113 1139 Pi = math.pi 1114 1140 # Get data … … 1124 1150 # check for major sector 1125 1151 if phi_min_major > phi_max_major: 1126 out_major = (phi_min_major <= phi_data) + (phi_max_major > phi_data) 1152 out_major = (phi_min_major <= phi_data) + \ 1153 (phi_max_major > phi_data) 1127 1154 else: 1128 out_major = (phi_min_major <= phi_data) & (phi_max_major > phi_data) 1155 out_major = (phi_min_major <= phi_data) & ( 1156 phi_max_major > phi_data) 1129 1157 1130 1158 # minor sector … … 1136 1164 if phi_min_minor > phi_max_minor: 1137 1165 out_minor = (phi_min_minor <= phi_data) + \ 1138 1166 (phi_max_minor >= phi_data) 1139 1167 else: 1140 1168 out_minor = (phi_min_minor <= phi_data) & \ 1141 1169 (phi_max_minor >= phi_data) 1142 1170 out = out_major + out_minor 1143 1171 -
src/sas/sascalc/dataloader/readers/sesans_reader.py
r9a5097c r149b8f6 1 1 """ 2 2 SESANS reader (based on ASCII reader) 3 3 4 4 Reader for .ses or .sesans file format 5 6 Jurrian Bakker 5 6 Jurrian Bakker 7 7 """ 8 8 import numpy as np … … 18 18 _ZERO = 1e-16 19 19 20 20 21 class Reader: 21 22 """ 22 23 Class to load sesans files (6 columns). 23 24 """ 24 # #File type25 # File type 25 26 type_name = "SESANS" 26 27 # #Wildcards27 28 # Wildcards 28 29 type = ["SESANS files (*.ses)|*.ses", 29 30 "SESANS files (*..sesans)|*.sesans"] 30 # #List of allowed extensions31 # List of allowed extensions 31 32 ext = ['.ses', '.SES', '.sesans', '.SESANS'] 32 33 # #Flag to bypass extension check33 34 # Flag to bypass extension check 34 35 allow_all = True 35 36 36 37 def read(self, path): 37 38 # print "reader triggered"39 40 38 """ 41 39 Load data file 42 40 43 41 :param path: file path 44 42 45 43 :return: SESANSData1D object, or None 46 44 47 45 :raise RuntimeError: when the file can't be opened 48 46 :raise ValueError: when the length of the data vectors are inconsistent … … 51 49 basename = os.path.basename(path) 52 50 _, extension = os.path.splitext(basename) 53 if self.allow_all or extension.lower() in self.ext: 54 try: 55 # Read in binary mode since GRASP frequently has no-ascii 56 # characters that brakes the open operation 57 input_f = open(path,'rb') 58 except: 59 raise RuntimeError, "sesans_reader: cannot open %s" % path 60 buff = input_f.read() 61 lines = buff.splitlines() 62 x = np.zeros(0) 63 y = np.zeros(0) 64 dy = np.zeros(0) 65 lam = np.zeros(0) 66 dlam = np.zeros(0) 67 dx = np.zeros(0) 68 69 #temp. space to sort data 70 tx = np.zeros(0) 71 ty = np.zeros(0) 72 tdy = np.zeros(0) 73 tlam = np.zeros(0) 74 tdlam = np.zeros(0) 75 tdx = np.zeros(0) 76 output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, isSesans=True) 77 self.filename = output.filename = basename 51 if not (self.allow_all or extension.lower() in self.ext): 52 raise RuntimeError( 53 "{} has an unrecognized file extension".format(path)) 54 else: 55 raise RuntimeError("{} is not a file".format(path)) 56 with open(path, 'r') as input_f: 57 line = input_f.readline() 58 params = {} 59 while not line.startswith("BEGIN_DATA"): 60 terms = line.split() 61 if len(terms) >= 2: 62 params[terms[0]] = " ".join(terms[1:]) 63 line = input_f.readline() 64 self.params = params 78 65 79 paramnames=[] 80 paramvals=[] 81 zvals=[] 82 dzvals=[] 83 lamvals=[] 84 dlamvals=[] 85 Pvals=[] 86 dPvals=[] 66 if "FileFormatVersion" not in self.params: 67 raise RuntimeError("SES file missing FileFormatVersion") 68 if float(self.params["FileFormatVersion"]) >= 2.0: 69 raise RuntimeError("SASView only supports SES version 1") 87 70 88 for line in lines: 89 # Initial try for CSV (split on ,) 90 line=line.strip() 91 toks = line.split('\t') 92 if len(toks)==2: 93 paramnames.append(toks[0]) 94 paramvals.append(toks[1]) 95 if len(toks)>5: 96 zvals.append(toks[0]) 97 dzvals.append(toks[3]) 98 lamvals.append(toks[4]) 99 dlamvals.append(toks[5]) 100 Pvals.append(toks[1]) 101 dPvals.append(toks[2]) 102 else: 103 continue 71 if "SpinEchoLength_unit" not in self.params: 72 raise RuntimeError("SpinEchoLength has no units") 73 if "Wavelength_unit" not in self.params: 74 raise RuntimeError("Wavelength has no units") 75 if params["SpinEchoLength_unit"] != params["Wavelength_unit"]: 76 raise RuntimeError("The spin echo data has rudely used " 77 "different units for the spin echo length " 78 "and the wavelength. While sasview could " 79 "handle this instance, it is a violation " 80 "of the file format and will not be " 81 "handled by other software.") 104 82 105 x=[] 106 y=[] 107 lam=[] 108 dx=[] 109 dy=[] 110 dlam=[] 111 lam_header = lamvals[0].split() 112 data_conv_z = None 113 default_z_unit = "A" 114 data_conv_P = None 115 default_p_unit = " " # Adjust unit for axis (L^-3) 116 lam_unit = lam_header[1].replace("[","").replace("]","") 117 if lam_unit == 'AA': 118 lam_unit = 'A' 119 varheader=[zvals[0],dzvals[0],lamvals[0],dlamvals[0],Pvals[0],dPvals[0]] 120 valrange=range(1, len(zvals)) 121 for i in valrange: 122 x.append(float(zvals[i])) 123 y.append(float(Pvals[i])) 124 lam.append(float(lamvals[i])) 125 dy.append(float(dPvals[i])) 126 dx.append(float(dzvals[i])) 127 dlam.append(float(dlamvals[i])) 83 headers = input_f.readline().split() 128 84 129 x,y,lam,dy,dx,dlam = [130 np.asarray(v, 'double')131 for v in (x,y,lam,dy,dx,dlam)132 ]85 self._insist_header(headers, "SpinEchoLength") 86 self._insist_header(headers, "Depolarisation") 87 self._insist_header(headers, "Depolarisation_error") 88 self._insist_header(headers, "Wavelength") 133 89 134 input_f.close()90 data = np.loadtxt(input_f) 135 91 136 output.x, output.x_unit = self._unit_conversion(x, lam_unit, default_z_unit) 137 output.y = y 138 output.y_unit = r'\AA^{-2} cm^{-1}' # output y_unit added 139 output.dx, output.dx_unit = self._unit_conversion(dx, lam_unit, default_z_unit) 140 output.dy = dy 141 output.lam, output.lam_unit = self._unit_conversion(lam, lam_unit, default_z_unit) 142 output.dlam, output.dlam_unit = self._unit_conversion(dlam, lam_unit, default_z_unit) 143 144 output.xaxis(r"\rm{z}", output.x_unit) 145 output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", output.y_unit) # Adjust label to ln P/(lam^2 t), remove lam column refs 92 if data.shape[1] != len(headers): 93 raise RuntimeError( 94 "File has {} headers, but {} columns".format( 95 len(headers), 96 data.shape[1])) 146 97 147 # Store loading process information 148 output.meta_data['loader'] = self.type_name 149 #output.sample.thickness = float(paramvals[6]) 150 output.sample.name = paramvals[1] 151 output.sample.ID = paramvals[0] 152 zaccept_unit_split = paramnames[7].split("[") 153 zaccept_unit = zaccept_unit_split[1].replace("]","") 154 if zaccept_unit.strip() == r'\AA^-1' or zaccept_unit.strip() == r'\A^-1': 155 zaccept_unit = "1/A" 156 output.sample.zacceptance=(float(paramvals[7]),zaccept_unit) 157 output.vars = varheader 98 if not data.size: 99 raise RuntimeError("{} is empty".format(path)) 100 x = data[:, headers.index("SpinEchoLength")] 101 if "SpinEchoLength_error" in headers: 102 dx = data[:, headers.index("SpinEchoLength_error")] 103 else: 104 dx = x * 0.05 105 lam = data[:, headers.index("Wavelength")] 106 if "Wavelength_error" in headers: 107 dlam = data[:, headers.index("Wavelength_error")] 108 else: 109 dlam = lam * 0.05 110 y = data[:, headers.index("Depolarisation")] 111 dy = data[:, headers.index("Depolarisation_error")] 158 112 159 if len(output.x) < 1: 160 raise RuntimeError, "%s is empty" % path 161 return output 113 lam_unit = self._unit_fetch("Wavelength") 114 x, x_unit = self._unit_conversion(x, "A", 115 self._unit_fetch( 116 "SpinEchoLength")) 117 dx, dx_unit = self._unit_conversion( 118 dx, lam_unit, 119 self._unit_fetch("SpinEchoLength")) 120 dlam, dlam_unit = self._unit_conversion( 121 dlam, lam_unit, 122 self._unit_fetch("Wavelength")) 123 y_unit = self._unit_fetch("Depolarisation") 162 124 163 else: 164 raise RuntimeError, "%s is not a file" % path 165 return None 125 output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, 126 isSesans=True) 166 127 167 def _unit_conversion(self, value, value_unit, default_unit): 168 if has_converter == True and value_unit != default_unit: 169 data_conv_q = Converter(value_unit) 170 value = data_conv_q(value, units=default_unit) 128 output.y_unit = y_unit 129 output.x_unit = x_unit 130 output.source.wavelength_unit = lam_unit 131 output.source.wavelength = lam 132 self.filename = output.filename = basename 133 output.xaxis(r"\rm{z}", x_unit) 134 # Adjust label to ln P/(lam^2 t), remove lam column refs 135 output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", y_unit) 136 # Store loading process information 137 output.meta_data['loader'] = self.type_name 138 output.sample.name = params["Sample"] 139 output.sample.ID = params["DataFileTitle"] 140 output.sample.thickness = self._unit_conversion( 141 float(params["Thickness"]), "cm", 142 self._unit_fetch("Thickness"))[0] 143 144 output.sample.zacceptance = ( 145 float(params["Theta_zmax"]), 146 self._unit_fetch("Theta_zmax")) 147 148 output.sample.yacceptance = ( 149 float(params["Theta_ymax"]), 150 self._unit_fetch("Theta_ymax")) 151 return output 152 153 @staticmethod 154 def _insist_header(headers, name): 155 if name not in headers: 156 raise RuntimeError( 157 "Missing {} column in spin echo data".format(name)) 158 159 @staticmethod 160 def _unit_conversion(value, value_unit, default_unit): 161 """ 162 Performs unit conversion on a measurement. 163 164 :param value: The magnitude of the measurement 165 :param value_unit: a string containing the final desired unit 166 :param default_unit: string with the units of the original measurement 167 :return: The magnitude of the measurement in the new units 168 """ 169 # (float, string, string) -> float 170 if has_converter and value_unit != default_unit: 171 data_conv_q = Converter(default_unit) 172 value = data_conv_q(value, units=value_unit) 171 173 new_unit = default_unit 172 174 else: 173 175 new_unit = value_unit 174 176 return value, new_unit 177 178 def _unit_fetch(self, unit): 179 return self.params[unit+"_unit"] -
src/sas/sasgui/perspectives/fitting/models.py
ra1b8fee r81b1f4d 163 163 164 164 165 def _find Models(dir):165 def _find_models(): 166 166 """ 167 167 Find custom models 168 168 """ 169 169 # List of plugin objects 170 dir = find_plugins_dir()170 directory = find_plugins_dir() 171 171 # Go through files in plug-in directory 172 if not os.path.isdir(dir ):173 msg = "SasView couldn't locate Model plugin folder %r." % dir 172 if not os.path.isdir(directory): 173 msg = "SasView couldn't locate Model plugin folder %r." % directory 174 174 logger.warning(msg) 175 175 return {} 176 176 177 plugin_log("looking for models in: %s" % str(dir ))178 # compile_file(dir) #always recompile the folder plugin179 logger.info("plugin model dir: %s" % str(dir ))177 plugin_log("looking for models in: %s" % str(directory)) 178 # compile_file(directory) #always recompile the folder plugin 179 logger.info("plugin model dir: %s" % str(directory)) 180 180 181 181 plugins = {} 182 for filename in os.listdir(dir ):182 for filename in os.listdir(directory): 183 183 name, ext = os.path.splitext(filename) 184 184 if ext == '.py' and not name == '__init__': 185 path = os.path.abspath(os.path.join(dir , filename))185 path = os.path.abspath(os.path.join(directory, filename)) 186 186 try: 187 187 model = load_custom_model(path) … … 193 193 plugin_log(msg) 194 194 logger.warning("Failed to load plugin %r. See %s for details" 195 196 195 % (path, PLUGIN_LOG)) 196 197 197 return plugins 198 198 … … 264 264 temp = {} 265 265 if self.is_changed(): 266 return _find Models(dir)266 return _find_models() 267 267 logger.info("plugin model : %s" % str(temp)) 268 268 return temp … … 339 339 """ 340 340 self.plugins = [] 341 new_plugins = _find Models(dir)341 new_plugins = _find_models() 342 342 for name, plug in new_plugins.iteritems(): 343 343 for stored_name, stored_plug in self.stored_plugins.iteritems(): -
test/sasdataloader/test/utest_averaging.py
r9a5097c re123eb9 1 1 2 import math 3 import os 2 4 import unittest 3 import math 4 5 from sas.sascalc.dataloader.loader import Loader 6 from sas.sascalc.dataloader.manipulations import Ring, CircularAverage, SectorPhi, get_q,reader2D_converter 7 5 from scipy.stats import binned_statistic_2d 8 6 import numpy as np 7 9 8 import sas.sascalc.dataloader.data_info as data_info 9 from sas.sascalc.dataloader.loader import Loader 10 from sas.sascalc.dataloader.manipulations import (Boxavg, Boxsum, 11 CircularAverage, Ring, 12 SectorPhi, SectorQ, SlabX, 13 SlabY, get_q, 14 reader2D_converter) 15 10 16 11 17 class Averaging(unittest.TestCase): … … 13 19 Test averaging manipulations on a flat distribution 14 20 """ 21 15 22 def setUp(self): 16 23 """ … … 18 25 should return the predefined height of the distribution (1.0). 19 26 """ 20 x_0 = np.ones([100,100])21 dx_0 = np.ones([100, 100])22 27 x_0 = np.ones([100, 100]) 28 dx_0 = np.ones([100, 100]) 29 23 30 self.data = data_info.Data2D(data=x_0, err_data=dx_0) 24 31 detector = data_info.Detector() 25 detector.distance = 1000.0 # mm26 detector.pixel_size.x = 1.0 #mm27 detector.pixel_size.y = 1.0 #mm28 32 detector.distance = 1000.0 # mm 33 detector.pixel_size.x = 1.0 # mm 34 detector.pixel_size.y = 1.0 # mm 35 29 36 # center in pixel position = (len(x_0)-1)/2 30 detector.beam_center.x = (len(x_0) -1)/2 #pixel number31 detector.beam_center.y = (len(x_0) -1)/2 #pixel number37 detector.beam_center.x = (len(x_0) - 1) / 2 # pixel number 38 detector.beam_center.y = (len(x_0) - 1) / 2 # pixel number 32 39 self.data.detector.append(detector) 33 40 34 41 source = data_info.Source() 35 source.wavelength = 10.0 #A42 source.wavelength = 10.0 # A 36 43 self.data.source = source 37 38 # get_q(dx, dy, det_dist, wavelength) where units are mm,mm,mm,and A respectively. 44 45 # get_q(dx, dy, det_dist, wavelength) where units are mm,mm,mm,and A 46 # respectively. 39 47 self.qmin = get_q(1.0, 1.0, detector.distance, source.wavelength) 40 48 41 49 self.qmax = get_q(49.5, 49.5, detector.distance, source.wavelength) 42 50 43 51 self.qstep = len(x_0) 44 x = np.linspace(start= -1*self.qmax,45 stop=self.qmax,46 num=self.qstep,47 endpoint=True )48 y = np.linspace(start= -1*self.qmax,49 stop=self.qmax,50 num=self.qstep,51 endpoint=True)52 self.data.x_bins =x53 self.data.y_bins =y52 x = np.linspace(start=-1 * self.qmax, 53 stop=self.qmax, 54 num=self.qstep, 55 endpoint=True) 56 y = np.linspace(start=-1 * self.qmax, 57 stop=self.qmax, 58 num=self.qstep, 59 endpoint=True) 60 self.data.x_bins = x 61 self.data.y_bins = y 54 62 self.data = reader2D_converter(self.data) 55 63 56 64 def test_ring_flat_distribution(self): 57 65 """ 58 66 Test ring averaging 59 67 """ 60 r = Ring(r_min=2 *self.qmin, r_max=5*self.qmin,61 center_x=self.data.detector[0].beam_center.x, 68 r = Ring(r_min=2 * self.qmin, r_max=5 * self.qmin, 69 center_x=self.data.detector[0].beam_center.x, 62 70 center_y=self.data.detector[0].beam_center.y) 63 71 r.nbins_phi = 20 64 72 65 73 o = r(self.data) 66 74 for i in range(20): 67 75 self.assertEqual(o.y[i], 1.0) 68 76 69 77 def test_sectorphi_full(self): 70 78 """ 71 79 Test sector averaging 72 80 """ 73 r = SectorPhi(r_min=self.qmin, r_max=3 *self.qmin,74 phi_min=0, phi_max=math.pi *2.0)81 r = SectorPhi(r_min=self.qmin, r_max=3 * self.qmin, 82 phi_min=0, phi_max=math.pi * 2.0) 75 83 r.nbins_phi = 20 76 84 o = r(self.data) 77 85 for i in range(7): 78 86 self.assertEqual(o.y[i], 1.0) 79 80 87 81 88 def test_sectorphi_partial(self): 82 89 """ 83 90 """ 84 91 phi_max = math.pi * 1.5 85 r = SectorPhi(r_min=self.qmin, r_max=3 *self.qmin,92 r = SectorPhi(r_min=self.qmin, r_max=3 * self.qmin, 86 93 phi_min=0, phi_max=phi_max) 87 94 self.assertEqual(r.phi_max, phi_max) … … 91 98 for i in range(17): 92 99 self.assertEqual(o.y[i], 1.0) 93 94 95 96 class data_info_tests(unittest.TestCase): 97 100 101 102 class DataInfoTests(unittest.TestCase): 103 98 104 def setUp(self): 99 self.data = Loader().load('MAR07232_rest.ASC') 100 105 filepath = os.path.join(os.path.dirname( 106 os.path.realpath(__file__)), 'MAR07232_rest.ASC') 107 self.data = Loader().load(filepath) 108 101 109 def test_ring(self): 102 110 """ 103 111 Test ring averaging 104 112 """ 105 r = Ring(r_min=.005, r_max=.01, 106 center_x=self.data.detector[0].beam_center.x, 113 r = Ring(r_min=.005, r_max=.01, 114 center_x=self.data.detector[0].beam_center.x, 107 115 center_y=self.data.detector[0].beam_center.y, 108 nbins =20)116 nbins=20) 109 117 ##r.nbins_phi = 20 110 111 o = r(self.data) 112 answer = Loader().load('ring_testdata.txt') 113 118 119 o = r(self.data) 120 filepath = os.path.join(os.path.dirname( 121 os.path.realpath(__file__)), 'ring_testdata.txt') 122 answer = Loader().load(filepath) 123 114 124 for i in range(r.nbins_phi - 1): 115 125 self.assertAlmostEqual(o.x[i + 1], answer.x[i], 4) 116 126 self.assertAlmostEqual(o.y[i + 1], answer.y[i], 4) 117 127 self.assertAlmostEqual(o.dy[i + 1], answer.dy[i], 4) 118 128 119 129 def test_circularavg(self): 120 130 """ 131 Test circular averaging 132 The test data was not generated by IGOR. 133 """ 134 r = CircularAverage(r_min=.00, r_max=.025, 135 bin_width=0.0003) 136 r.nbins_phi = 20 137 138 o = r(self.data) 139 140 filepath = os.path.join(os.path.dirname( 141 os.path.realpath(__file__)), 'avg_testdata.txt') 142 answer = Loader().load(filepath) 143 for i in range(r.nbins_phi): 144 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 145 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 146 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 147 148 def test_box(self): 149 """ 121 150 Test circular averaging 122 151 The test data was not generated by IGOR. 123 152 """ 124 r = CircularAverage(r_min=.00, r_max=.025, 125 bin_width=0.0003) 126 r.nbins_phi = 20 127 128 o = r(self.data) 129 130 answer = Loader().load('avg_testdata.txt') 131 for i in range(r.nbins_phi): 132 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 133 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 134 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 135 136 def test_box(self): 137 """ 138 Test circular averaging 139 The test data was not generated by IGOR. 140 """ 141 from sas.sascalc.dataloader.manipulations import Boxsum, Boxavg 142 153 143 154 r = Boxsum(x_min=.01, x_max=.015, y_min=0.01, y_max=0.015) 144 155 s, ds, npoints = r(self.data) 145 156 self.assertAlmostEqual(s, 34.278990899999997, 4) 146 157 self.assertAlmostEqual(ds, 7.8007981835194293, 4) 147 self.assertAlmostEqual(npoints, 324.0000, 4) 148 158 self.assertAlmostEqual(npoints, 324.0000, 4) 159 149 160 r = Boxavg(x_min=.01, x_max=.015, y_min=0.01, y_max=0.015) 150 161 s, ds = r(self.data) 151 162 self.assertAlmostEqual(s, 0.10579935462962962, 4) 152 163 self.assertAlmostEqual(ds, 0.024076537603455028, 4) 153 164 154 165 def test_slabX(self): 155 166 """ … … 157 168 The test data was not generated by IGOR. 158 169 """ 159 from sas.sascalc.dataloader.manipulations import SlabX 160 161 r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002,y_max=0.0002, bin_width=0.0004)170 171 r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002, 172 y_max=0.0002, bin_width=0.0004) 162 173 r.fold = False 163 174 o = r(self.data) 164 175 165 answer = Loader().load('slabx_testdata.txt') 166 for i in range(len(o.x)): 167 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 168 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 169 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 170 176 filepath = os.path.join(os.path.dirname( 177 os.path.realpath(__file__)), 'slabx_testdata.txt') 178 answer = Loader().load(filepath) 179 for i in range(len(o.x)): 180 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 181 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 182 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 183 171 184 def test_slabY(self): 172 185 """ … … 174 187 The test data was not generated by IGOR. 175 188 """ 176 from sas.sascalc.dataloader.manipulations import SlabY 177 178 r = SlabY(x_min=.005, x_max=.01, y_min=-0.01, y_max=0.01, bin_width=0.0004)189 190 r = SlabY(x_min=.005, x_max=.01, y_min=- 191 0.01, y_max=0.01, bin_width=0.0004) 179 192 r.fold = False 180 193 o = r(self.data) 181 194 182 answer = Loader().load('slaby_testdata.txt') 183 for i in range(len(o.x)): 184 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 185 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 186 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 187 195 filepath = os.path.join(os.path.dirname( 196 os.path.realpath(__file__)), 'slaby_testdata.txt') 197 answer = Loader().load(filepath) 198 for i in range(len(o.x)): 199 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 200 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 201 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 202 188 203 def test_sectorphi_full(self): 189 204 """ … … 193 208 The test data was not generated by IGOR. 194 209 """ 195 from sas.sascalc.dataloader.manipulations import SectorPhi 196 import math 197 210 198 211 nbins = 19 199 212 phi_min = math.pi / (nbins + 1) 200 213 phi_max = math.pi * 2 - phi_min 201 214 202 215 r = SectorPhi(r_min=.005, 203 216 r_max=.01, … … 207 220 o = r(self.data) 208 221 209 answer = Loader().load('ring_testdata.txt') 210 for i in range(len(o.x)): 211 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 212 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 213 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 214 222 filepath = os.path.join(os.path.dirname( 223 os.path.realpath(__file__)), 'ring_testdata.txt') 224 answer = Loader().load(filepath) 225 for i in range(len(o.x)): 226 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 227 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 228 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 229 215 230 def test_sectorphi_quarter(self): 216 231 """ … … 218 233 The test data was not generated by IGOR. 219 234 """ 220 from sas.sascalc.dataloader.manipulations import SectorPhi 221 import math222 223 r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0)224 r.nbins_phi = 20 225 o = r(self.data)226 227 answer = Loader().load( 'sectorphi_testdata.txt')228 for i in range(len(o.x)): 229 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 230 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 231 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 232 235 236 r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0) 237 r.nbins_phi = 20 238 o = r(self.data) 239 240 filepath = os.path.join(os.path.dirname( 241 os.path.realpath(__file__)), 'sectorphi_testdata.txt') 242 answer = Loader().load(filepath) 243 for i in range(len(o.x)): 244 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 245 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 246 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 247 233 248 def test_sectorq_full(self): 234 249 """ … … 236 251 The test data was not generated by IGOR. 237 252 """ 238 from sas.sascalc.dataloader.manipulations import SectorQ 239 import math 240 241 r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0) 242 r.nbins_phi = 20 243 o = r(self.data) 244 245 answer = Loader().load('sectorq_testdata.txt') 246 for i in range(len(o.x)): 247 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 248 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 249 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 250 253 254 r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0) 255 r.nbins_phi = 20 256 o = r(self.data) 257 258 filepath = os.path.join(os.path.dirname( 259 os.path.realpath(__file__)), 'sectorq_testdata.txt') 260 answer = Loader().load(filepath) 261 for i in range(len(o.x)): 262 self.assertAlmostEqual(o.x[i], answer.x[i], 4) 263 self.assertAlmostEqual(o.y[i], answer.y[i], 4) 264 self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 265 266 def test_sectorq_log(self): 267 """ 268 Test sector averaging I(q) 269 The test data was not generated by IGOR. 270 """ 271 272 r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0, base=10) 273 r.nbins_phi = 20 274 o = r(self.data) 275 276 expected_binning = np.logspace(np.log10(0.005), np.log10(0.01), 20, base=10) 277 for i in range(len(o.x)): 278 self.assertAlmostEqual(o.x[i], expected_binning[i], 3) 279 280 # TODO: Test for Y values (o.y) 281 # print len(self.data.x_bins) 282 # print len(self.data.y_bins) 283 # print self.data.q_data.shape 284 # data_to_bin = np.array(self.data.q_data) 285 # data_to_bin = data_to_bin.reshape(len(self.data.x_bins), len(self.data.y_bins)) 286 # H, xedges, yedges, binnumber = binned_statistic_2d(self.data.x_bins, self.data.y_bins, data_to_bin, 287 # bins=[[0, math.pi / 2.0], expected_binning], statistic='mean') 288 # xedges_width = (xedges[1] - xedges[0]) 289 # xedges_center = xedges[1:] - xedges_width / 2 290 291 # yedges_width = (yedges[1] - yedges[0]) 292 # yedges_center = yedges[1:] - yedges_width / 2 293 294 # print H.flatten().shape 295 # print o.y.shape 296 251 297 252 298 if __name__ == '__main__': -
test/sasguiframe/test/utest_manipulations.py
r959eb01 rc0ca2e3d 2 2 Unit tests for data manipulations 3 3 """ 4 #TODO: what happens if you add a Data1D to a Data2D? 5 4 # TODO: what happens if you add a Data1D to a Data2D? 5 6 import math 7 import os.path 6 8 import unittest 7 import math 9 8 10 import numpy as np 9 from sas.sascalc.dataloader.loader import Loader 10 from sas.sas gui.guiframe.dataFitting import Data1D, Data2D11 from sas.sasgui.guiframe.dataFitting import Data1D as Theory1D12 13 import os.path 14 15 class data_info_tests(unittest.TestCase):16 11 12 from sas.sascalc.dataloader.loader import Loader 13 from sas.sasgui.guiframe.dataFitting import Data1D 14 from sas.sasgui.guiframe.dataFitting import Data2D 15 16 17 class DataInfoTests(unittest.TestCase): 18 17 19 def setUp(self): 18 20 data = Loader().load("cansas1d.xml") 19 21 self.data = data[0] 20 22 21 23 def test_clone1D(self): 22 24 """ … … 24 26 """ 25 27 clone = self.data.clone_without_data() 26 28 27 29 for i in range(len(self.data.detector)): 28 self.assertEqual(self.data.detector[i].distance, clone.detector[i].distance) 29 30 class theory1d_tests(unittest.TestCase): 31 30 self.assertEqual( 31 self.data.detector[i].distance, clone.detector[i].distance) 32 33 34 class Theory1DTests(unittest.TestCase): 35 32 36 def setUp(self): 33 37 data = Loader().load("cansas1d.xml") 34 38 self.data = data[0] 35 39 36 40 def test_clone_theory1D(self): 37 41 """ 38 42 Test basic cloning 39 43 """ 40 theory = Theory1D(x=[], y=[], dy=None)44 theory = Data1D(x=[], y=[], dy=None) 41 45 theory.clone_without_data(clone=self.data) 42 46 theory.copy_from_datainfo(data1d=self.data) 43 47 for i in range(len(self.data.detector)): 44 self.assertEqual(self.data.detector[i].distance, theory.detector[i].distance) 45 48 self.assertEqual( 49 self.data.detector[i].distance, theory.detector[i].distance) 50 46 51 for i in range(len(self.data.x)): 47 52 self.assertEqual(self.data.x[i], theory.x[i]) … … 49 54 self.assertEqual(self.data.dy[i], theory.dy[i]) 50 55 51 class manip_tests(unittest.TestCase): 52 56 57 class ManipTests(unittest.TestCase): 58 53 59 def setUp(self): 54 60 # Create two data sets to play with 55 61 x_0 = np.ones(5) 56 62 for i in range(5): 57 x_0[i] = x_0[i] *(i+1.0)58 59 y_0 = 2.0 *np.ones(5)60 dy_0 = 0.5 *np.ones(5)63 x_0[i] = x_0[i] * (i + 1.0) 64 65 y_0 = 2.0 * np.ones(5) 66 dy_0 = 0.5 * np.ones(5) 61 67 self.data = Data1D(x_0, y_0, dy=dy_0) 62 68 63 69 x = self.data.x 64 70 y = np.ones(5) 65 71 dy = np.ones(5) 66 72 self.data2 = Data1D(x, y, dy=dy) 67 68 73 69 74 def test_load(self): 70 75 """ … … 73 78 # There should be 5 entries in the file 74 79 self.assertEqual(len(self.data.x), 5) 75 80 76 81 for i in range(5): 77 82 # The x values should be from 1 to 5 78 self.assertEqual(self.data.x[i], float(i +1))79 83 self.assertEqual(self.data.x[i], float(i + 1)) 84 80 85 # All y-error values should be 0.5 81 self.assertEqual(self.data.dy[i], 0.5) 82 86 self.assertEqual(self.data.dy[i], 0.5) 87 83 88 # All y values should be 2.0 84 self.assertEqual(self.data.y[i], 2.0) 85 89 self.assertEqual(self.data.y[i], 2.0) 90 86 91 def test_add(self): 87 result = self.data2 +self.data92 result = self.data2 + self.data 88 93 for i in range(5): 89 94 self.assertEqual(result.y[i], 3.0) 90 self.assertEqual(result.dy[i], math.sqrt(0.5**2 +1.0))91 95 self.assertEqual(result.dy[i], math.sqrt(0.5**2 + 1.0)) 96 92 97 def test_sub(self): 93 result = self.data2 -self.data98 result = self.data2 - self.data 94 99 for i in range(5): 95 100 self.assertEqual(result.y[i], -1.0) 96 self.assertEqual(result.dy[i], math.sqrt(0.5**2 +1.0))97 101 self.assertEqual(result.dy[i], math.sqrt(0.5**2 + 1.0)) 102 98 103 def test_mul(self): 99 result = self.data2 *self.data104 result = self.data2 * self.data 100 105 for i in range(5): 101 106 self.assertEqual(result.y[i], 2.0) 102 self.assertEqual(result.dy[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2)) 103 107 self.assertEqual(result.dy[i], math.sqrt( 108 (0.5 * 1.0)**2 + (1.0 * 2.0)**2)) 109 104 110 def test_div(self): 105 result = self.data2 /self.data111 result = self.data2 / self.data 106 112 for i in range(5): 107 113 self.assertEqual(result.y[i], 0.5) 108 self.assertEqual(result.dy[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2)) 109 114 self.assertEqual(result.dy[i], math.sqrt( 115 (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2)) 116 110 117 def test_radd(self): 111 result = self.data +3.0118 result = self.data + 3.0 112 119 for i in range(5): 113 120 self.assertEqual(result.y[i], 5.0) 114 121 self.assertEqual(result.dy[i], 0.5) 115 116 result = 3.0 +self.data122 123 result = 3.0 + self.data 117 124 for i in range(5): 118 125 self.assertEqual(result.y[i], 5.0) 119 126 self.assertEqual(result.dy[i], 0.5) 120 127 121 128 def test_rsub(self): 122 result = self.data -3.0129 result = self.data - 3.0 123 130 for i in range(5): 124 131 self.assertEqual(result.y[i], -1.0) 125 132 self.assertEqual(result.dy[i], 0.5) 126 127 result = 3.0 -self.data133 134 result = 3.0 - self.data 128 135 for i in range(5): 129 136 self.assertEqual(result.y[i], 1.0) 130 137 self.assertEqual(result.dy[i], 0.5) 131 138 132 139 def test_rmul(self): 133 result = self.data *3.0140 result = self.data * 3.0 134 141 for i in range(5): 135 142 self.assertEqual(result.y[i], 6.0) 136 143 self.assertEqual(result.dy[i], 1.5) 137 138 result = 3.0 *self.data144 145 result = 3.0 * self.data 139 146 for i in range(5): 140 147 self.assertEqual(result.y[i], 6.0) 141 148 self.assertEqual(result.dy[i], 1.5) 142 149 143 150 def test_rdiv(self): 144 result = self.data /4.0151 result = self.data / 4.0 145 152 for i in range(5): 146 153 self.assertEqual(result.y[i], 0.5) 147 154 self.assertEqual(result.dy[i], 0.125) 148 149 result = 6.0 /self.data155 156 result = 6.0 / self.data 150 157 for i in range(5): 151 158 self.assertEqual(result.y[i], 3.0) 152 self.assertEqual(result.dy[i], 6.0*0.5/4.0) 153 154 class manip_2D(unittest.TestCase): 155 159 self.assertEqual(result.dy[i], 6.0 * 0.5 / 4.0) 160 161 162 class Manin2DTests(unittest.TestCase): 163 156 164 def setUp(self): 157 165 # Create two data sets to play with 158 x_0 = 2.0 *np.ones(25)159 dx_0 = 0.5 *np.ones(25)166 x_0 = 2.0 * np.ones(25) 167 dx_0 = 0.5 * np.ones(25) 160 168 qx_0 = np.arange(25) 161 169 qy_0 = np.arange(25) 162 170 mask_0 = np.zeros(25) 163 dqx_0 = np.arange(25) /100164 dqy_0 = np.arange(25) /100171 dqx_0 = np.arange(25) / 100 172 dqy_0 = np.arange(25) / 100 165 173 q_0 = np.sqrt(qx_0 * qx_0 + qy_0 * qy_0) 166 self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 167 qy_data=qy_0, q_data=q_0, mask=mask_0, 174 self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 175 qy_data=qy_0, q_data=q_0, mask=mask_0, 168 176 dqx_data=dqx_0, dqy_data=dqy_0) 169 177 170 178 y = np.ones(25) 171 179 dy = np.ones(25) … … 174 182 mask = np.zeros(25) 175 183 q = np.sqrt(qx * qx + qy * qy) 176 self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 184 self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 177 185 q_data=q, mask=mask) 178 179 186 180 187 def test_load(self): 181 188 """ … … 184 191 # There should be 5 entries in the file 185 192 self.assertEqual(np.size(self.data.data), 25) 186 193 187 194 for i in range(25): 188 195 # All y-error values should be 0.5 189 self.assertEqual(self.data.err_data[i], 0.5) 190 196 self.assertEqual(self.data.err_data[i], 0.5) 197 191 198 # All y values should be 2.0 192 self.assertEqual(self.data.data[i], 2.0) 193 199 self.assertEqual(self.data.data[i], 2.0) 200 194 201 def test_add(self): 195 result = self.data2 +self.data202 result = self.data2 + self.data 196 203 for i in range(25): 197 204 self.assertEqual(result.data[i], 3.0) 198 self.assertEqual(result.err_data[i], math.sqrt(0.5**2 +1.0))199 205 self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 206 200 207 def test_sub(self): 201 result = self.data2 -self.data202 for i in range(25): 203 204 self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0))205 208 result = self.data2 - self.data 209 for i in range(25): 210 self.assertEqual(result.data[i], -1.0) 211 self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 212 206 213 def test_mul(self): 207 result = self.data2 *self.data214 result = self.data2 * self.data 208 215 for i in range(25): 209 216 self.assertEqual(result.data[i], 2.0) 210 self.assertEqual(result.err_data[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2)) 211 217 self.assertEqual(result.err_data[i], math.sqrt( 218 (0.5 * 1.0)**2 + (1.0 * 2.0)**2)) 219 212 220 def test_div(self): 213 result = self.data2 /self.data221 result = self.data2 / self.data 214 222 for i in range(25): 215 223 self.assertEqual(result.data[i], 0.5) 216 self.assertEqual(result.err_data[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2)) 217 224 self.assertEqual(result.err_data[i], math.sqrt( 225 (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2)) 226 218 227 def test_radd(self): 219 result = self.data +3.0228 result = self.data + 3.0 220 229 for i in range(25): 221 230 self.assertEqual(result.data[i], 5.0) 222 231 self.assertEqual(result.err_data[i], 0.5) 223 224 result = 3.0 +self.data232 233 result = 3.0 + self.data 225 234 for i in range(25): 226 235 self.assertEqual(result.data[i], 5.0) 227 236 self.assertEqual(result.err_data[i], 0.5) 228 237 229 238 def test_rsub(self): 230 result = self.data -3.0239 result = self.data - 3.0 231 240 for i in range(25): 232 241 self.assertEqual(result.data[i], -1.0) 233 242 self.assertEqual(result.err_data[i], 0.5) 234 235 result = 3.0 -self.data243 244 result = 3.0 - self.data 236 245 for i in range(25): 237 246 self.assertEqual(result.data[i], 1.0) 238 247 self.assertEqual(result.err_data[i], 0.5) 239 248 240 249 def test_rmul(self): 241 result = self.data *3.0250 result = self.data * 3.0 242 251 for i in range(25): 243 252 self.assertEqual(result.data[i], 6.0) 244 253 self.assertEqual(result.err_data[i], 1.5) 245 246 result = 3.0 *self.data254 255 result = 3.0 * self.data 247 256 for i in range(25): 248 257 self.assertEqual(result.data[i], 6.0) 249 258 self.assertEqual(result.err_data[i], 1.5) 250 259 251 260 def test_rdiv(self): 252 result = self.data /4.0261 result = self.data / 4.0 253 262 for i in range(25): 254 263 self.assertEqual(result.data[i], 0.5) 255 264 self.assertEqual(result.err_data[i], 0.125) 256 265 257 result = 6.0 /self.data266 result = 6.0 / self.data 258 267 for i in range(25): 259 268 self.assertEqual(result.data[i], 3.0) 260 self.assertEqual(result.err_data[i], 6.0*0.5/4.0) 261 262 class extra_manip_2D(unittest.TestCase): 263 269 self.assertEqual(result.err_data[i], 6.0 * 0.5 / 4.0) 270 271 272 class ExtraManip2DTests(unittest.TestCase): 273 264 274 def setUp(self): 265 275 # Create two data sets to play with 266 x_0 = 2.0 *np.ones(25)267 dx_0 = 0.5 *np.ones(25)276 x_0 = 2.0 * np.ones(25) 277 dx_0 = 0.5 * np.ones(25) 268 278 qx_0 = np.arange(25) 269 279 qy_0 = np.arange(25) 270 280 mask_0 = np.zeros(25) 271 dqx_0 = np.arange(25) /100272 dqy_0 = np.arange(25) /100281 dqx_0 = np.arange(25) / 100 282 dqy_0 = np.arange(25) / 100 273 283 q_0 = np.sqrt(qx_0 * qx_0 + qy_0 * qy_0) 274 self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 275 qy_data=qy_0, q_data=q_0, mask=mask_0, 284 self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 285 qy_data=qy_0, q_data=q_0, mask=mask_0, 276 286 dqx_data=dqx_0, dqy_data=dqy_0) 277 287 278 288 y = np.ones(25) 279 289 dy = np.ones(25) … … 282 292 mask = np.zeros(25) 283 293 q = np.sqrt(qx * qx + qy * qy) 284 self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 294 self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 285 295 q_data=q, mask=mask) 286 287 296 288 297 def test_load(self): 289 298 """ … … 292 301 # There should be 5 entries in the file 293 302 self.assertEqual(np.size(self.data.data), 25) 294 303 295 304 for i in range(25): 296 305 # All y-error values should be 0.5 297 self.assertEqual(self.data.err_data[i], 0.5) 298 306 self.assertEqual(self.data.err_data[i], 0.5) 307 299 308 # All y values should be 2.0 300 self.assertEqual(self.data.data[i], 2.0) 301 309 self.assertEqual(self.data.data[i], 2.0) 310 302 311 def test_add(self): 303 result = self.data2 +self.data312 result = self.data2 + self.data 304 313 for i in range(25): 305 314 self.assertEqual(result.data[i], 3.0) 306 self.assertEqual(result.err_data[i], math.sqrt(0.5**2 +1.0))307 315 self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 316 308 317 def test_sub(self): 309 result = self.data2 -self.data310 for i in range(25): 311 312 self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0))313 318 result = self.data2 - self.data 319 for i in range(25): 320 self.assertEqual(result.data[i], -1.0) 321 self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 322 314 323 def test_mul(self): 315 result = self.data2 *self.data324 result = self.data2 * self.data 316 325 for i in range(25): 317 326 self.assertEqual(result.data[i], 2.0) 318 self.assertEqual(result.err_data[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2)) 319 327 self.assertEqual(result.err_data[i], math.sqrt( 328 (0.5 * 1.0)**2 + (1.0 * 2.0)**2)) 329 320 330 def test_div(self): 321 result = self.data2 /self.data331 result = self.data2 / self.data 322 332 for i in range(25): 323 333 self.assertEqual(result.data[i], 0.5) 324 self.assertEqual(result.err_data[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2)) 325 334 self.assertEqual(result.err_data[i], math.sqrt( 335 (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2)) 336 326 337 def test_radd(self): 327 result = self.data +3.0338 result = self.data + 3.0 328 339 for i in range(25): 329 340 self.assertEqual(result.data[i], 5.0) 330 341 self.assertEqual(result.err_data[i], 0.5) 331 332 result = 3.0 +self.data342 343 result = 3.0 + self.data 333 344 for i in range(25): 334 345 self.assertEqual(result.data[i], 5.0) 335 346 self.assertEqual(result.err_data[i], 0.5) 336 347 337 348 def test_rsub(self): 338 result = self.data -3.0349 result = self.data - 3.0 339 350 for i in range(25): 340 351 self.assertEqual(result.data[i], -1.0) 341 352 self.assertEqual(result.err_data[i], 0.5) 342 343 result = 3.0 -self.data353 354 result = 3.0 - self.data 344 355 for i in range(25): 345 356 self.assertEqual(result.data[i], 1.0) 346 357 self.assertEqual(result.err_data[i], 0.5) 347 358 348 359 def test_rmul(self): 349 result = self.data *3.0360 result = self.data * 3.0 350 361 for i in range(25): 351 362 self.assertEqual(result.data[i], 6.0) 352 363 self.assertEqual(result.err_data[i], 1.5) 353 354 result = 3.0 *self.data364 365 result = 3.0 * self.data 355 366 for i in range(25): 356 367 self.assertEqual(result.data[i], 6.0) 357 368 self.assertEqual(result.err_data[i], 1.5) 358 369 359 370 def test_rdiv(self): 360 result = self.data /4.0371 result = self.data / 4.0 361 372 for i in range(25): 362 373 self.assertEqual(result.data[i], 0.5) 363 374 self.assertEqual(result.err_data[i], 0.125) 364 375 365 result = 6.0 /self.data376 result = 6.0 / self.data 366 377 for i in range(25): 367 378 self.assertEqual(result.data[i], 3.0) 368 self.assertEqual(result.err_data[i], 6.0*0.5/4.0) 379 self.assertEqual(result.err_data[i], 6.0 * 0.5 / 4.0) 380 369 381 370 382 if __name__ == '__main__': 371 383 unittest.main() 372 -
src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter2D.py
r7432acb r3e5648b 361 361 if self.slicer.__class__.__name__ != "BoxSum": 362 362 wx_id = ids.next() 363 slicerpop.Append(wx_id, '&Edit Slicer Parameters') 363 name = '&Edit Slicer Parameters and Batch Slicing' 364 slicerpop.Append(wx_id, name) 364 365 wx.EVT_MENU(self, wx_id, self._onEditSlicer) 365 366 slicerpop.AppendSeparator() … … 532 533 533 534 """ 534 # #Clear current slicer535 # Clear current slicer 535 536 if self.slicer is not None: 536 537 self.slicer.clear() 537 # #Create a new slicer538 # Create a new slicer 538 539 self.slicer_z += 1 539 540 self.slicer = slicer(self, self.subplot, zorder=self.slicer_z) 540 541 self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax) 541 542 self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax) 542 # #Draw slicer543 # Draw slicer 543 544 self.update() 544 545 self.slicer.update() … … 572 573 npt = math.floor(npt) 573 574 from sas.sascalc.dataloader.manipulations import CircularAverage 574 # #compute the maximum radius of data2D575 # compute the maximum radius of data2D 575 576 self.qmax = max(math.fabs(self.data2D.xmax), 576 577 math.fabs(self.data2D.xmin)) … … 578 579 math.fabs(self.data2D.ymin)) 579 580 self.radius = math.sqrt(math.pow(self.qmax, 2) + math.pow(self.ymax, 2)) 580 # #Compute beam width581 # Compute beam width 581 582 bin_width = (self.qmax + self.qmax) / npt 582 # #Create data1D circular average of data2D583 # Create data1D circular average of data2D 583 584 Circle = CircularAverage(r_min=0, r_max=self.radius, 584 585 bin_width=bin_width) … … 599 600 new_plot.name = "Circ avg " + self.data2D.name 600 601 new_plot.source = self.data2D.source 601 # new_plot.info = self.data2D.info602 # new_plot.info = self.data2D.info 602 603 new_plot.interactive = True 603 604 new_plot.detector = self.data2D.detector 604 605 605 # #If the data file does not tell us what the axes are, just assume...606 # If the data file does not tell us what the axes are, just assume... 606 607 new_plot.xaxis("\\rm{Q}", "A^{-1}") 607 608 if hasattr(self.data2D, "scale") and \ … … 615 616 new_plot.id = "Circ avg " + self.data2D.name 616 617 new_plot.is_data = True 617 self.parent.update_theory(data_id=self.data2D.id, \ 618 theory=new_plot) 618 self.parent.update_theory(data_id=self.data2D.id, theory=new_plot) 619 619 wx.PostEvent(self.parent, 620 620 NewPlotEvent(plot=new_plot, title=new_plot.name)) … … 630 630 """ 631 631 if self.slicer is not None: 632 from SlicerParametersimport SlicerParameterPanel632 from parameters_panel_slicer import SlicerParameterPanel 633 633 dialog = SlicerParameterPanel(self, -1, "Slicer Parameters") 634 634 dialog.set_slicer(self.slicer.__class__.__name__, … … 668 668 params = self.slicer.get_params() 669 669 ## Create a new panel to display results of summation of Data2D 670 from slicerpanelimport SlicerPanel670 from parameters_panel_boxsum import SlicerPanel 671 671 win = MDIFrame(self.parent, None, 'None', (100, 200)) 672 672 new_panel = SlicerPanel(parent=win, id=-1, … … 758 758 if default_name.count('.') > 0: 759 759 default_name = default_name.split('.')[0] 760 #default_name += "_out"761 760 if self.parent is not None: 762 761 self.parent.show_data2d(data, default_name) 763 762 764 763 def modifyGraphAppearance(self, e): 765 self.graphApp = graphAppearance(self, 'Modify graph appearance', legend=False) 764 self.graphApp = graphAppearance(self, 'Modify graph appearance', 765 legend=False) 766 766 self.graphApp.setDefaults(self.grid_on, self.legend_on, 767 767 self.xaxis_label, self.yaxis_label, -
src/sas/sasgui/guiframe/local_perspectives/plotting/parameters_panel_boxsum.py
r7432acb r37d461c 1 1 import wx 2 2 import wx.lib.newevent 3 #from copy import deepcopy 3 from parameters_panel_slicer import SlicerParameterPanel 4 4 from sas.sasgui.guiframe.utils import format_number 5 from sas.sasgui.guiframe. events import SlicerParameterEvent6 from sas.sasgui.guiframe.events import EVT_SLICER_PARS7 from sas.sasgui.guiframe.events import EVT_SLICER 5 from sas.sasgui.guiframe.panel_base import PanelBase 6 from sas.sasgui.guiframe.events import (SlicerParameterEvent, EVT_SLICER_PARS, 7 EVT_SLICER) 8 8 9 from sas.sasgui.guiframe.panel_base import PanelBase10 9 11 10 class SlicerPanel(wx.Panel, PanelBase): … … 13 12 Panel class to show the slicer parameters 14 13 """ 15 #TODO: show units 16 #TODO: order parameters properly 17 ## Internal name for the AUI manager 14 # Internal name for the AUI manager 18 15 window_name = "Slicer panel" 19 # #Title to appear on top of the window16 # Title to appear on top of the window 20 17 window_caption = "Slicer Panel" 21 18 CENTER_PANE = False … … 25 22 wx.Panel.__init__(self, parent, id, *args, **kwargs) 26 23 PanelBase.__init__(self) 27 # #Initialization of the class24 # Initialization of the class 28 25 self.base = base 29 26 if params is None: … … 44 41 else: 45 42 self.set_slicer(type, params) 46 ## Bindings 47 self.parent.Bind(EVT_SLICER, self.onEVT_SLICER) 48 self.parent.Bind(EVT_SLICER_PARS, self.onParamChange) 49 50 def onEVT_SLICER(self, event): 51 """ 52 Process EVT_SLICER events 53 When the slicer changes, update the panel 54 55 :param event: EVT_SLICER event 56 57 """ 58 event.Skip() 59 if event.obj_class is None: 60 self.set_slicer(None, None) 61 else: 62 self.set_slicer(event.type, event.params) 43 # Bindings 44 self.parent.Bind(EVT_SLICER, SlicerParameterPanel.on_evt_slicer) 45 self.parent.Bind(EVT_SLICER_PARS, SlicerParameterPanel.on_param_change) 63 46 64 47 def set_slicer(self, type, params): … … 84 67 keys.sort() 85 68 for item in keys: 86 if not item.lower() in ["num_points", "avg", "avg_error", "sum", "sum_error"]: 69 if not item.lower() in ["num_points", "avg", "avg_error", "sum", 70 "sum_error"]: 87 71 n += 1 88 72 text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT) 89 73 self.bck.Add(text, (n - 1, 0), 90 flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=15) 74 flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 75 border=15) 91 76 ctl = wx.TextCtrl(self, -1, size=(80, 20), 92 77 style=wx.TE_PROCESS_ENTER) … … 95 80 ctl.SetToolTipString(hint_msg) 96 81 ctl.SetValue(str(format_number(params[item]))) 97 self.Bind(wx.EVT_TEXT_ENTER, self.on TextEnter)98 ctl.Bind(wx.EVT_SET_FOCUS, self.on SetFocus)99 ctl.Bind(wx.EVT_KILL_FOCUS, self.on TextEnter)82 self.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter) 83 ctl.Bind(wx.EVT_SET_FOCUS, self.on_set_focus) 84 ctl.Bind(wx.EVT_KILL_FOCUS, self.on_text_enter) 100 85 self.parameters.append([item, ctl]) 101 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, border=0) 86 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, 87 border=0) 102 88 for item in keys: 103 if item.lower() in ["num_points", "avg", "avg_error", "sum", "sum_error"]: 89 if item.lower() in ["num_points", "avg", "avg_error", "sum", 90 "sum_error"]: 104 91 n += 1 105 text = wx.StaticText(self, -1, item + ": ", style=wx.ALIGN_LEFT) 106 self.bck.Add(text, (n - 1, 0), flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 92 text = wx.StaticText(self, -1, item + ": ", 93 style=wx.ALIGN_LEFT) 94 self.bck.Add(text, (n - 1, 0), 95 flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 107 96 border=15) 108 97 ctl = wx.StaticText(self, -1, … … 110 99 style=wx.ALIGN_LEFT) 111 100 ctl.SetToolTipString("Result %s" % item) 112 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, border=0) 101 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, 102 border=0) 113 103 self.bck.Layout() 114 104 self.Layout() 115 p sizer = self.parent.GetSizer()116 if p sizer is not None:117 p sizer.Layout()105 p_sizer = self.parent.GetSizer() 106 if p_sizer is not None: 107 p_sizer.Layout() 118 108 119 def on SetFocus(self, evt):109 def on_set_focus(self, evt): 120 110 """ 121 111 Highlight the txtcrtl … … 126 116 # Select the whole control, after this event resolves 127 117 wx.CallAfter(widget.SetSelection, -1, -1) 128 return129 118 130 def onParamChange(self, evt): 131 """ 132 Receive and event and reset the text field contained in self.parameters 133 134 """ 135 evt.Skip() 136 for item in self.parameters: 137 if item[0] in evt.params: 138 item[1].SetValue(format_number(evt.params[item[0]])) 139 item[1].Refresh() 140 141 def onTextEnter(self, evt): 119 def on_text_enter(self, evt): 142 120 """ 143 121 Parameters have changed … … 149 127 try: 150 128 params[item[0]] = float(item[1].GetValue()) 151 item[1].SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) 129 item[1].SetBackgroundColour(wx.SystemSettings_GetColour( 130 wx.SYS_COLOUR_WINDOW)) 152 131 item[1].Refresh() 153 132 except: … … 155 134 item[1].SetBackgroundColour("pink") 156 135 item[1].Refresh() 157 158 if has_error == False: 136 if not has_error: 159 137 # Post parameter event 160 # #base is guiframe is this case138 # base is guiframe is this case 161 139 event = SlicerParameterEvent(type=self.type, params=params) 162 140 wx.PostEvent(self.base, event) … … 166 144 On Close Event 167 145 """ 168 ID= self.uid169 self.parent.delete_panel( ID)146 uid = self.uid 147 self.parent.delete_panel(uid) 170 148 self.frame.Destroy() -
src/sas/sasgui/perspectives/fitting/basepage.py
ra1b8fee r914c49d5 254 254 if not hasattr(self, "model_view"): 255 255 return 256 toggle_mode_on = self.model_view.IsEnabled() 256 toggle_mode_on = self.model_view.IsEnabled() or self.data is None 257 257 if toggle_mode_on: 258 258 if self.enable2D and not check_data_validity(self.data):
Note: See TracChangeset
for help on using the changeset viewer.