Changes in / [b53f529:00fd278] in sasview
- Files:
-
- 1 added
- 4 deleted
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
build_tools/conda_qt5_min_centos.yml
r0930e22 r16417bb 7 7 - hdf5 8 8 - h5py 9 - ipython=6 10 - ipykernel=4.9 9 - ipython 11 10 - jupyter 12 11 - twisted -
build_tools/conda_qt5_min_osx.yml
r00fd278 r00fd278 20 20 - pyopencl 21 21 - testpath=0.3.1 22 - numpy=1.1523 22 - pip: 24 23 - pytools … … 26 25 - bumps 27 26 - xhtml2pdf 28 - qt5reactor 27 - qt5reactor 29 28 -
build_tools/conda_qt5_win.yml
r473a85a r7ecece1 9 9 - h5py 10 10 - ipython=6 11 - ipykernel= 4.911 - ipykernel=5 12 12 - jupyter 13 13 - twisted -
src/sas/qtgui/MainWindow/MainWindow.py
rd541324e r33c0561 56 56 app = QApplication([]) 57 57 58 # Make the event loop interruptable quickly59 import signal60 signal.signal(signal.SIGINT, signal.SIG_DFL)61 62 58 # Main must have reference to the splash screen, so making it explicit 63 59 splash = SplashScreen() -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r1d6899f rbbcf9f0 1768 1768 raise ValueError("Setting model parameters failed with: %s" % ex) 1769 1769 1770 qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 1770 1771 fitter_single.set_data(data=weighted_data, id=fit_id, smearer=smearer, qmin=qmin, 1771 1772 qmax=qmax) -
src/sas/qtgui/Plotting/Plotter2D.py
r8db20a9 rc30822c 468 468 # check scale 469 469 if self.scale == 'log_{10}': 470 with numpy.errstate(all='ignore'): 471 output = numpy.log10(output) 472 index = numpy.isfinite(output) 473 if not index.all(): 474 cutoff = (numpy.quantile(output[index], 0.05) - numpy.log10(2) if index.any() else 0.) 475 output[output < cutoff] = cutoff 476 output[~index] = cutoff 477 vmin, vmax = None, None 470 try: 471 if self.zmin is None and len(output[output > 0]) > 0: 472 zmin_temp = self.zmin 473 output[output > 0] = numpy.log10(output[output > 0]) 474 elif self.zmin <= 0: 475 zmin_temp = self.zmin 476 output[output > 0] = numpy.zeros(len(output)) 477 output[output <= 0] = MIN_Z 478 else: 479 zmin_temp = self.zmin 480 output[output > 0] = numpy.log10(output[output > 0]) 481 except: 482 #Too many problems in 2D plot with scale 483 pass 478 484 479 485 self.cmap = cmap -
src/sas/qtgui/Utilities/GuiUtils.py
r4333edf r10786bc2 12 12 import urllib.parse 13 13 import json 14 import types15 14 from io import BytesIO 16 15 … … 45 44 46 45 from sas.sascalc.dataloader.loader import Loader 47 from sas.sascalc.file_converter.nxcansas_writer import NXcanSASWriter48 49 46 from sas.qtgui.Utilities import CustomDir 50 47 … … 796 793 797 794 wildcard = "Text files (*.txt);;"\ 798 "CanSAS 1D files(*.xml);;"\ 799 "NXcanSAS files (*.h5)" 795 "CanSAS 1D files(*.xml)" 800 796 kwargs = { 801 797 'caption' : 'Save As', … … 816 812 if os.path.splitext(filename)[1].lower() == ".txt": 817 813 onTXTSave(data, filename) 818 elif os.path.splitext(filename)[1].lower() == ".xml":814 if os.path.splitext(filename)[1].lower() == ".xml": 819 815 loader.save(filename, data, ".xml") 820 elif os.path.splitext(filename)[1].lower() == ".h5":821 nxcansaswriter = NXcanSASWriter()822 nxcansaswriter.write([data], filename)823 816 824 817 def saveData2D(data): … … 831 824 default_name += "_out" + ext_format 832 825 833 wildcard = "IGOR/DAT 2D file in Q_map (*.dat);;"\ 834 "NXcanSAS files (*.h5)" 826 wildcard = "IGOR/DAT 2D file in Q_map (*.dat)" 835 827 kwargs = { 836 828 'caption' : 'Save As', … … 852 844 if os.path.splitext(filename)[1].lower() == ext_format: 853 845 loader.save(filename, data, ext_format) 854 elif os.path.splitext(filename)[1].lower() == ".h5":855 nxcansaswriter = NXcanSASWriter()856 nxcansaswriter.write([data], filename)857 858 846 859 847 class FormulaValidator(QtGui.QValidator): … … 1223 1211 return add_type(content, type(o)) 1224 1212 1225 if isinstance(o, types.FunctionType):1226 # we have a pure function1227 content = o.__dict__.copy()1228 return add_type(content, type(o))1229 1230 1213 # not supported 1231 1214 logging.info("data cannot be serialized to json: %s" % type(o)) … … 1240 1223 ''' 1241 1224 supported = [ 1242 tuple, set, types.FunctionType,1225 tuple, set, 1243 1226 Sample, Source, Vector, 1244 1227 Plottable, Data1D, Data2D, PlottableTheory1D, PlottableFit1D, Text, Chisq, View, … … 1295 1278 buffer.seek(0) 1296 1279 return np.load(buffer) 1297 1298 # function1299 if cls == types.FunctionType:1300 return cls1301 1280 1302 1281 logging.info('not implemented: %s, %s' % (type, cls)) -
src/sas/sascalc/data_util/nxsunit.py
r8db20a9 r574adc7 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 '1/Angstrom': 1, '1/angstrom': 1, 'A^{-1}': 1, 'cm^{-1}': 1e-8,139 138 '10^-3 Angstrom^-1': 1e-3, '1/cm': 1e-8, '1/m': 1e-10, 140 'nm^ {-1}': 1, 'nm^-1': 0.1, '1/nm': 0.1, 'n_m^-1': 0.1 }139 'nm^-1': 0.1, '1/nm': 0.1, 'n_m^-1': 0.1 } 141 140 142 141 _caret_optional(sld) … … 158 157 # units for that particular dimension. 159 158 # Note: don't have support for dimensionless units. 160 unknown = {None:1, '???':1, '': 1, 'a.u.': 1 , 'Counts': 1, 'counts': 1}159 unknown = {None:1, '???':1, '': 1, 'a.u.': 1} 161 160 162 161 def __init__(self, name): -
src/sas/sascalc/data_util/registry.py
r8db20a9 ra26f67f 111 111 for L in loaders: 112 112 if L not in result: result.append(L) 113 loaders = result 114 #loaders = L 113 loaders = L 115 114 # Raise an error if there are no matching extensions 116 115 if len(loaders) == 0: -
src/sas/sascalc/dataloader/data_info.py
r8db20a9 rb8080e1 954 954 _str += "Data:\n" 955 955 _str += " Type: %s\n" % self.__class__.__name__ 956 _str += " X-axis: %s\t[%s]\n" % (self._xaxis, self._xunit) 957 _str += " Y-axis: %s\t[%s]\n" % (self._yaxis, self._yunit) 956 _str += " X- & Y-axis: %s\t[%s]\n" % (self._yaxis, self._yunit) 958 957 _str += " Z-axis: %s\t[%s]\n" % (self._zaxis, self._zunit) 959 958 _str += " Length: %g \n" % (len(self.data)) … … 984 983 qx_data=qx_data, qy_data=qy_data, 985 984 q_data=q_data, mask=mask) 986 987 clone._xaxis = self._xaxis988 clone._yaxis = self._yaxis989 clone._zaxis = self._zaxis990 clone._xunit = self._xunit991 clone._yunit = self._yunit992 clone._zunit = self._zunit993 clone.x_bins = self.x_bins994 clone.y_bins = self.y_bins995 985 996 986 clone.title = self.title … … 1163 1153 def combine_data_info_with_plottable(data, datainfo): 1164 1154 """ 1165 A function that combines the DataInfo data in self.current_datainto with a 1166 plottable_1D or 2D data object. 1155 A function that combines the DataInfo data in self.current_datainto with a plottable_1D or 2D data object. 1167 1156 1168 1157 :param data: A plottable_1D or plottable_2D data object … … 1182 1171 final_dataset.yaxis(data._yaxis, data._yunit) 1183 1172 elif isinstance(data, plottable_2D): 1184 final_dataset = Data2D(data.data, data.err_data, data.qx_data, 1185 data.qy_data, data.q_data, data.mask, 1186 data.dqx_data, data.dqy_data) 1173 final_dataset = Data2D(data.data, data.err_data, data.qx_data, data.qy_data, data.q_data, 1174 data.mask, data.dqx_data, data.dqy_data) 1187 1175 final_dataset.xaxis(data._xaxis, data._xunit) 1188 1176 final_dataset.yaxis(data._yaxis, data._yunit) 1189 1177 final_dataset.zaxis(data._zaxis, data._zunit) 1190 final_dataset.y_bins = data.y_bins 1191 final_dataset.x_bins = data.x_bins 1178 if len(data.data.shape) == 2: 1179 n_rows, n_cols = data.data.shape 1180 final_dataset.y_bins = data.qy_data[0::int(n_cols)] 1181 final_dataset.x_bins = data.qx_data[:int(n_cols)] 1192 1182 else: 1193 return_string = ("Should Never Happen: _combine_data_info_with_plottabl" 1194 "e input is not a plottable1d or plottable2d data " 1195 "object") 1183 return_string = "Should Never Happen: _combine_data_info_with_plottable input is not a plottable1d or " + \ 1184 "plottable2d data object" 1196 1185 return return_string 1197 1186 -
src/sas/sascalc/dataloader/file_reader_base_class.py
r8db20a9 rbe7c981 16 16 from .data_info import Data1D, Data2D, DataInfo, plottable_1D, plottable_2D,\ 17 17 combine_data_info_with_plottable 18 from sas.sascalc.data_util.nxsunit import Converter19 18 20 19 logger = logging.getLogger(__name__) … … 38 37 "SasView cannot guarantee the accuracy of the data.") 39 38 40 41 39 class FileReader(object): 42 40 # String to describe the type of data this reader can load … … 47 45 ext = ['.txt'] 48 46 # Deprecated extensions 49 deprecated_extensions = ['.asc' ]47 deprecated_extensions = ['.asc', '.nxs'] 50 48 # Bypass extension check and try to load anyway 51 49 allow_all = False … … 100 98 if len(self.output) > 0: 101 99 # Sort the data that's been loaded 102 self. convert_data_units()103 self.sort_ data()100 self.sort_one_d_data() 101 self.sort_two_d_data() 104 102 else: 105 103 msg = "Unable to find file at: {}\n".format(filepath) … … 142 140 Returns the entire file as a string. 143 141 """ 142 #return self.f_open.read() 144 143 return decode(self.f_open.read()) 145 144 … … 167 166 self.output.append(data_obj) 168 167 169 def sort_ data(self):168 def sort_one_d_data(self): 170 169 """ 171 170 Sort 1D data along the X axis for consistency … … 175 174 # Normalize the units for 176 175 data.x_unit = self.format_unit(data.x_unit) 177 data._xunit = data.x_unit178 176 data.y_unit = self.format_unit(data.y_unit) 179 data._yunit = data.y_unit180 177 # Sort data by increasing x and remove 1st point 181 178 ind = np.lexsort((data.y, data.x)) … … 206 203 data.ymin = np.min(data.y) 207 204 data.ymax = np.max(data.y) 208 elif isinstance(data, Data2D):209 # Normalize the units for210 data.Q_unit = self.format_unit(data.Q_unit)211 data.I_unit = self.format_unit(data.I_unit)212 data._xunit = data.Q_unit213 data._yunit = data.Q_unit214 data._zunit = data.I_unit215 data.data = data.data.astype(np.float64)216 data.qx_data = data.qx_data.astype(np.float64)217 data.xmin = np.min(data.qx_data)218 data.xmax = np.max(data.qx_data)219 data.qy_data = data.qy_data.astype(np.float64)220 data.ymin = np.min(data.qy_data)221 data.ymax = np.max(data.qy_data)222 data.q_data = np.sqrt(data.qx_data * data.qx_data223 + data.qy_data * data.qy_data)224 if data.err_data is not None:225 data.err_data = data.err_data.astype(np.float64)226 if data.dqx_data is not None:227 data.dqx_data = data.dqx_data.astype(np.float64)228 if data.dqy_data is not None:229 data.dqy_data = data.dqy_data.astype(np.float64)230 if data.mask is not None:231 data.mask = data.mask.astype(dtype=bool)232 233 if len(data.data.shape) == 2:234 n_rows, n_cols = data.data.shape235 data.y_bins = data.qy_data[0::int(n_cols)]236 data.x_bins = data.qx_data[:int(n_cols)]237 data.data = data.data.flatten()238 data = self._remove_nans_in_data(data)239 if len(data.data) > 0:240 data.xmin = np.min(data.qx_data)241 data.xmax = np.max(data.qx_data)242 data.ymin = np.min(data.qy_data)243 data.ymax = np.max(data.qy_data)244 205 245 206 @staticmethod … … 281 242 return data 282 243 283 @staticmethod 284 def set_default_1d_units(data): 285 """ 286 Set the x and y axes to the default 1D units 287 :param data: 1D data set 288 :return: 289 """ 290 data.xaxis(r"\rm{Q}", '1/A') 291 data.yaxis(r"\rm{Intensity}", "1/cm") 292 return data 293 294 @staticmethod 295 def set_default_2d_units(data): 296 """ 297 Set the x and y axes to the default 2D units 298 :param data: 2D data set 299 :return: 300 """ 301 data.xaxis("\\rm{Q_{x}}", '1/A') 302 data.yaxis("\\rm{Q_{y}}", '1/A') 303 data.zaxis("\\rm{Intensity}", "1/cm") 304 return data 305 306 def convert_data_units(self, default_q_unit="1/A"): 307 """ 308 Converts al; data to the sasview default of units of A^{-1} for Q and 309 cm^{-1} for I. 310 :param default_q_unit: The default Q unit used by Sasview 311 """ 312 convert_q = True 313 new_output = [] 314 for data in self.output: 315 if data.isSesans: 316 new_output.append(data) 317 continue 318 try: 319 file_x_unit = data._xunit 320 data_conv_x = Converter(file_x_unit) 321 except KeyError: 322 logger.info("Unrecognized Q units in data file. No data " 323 "conversion attempted") 324 convert_q = False 325 try: 326 327 if isinstance(data, Data1D): 328 if convert_q: 329 data.x = data_conv_x(data.x, units=default_q_unit) 330 data._xunit = default_q_unit 331 data.x_unit = default_q_unit 332 if data.dx is not None: 333 data.dx = data_conv_x(data.dx, 334 units=default_q_unit) 335 if data.dxl is not None: 336 data.dxl = data_conv_x(data.dxl, 337 units=default_q_unit) 338 if data.dxw is not None: 339 data.dxw = data_conv_x(data.dxw, 340 units=default_q_unit) 341 elif isinstance(data, Data2D): 342 if convert_q: 343 data.qx_data = data_conv_x(data.qx_data, 344 units=default_q_unit) 345 if data.dqx_data is not None: 346 data.dqx_data = data_conv_x(data.dqx_data, 347 units=default_q_unit) 348 try: 349 file_y_unit = data._yunit 350 data_conv_y = Converter(file_y_unit) 351 data.qy_data = data_conv_y(data.qy_data, 352 units=default_q_unit) 353 if data.dqy_data is not None: 354 data.dqy_data = data_conv_y(data.dqy_data, 355 units=default_q_unit) 356 except KeyError: 357 logger.info("Unrecognized Qy units in data file. No" 358 " data conversion attempted") 359 except KeyError: 360 message = "Unable to convert Q units from {0} to 1/A." 361 message.format(default_q_unit) 362 data.errors.append(message) 363 new_output.append(data) 364 self.output = new_output 244 def sort_two_d_data(self): 245 for dataset in self.output: 246 if isinstance(dataset, Data2D): 247 # Normalize the units for 248 dataset.x_unit = self.format_unit(dataset.Q_unit) 249 dataset.y_unit = self.format_unit(dataset.I_unit) 250 dataset.data = dataset.data.astype(np.float64) 251 dataset.qx_data = dataset.qx_data.astype(np.float64) 252 dataset.xmin = np.min(dataset.qx_data) 253 dataset.xmax = np.max(dataset.qx_data) 254 dataset.qy_data = dataset.qy_data.astype(np.float64) 255 dataset.ymin = np.min(dataset.qy_data) 256 dataset.ymax = np.max(dataset.qy_data) 257 dataset.q_data = np.sqrt(dataset.qx_data * dataset.qx_data 258 + dataset.qy_data * dataset.qy_data) 259 if dataset.err_data is not None: 260 dataset.err_data = dataset.err_data.astype(np.float64) 261 if dataset.dqx_data is not None: 262 dataset.dqx_data = dataset.dqx_data.astype(np.float64) 263 if dataset.dqy_data is not None: 264 dataset.dqy_data = dataset.dqy_data.astype(np.float64) 265 if dataset.mask is not None: 266 dataset.mask = dataset.mask.astype(dtype=bool) 267 268 if len(dataset.data.shape) == 2: 269 n_rows, n_cols = dataset.data.shape 270 dataset.y_bins = dataset.qy_data[0::int(n_cols)] 271 dataset.x_bins = dataset.qx_data[:int(n_cols)] 272 dataset.data = dataset.data.flatten() 273 dataset = self._remove_nans_in_data(dataset) 274 if len(dataset.data) > 0: 275 dataset.xmin = np.min(dataset.qx_data) 276 dataset.xmax = np.max(dataset.qx_data) 277 dataset.ymin = np.min(dataset.qy_data) 278 dataset.ymax = np.max(dataset.qy_data) 365 279 366 280 def format_unit(self, unit=None): … … 453 367 self.current_dataset.qy_data)) 454 368 if has_error_dy: 455 self.current_dataset.err_data = self.current_dataset.err_data[ 456 x != 0] 369 self.current_dataset.err_data = self.current_dataset.err_data[x != 0] 457 370 if has_error_dqx: 458 self.current_dataset.dqx_data = self.current_dataset.dqx_data[ 459 x != 0] 371 self.current_dataset.dqx_data = self.current_dataset.dqx_data[x != 0] 460 372 if has_error_dqy: 461 self.current_dataset.dqy_data = self.current_dataset.dqy_data[ 462 x != 0] 373 self.current_dataset.dqy_data = self.current_dataset.dqy_data[x != 0] 463 374 if has_mask: 464 375 self.current_dataset.mask = self.current_dataset.mask[x != 0] -
src/sas/sascalc/dataloader/loader.py
r8db20a9 rb8080e1 367 367 try: 368 368 return fn(path, data) 369 except Exception as exc: 370 msg = "Saving file {} using the {} writer failed.\n".format( 371 path, type(fn).__name__) 372 msg += str(exc) 373 logger.exception(msg) # give other loaders a chance to succeed 369 except Exception: 370 pass # give other loaders a chance to succeed 371 # If we get here it is because all loaders failed 372 raise # reraises last exception 374 373 375 374 -
src/sas/sascalc/dataloader/readers/abs_reader.py
r8db20a9 rb8080e1 48 48 detector = Detector() 49 49 data_line = 0 50 x_index = 451 50 self.reset_data_list(len(lines)) 52 51 self.current_datainfo.detector.append(detector) … … 64 63 for line in lines: 65 64 # Information line 1 66 if line.find(".bt5") > 0:67 x_index = 068 65 if is_info: 69 66 is_info = False … … 174 171 175 172 try: 176 _x = float(toks[ x_index])173 _x = float(toks[4]) 177 174 _y = float(toks[1]) 178 175 _dy = float(toks[2]) … … 228 225 raise ValueError("ascii_reader: could not load file") 229 226 230 self.current_dataset = self.set_default_1d_units(self.current_dataset)231 227 if data_conv_q is not None: 232 228 self.current_dataset.xaxis("\\rm{Q}", base_q_unit) 229 else: 230 self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 233 231 if data_conv_i is not None: 234 232 self.current_dataset.yaxis("\\rm{Intensity}", base_i_unit) 233 else: 234 self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 235 235 236 236 # Store loading process information -
src/sas/sascalc/dataloader/readers/ascii_reader.py
r8db20a9 r7b07fbe 157 157 158 158 self.remove_empty_q_values() 159 self.current_dataset = self.set_default_1d_units(self.current_dataset) 159 self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 160 self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 160 161 161 162 # Store loading process information -
src/sas/sascalc/dataloader/readers/associations.py
r8db20a9 rb8080e1 23 23 ".ses": "sesans_reader", 24 24 ".h5": "cansas_reader_HDF5", 25 ".nxs": "cansas_reader_HDF5",26 25 ".txt": "ascii_reader", 27 26 ".dat": "red2d_reader", -
src/sas/sascalc/dataloader/readers/cansas_reader.py
r8db20a9 rb1b71ad 812 812 node.append(point) 813 813 self.write_node(point, "Q", datainfo.x[i], 814 {'unit': datainfo. _xunit})814 {'unit': datainfo.x_unit}) 815 815 if len(datainfo.y) >= i: 816 816 self.write_node(point, "I", datainfo.y[i], 817 {'unit': datainfo. _yunit})817 {'unit': datainfo.y_unit}) 818 818 if datainfo.dy is not None and len(datainfo.dy) > i: 819 819 self.write_node(point, "Idev", datainfo.dy[i], 820 {'unit': datainfo. _yunit})820 {'unit': datainfo.y_unit}) 821 821 if datainfo.dx is not None and len(datainfo.dx) > i: 822 822 self.write_node(point, "Qdev", datainfo.dx[i], 823 {'unit': datainfo. _xunit})823 {'unit': datainfo.x_unit}) 824 824 if datainfo.dxw is not None and len(datainfo.dxw) > i: 825 825 self.write_node(point, "dQw", datainfo.dxw[i], 826 {'unit': datainfo. _xunit})826 {'unit': datainfo.x_unit}) 827 827 if datainfo.dxl is not None and len(datainfo.dxl) > i: 828 828 self.write_node(point, "dQl", datainfo.dxl[i], 829 {'unit': datainfo. _xunit})829 {'unit': datainfo.x_unit}) 830 830 if datainfo.isSesans: 831 831 sesans_attrib = {'x_axis': datainfo._xaxis, -
src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py
r8db20a9 rb8080e1 1 1 """ 2 NXcanSASdata reader for reading HDF5 formatted CanSAS files.2 CanSAS 2D data reader for reading HDF5 formatted CanSAS files. 3 3 """ 4 4 … … 12 12 Data1D, Data2D, DataInfo, Process, Aperture, Collimation, \ 13 13 TransmissionSpectrum, Detector 14 from ..data_info import combine_data_info_with_plottable 14 15 from ..loader_exceptions import FileContentsException, DefaultReaderException 15 16 from ..file_reader_base_class import FileReader, decode 16 17 17 try:18 basestring19 except NameError: # CRUFT: python 2 support20 basestring = str21 22 23 18 def h5attr(node, key, default=None): 24 19 return decode(node.attrs.get(key, default)) 25 20 26 27 21 class Reader(FileReader): 28 22 """ 29 A class for reading in NXcanSAS data files. The current implementation has30 been tested to load data generated by multiple facilities, all of which are31 known to produce NXcanSAS standards compliant data. Any number of data sets32 may be present within the file and any dimensionality of data may be used.33 Currently 1D and 2D SAS data sets are supported, but should be immediately34 extensible to SESANS data. 35 36 Any number of SASdata groups may be present in a SASentry and the data37 within each SASdata group can be a single 1D I(Q), multi-framed 1D I(Q), 38 2D I(Qx, Qy) or multi-framed 2D I(Qx, Qy).23 A class for reading in CanSAS v2.0 data files. The existing iteration opens 24 Mantid generated HDF5 formatted files with file extension .h5/.H5. Any 25 number of data sets may be present within the file and any dimensionality 26 of data may be used. Currently 1D and 2D SAS data sets are supported, but 27 future implementations will include 1D and 2D SESANS data. 28 29 Any number of SASdata sets may be present in a SASentry and the data within 30 can be either 1D I(Q) or 2D I(Qx, Qy). 31 32 Also supports reading NXcanSAS formatted HDF5 files 39 33 40 34 :Dependencies: 41 The NXcanSAS HDF5 reader requires h5py => v2.5.0 or later.35 The CanSAS HDF5 reader requires h5py => v2.5.0 or later. 42 36 """ 43 37 44 38 # CanSAS version 45 39 cansas_version = 2.0 40 # Logged warnings or messages 41 logging = None 42 # List of errors for the current data set 43 errors = None 44 # Raw file contents to be processed 45 raw_data = None 46 # List of plottable1D objects that should be linked to the current_datainfo 47 data1d = None 48 # List of plottable2D objects that should be linked to the current_datainfo 49 data2d = None 46 50 # Data type name 47 type_name = " NXcanSAS"51 type_name = "CanSAS 2.0" 48 52 # Wildcards 49 type = [" NXcanSAS HDF5 Files (*.h5)|*.h5|"]53 type = ["CanSAS 2.0 HDF5 Files (*.h5)|*.h5"] 50 54 # List of allowed extensions 51 55 ext = ['.h5', '.H5'] … … 77 81 except Exception as e: 78 82 if extension not in self.ext: 79 msg = "NXcanSAS Reader could not load file {}".format( 80 basename + extension) 83 msg = "CanSAS2.0 HDF5 Reader could not load file {}".format(basename + extension) 81 84 raise DefaultReaderException(msg) 82 85 raise FileContentsException(e.message) … … 92 95 self.raw_data.close() 93 96 94 for data_set in self.output: 95 if isinstance(data_set, Data1D): 96 if data_set.x.size < 5: 97 exception = FileContentsException( 98 "Fewer than 5 data points found.") 99 data_set.errors.append(exception) 97 for dataset in self.output: 98 if isinstance(dataset, Data1D): 99 if dataset.x.size < 5: 100 self.output = [] 101 raise FileContentsException("Fewer than 5 data points found.") 100 102 101 103 def reset_state(self): … … 107 109 self.data2d = [] 108 110 self.raw_data = None 109 self.multi_frame = False 110 self.data_frames = [] 111 self.data_uncertainty_frames = [] 112 self.errors = [] 111 self.errors = set() 113 112 self.logging = [] 114 self.q_names = []115 self.mask_name = u''116 self.i_name = u''117 self.i_node = u''118 self.i_uncertainties_name = u''119 self.q_uncertainty_names = []120 self.q_resolution_names = []121 113 self.parent_class = u'' 122 114 self.detector = Detector() … … 139 131 value = data.get(key) 140 132 class_name = h5attr(value, u'canSAS_class') 141 if isinstance(class_name, (list, tuple, np.ndarray)):142 class_name = class_name[0]143 133 if class_name is None: 144 134 class_name = h5attr(value, u'NX_class') … … 150 140 if isinstance(value, h5py.Group): 151 141 # Set parent class before recursion 152 last_parent_class = self.parent_class153 142 self.parent_class = class_name 154 143 parent_list.append(key) … … 158 147 self.add_data_set(key) 159 148 elif class_prog.match(u'SASdata'): 160 self._find_data_attributes(value) 161 self._initialize_new_data_set(value) 149 self._initialize_new_data_set(parent_list) 162 150 # Recursion step to access data within the group 163 151 self.read_children(value, parent_list) 152 # Reset parent class when returning from recursive method 153 self.parent_class = class_name 164 154 self.add_intermediate() 165 # Reset parent class when returning from recursive method166 self.parent_class = last_parent_class167 155 parent_list.remove(key) 168 156 169 157 elif isinstance(value, h5py.Dataset): 170 158 # If this is a dataset, store the data appropriately 171 data_set = value.value159 data_set = data[key][:] 172 160 unit = self._get_unit(value) 161 162 # I and Q Data 163 if key == u'I': 164 if isinstance(self.current_dataset, plottable_2D): 165 self.current_dataset.data = data_set 166 self.current_dataset.zaxis("Intensity", unit) 167 else: 168 self.current_dataset.y = data_set.flatten() 169 self.current_dataset.yaxis("Intensity", unit) 170 continue 171 elif key == u'Idev': 172 if isinstance(self.current_dataset, plottable_2D): 173 self.current_dataset.err_data = data_set.flatten() 174 else: 175 self.current_dataset.dy = data_set.flatten() 176 continue 177 elif key == u'Q': 178 self.current_dataset.xaxis("Q", unit) 179 if isinstance(self.current_dataset, plottable_2D): 180 self.current_dataset.q = data_set.flatten() 181 else: 182 self.current_dataset.x = data_set.flatten() 183 continue 184 elif key == u'Qdev': 185 self.current_dataset.dx = data_set.flatten() 186 continue 187 elif key == u'dQw': 188 self.current_dataset.dxw = data_set.flatten() 189 continue 190 elif key == u'dQl': 191 self.current_dataset.dxl = data_set.flatten() 192 continue 193 elif key == u'Qy': 194 self.current_dataset.yaxis("Q_y", unit) 195 self.current_dataset.qy_data = data_set.flatten() 196 continue 197 elif key == u'Qydev': 198 self.current_dataset.dqy_data = data_set.flatten() 199 continue 200 elif key == u'Qx': 201 self.current_dataset.xaxis("Q_x", unit) 202 self.current_dataset.qx_data = data_set.flatten() 203 continue 204 elif key == u'Qxdev': 205 self.current_dataset.dqx_data = data_set.flatten() 206 continue 207 elif key == u'Mask': 208 self.current_dataset.mask = data_set.flatten() 209 continue 210 # Transmission Spectrum 211 elif (key == u'T' 212 and self.parent_class == u'SAStransmission_spectrum'): 213 self.trans_spectrum.transmission = data_set.flatten() 214 continue 215 elif (key == u'Tdev' 216 and self.parent_class == u'SAStransmission_spectrum'): 217 self.trans_spectrum.transmission_deviation = \ 218 data_set.flatten() 219 continue 220 elif (key == u'lambda' 221 and self.parent_class == u'SAStransmission_spectrum'): 222 self.trans_spectrum.wavelength = data_set.flatten() 223 continue 173 224 174 225 for data_point in data_set: … … 180 231 # Top Level Meta Data 181 232 if key == u'definition': 182 if isinstance(data_set, basestring): 183 self.current_datainfo.meta_data['reader'] = data_set 184 break 185 else: 186 self.current_datainfo.meta_data[ 187 'reader'] = data_point 188 # Run 233 self.current_datainfo.meta_data['reader'] = data_point 189 234 elif key == u'run': 235 self.current_datainfo.run.append(data_point) 190 236 try: 191 237 run_name = h5attr(value, 'name') 192 run_dict = {data_ set: run_name}238 run_dict = {data_point: run_name} 193 239 self.current_datainfo.run_name = run_dict 194 240 except Exception: 195 241 pass 196 if isinstance(data_set, basestring):197 self.current_datainfo.run.append(data_set)198 break199 else:200 self.current_datainfo.run.append(data_point)201 # Title202 242 elif key == u'title': 203 if isinstance(data_set, basestring): 204 self.current_datainfo.title = data_set 205 break 206 else: 207 self.current_datainfo.title = data_point 208 # Note 243 self.current_datainfo.title = data_point 209 244 elif key == u'SASnote': 210 self.current_datainfo.notes.append(data_ set)211 break 245 self.current_datainfo.notes.append(data_point) 246 212 247 # Sample Information 213 elif self.parent_class == u'SASsample': 214 self.process_sample(data_point, key) 248 # CanSAS 2.0 format 249 elif key == u'Title' and self.parent_class == u'SASsample': 250 self.current_datainfo.sample.name = data_point 251 # NXcanSAS format 252 elif key == u'name' and self.parent_class == u'SASsample': 253 self.current_datainfo.sample.name = data_point 254 # NXcanSAS format 255 elif key == u'ID' and self.parent_class == u'SASsample': 256 self.current_datainfo.sample.name = data_point 257 elif (key == u'thickness' 258 and self.parent_class == u'SASsample'): 259 self.current_datainfo.sample.thickness = data_point 260 elif (key == u'temperature' 261 and self.parent_class == u'SASsample'): 262 self.current_datainfo.sample.temperature = data_point 263 elif (key == u'transmission' 264 and self.parent_class == u'SASsample'): 265 self.current_datainfo.sample.transmission = data_point 266 elif (key == u'x_position' 267 and self.parent_class == u'SASsample'): 268 self.current_datainfo.sample.position.x = data_point 269 elif (key == u'y_position' 270 and self.parent_class == u'SASsample'): 271 self.current_datainfo.sample.position.y = data_point 272 elif key == u'pitch' and self.parent_class == u'SASsample': 273 self.current_datainfo.sample.orientation.x = data_point 274 elif key == u'yaw' and self.parent_class == u'SASsample': 275 self.current_datainfo.sample.orientation.y = data_point 276 elif key == u'roll' and self.parent_class == u'SASsample': 277 self.current_datainfo.sample.orientation.z = data_point 278 elif (key == u'details' 279 and self.parent_class == u'SASsample'): 280 self.current_datainfo.sample.details.append(data_point) 281 215 282 # Instrumental Information 216 283 elif (key == u'name' 217 284 and self.parent_class == u'SASinstrument'): 218 285 self.current_datainfo.instrument = data_point 219 # Detector 220 elif self.parent_class == u'SASdetector': 221 self.process_detector(data_point, key, unit) 222 # Collimation 223 elif self.parent_class == u'SAScollimation': 224 self.process_collimation(data_point, key, unit) 225 # Aperture 226 elif self.parent_class == u'SASaperture': 227 self.process_aperture(data_point, key) 286 elif key == u'name' and self.parent_class == u'SASdetector': 287 self.detector.name = data_point 288 elif key == u'SDD' and self.parent_class == u'SASdetector': 289 self.detector.distance = float(data_point) 290 self.detector.distance_unit = unit 291 elif (key == u'slit_length' 292 and self.parent_class == u'SASdetector'): 293 self.detector.slit_length = float(data_point) 294 self.detector.slit_length_unit = unit 295 elif (key == u'x_position' 296 and self.parent_class == u'SASdetector'): 297 self.detector.offset.x = float(data_point) 298 self.detector.offset_unit = unit 299 elif (key == u'y_position' 300 and self.parent_class == u'SASdetector'): 301 self.detector.offset.y = float(data_point) 302 self.detector.offset_unit = unit 303 elif (key == u'pitch' 304 and self.parent_class == u'SASdetector'): 305 self.detector.orientation.x = float(data_point) 306 self.detector.orientation_unit = unit 307 elif key == u'roll' and self.parent_class == u'SASdetector': 308 self.detector.orientation.z = float(data_point) 309 self.detector.orientation_unit = unit 310 elif key == u'yaw' and self.parent_class == u'SASdetector': 311 self.detector.orientation.y = float(data_point) 312 self.detector.orientation_unit = unit 313 elif (key == u'beam_center_x' 314 and self.parent_class == u'SASdetector'): 315 self.detector.beam_center.x = float(data_point) 316 self.detector.beam_center_unit = unit 317 elif (key == u'beam_center_y' 318 and self.parent_class == u'SASdetector'): 319 self.detector.beam_center.y = float(data_point) 320 self.detector.beam_center_unit = unit 321 elif (key == u'x_pixel_size' 322 and self.parent_class == u'SASdetector'): 323 self.detector.pixel_size.x = float(data_point) 324 self.detector.pixel_size_unit = unit 325 elif (key == u'y_pixel_size' 326 and self.parent_class == u'SASdetector'): 327 self.detector.pixel_size.y = float(data_point) 328 self.detector.pixel_size_unit = unit 329 elif (key == u'distance' 330 and self.parent_class == u'SAScollimation'): 331 self.collimation.length = data_point 332 self.collimation.length_unit = unit 333 elif (key == u'name' 334 and self.parent_class == u'SAScollimation'): 335 self.collimation.name = data_point 336 elif (key == u'shape' 337 and self.parent_class == u'SASaperture'): 338 self.aperture.shape = data_point 339 elif (key == u'x_gap' 340 and self.parent_class == u'SASaperture'): 341 self.aperture.size.x = data_point 342 elif (key == u'y_gap' 343 and self.parent_class == u'SASaperture'): 344 self.aperture.size.y = data_point 345 228 346 # Process Information 229 elif self.parent_class == u'SASprocess': # CanSAS 2.0 230 self.process_process(data_point, key) 347 elif (key == u'Title' 348 and self.parent_class == u'SASprocess'): # CanSAS 2.0 349 self.process.name = data_point 350 elif (key == u'name' 351 and self.parent_class == u'SASprocess'): # NXcanSAS 352 self.process.name = data_point 353 elif (key == u'description' 354 and self.parent_class == u'SASprocess'): 355 self.process.description = data_point 356 elif key == u'date' and self.parent_class == u'SASprocess': 357 self.process.date = data_point 358 elif key == u'term' and self.parent_class == u'SASprocess': 359 self.process.term = data_point 360 elif self.parent_class == u'SASprocess': 361 self.process.notes.append(data_point) 362 231 363 # Source 232 elif self.parent_class == u'SASsource': 233 self.process_source(data_point, key, unit) 364 elif (key == u'wavelength' 365 and self.parent_class == u'SASdata'): 366 self.current_datainfo.source.wavelength = data_point 367 self.current_datainfo.source.wavelength_unit = unit 368 elif (key == u'incident_wavelength' 369 and self.parent_class == 'SASsource'): 370 self.current_datainfo.source.wavelength = data_point 371 self.current_datainfo.source.wavelength_unit = unit 372 elif (key == u'wavelength_max' 373 and self.parent_class == u'SASsource'): 374 self.current_datainfo.source.wavelength_max = data_point 375 self.current_datainfo.source.wavelength_max_unit = unit 376 elif (key == u'wavelength_min' 377 and self.parent_class == u'SASsource'): 378 self.current_datainfo.source.wavelength_min = data_point 379 self.current_datainfo.source.wavelength_min_unit = unit 380 elif (key == u'incident_wavelength_spread' 381 and self.parent_class == u'SASsource'): 382 self.current_datainfo.source.wavelength_spread = \ 383 data_point 384 self.current_datainfo.source.wavelength_spread_unit = \ 385 unit 386 elif (key == u'beam_size_x' 387 and self.parent_class == u'SASsource'): 388 self.current_datainfo.source.beam_size.x = data_point 389 self.current_datainfo.source.beam_size_unit = unit 390 elif (key == u'beam_size_y' 391 and self.parent_class == u'SASsource'): 392 self.current_datainfo.source.beam_size.y = data_point 393 self.current_datainfo.source.beam_size_unit = unit 394 elif (key == u'beam_shape' 395 and self.parent_class == u'SASsource'): 396 self.current_datainfo.source.beam_shape = data_point 397 elif (key == u'radiation' 398 and self.parent_class == u'SASsource'): 399 self.current_datainfo.source.radiation = data_point 400 elif (key == u'transmission' 401 and self.parent_class == u'SASdata'): 402 self.current_datainfo.sample.transmission = data_point 403 234 404 # Everything else goes in meta_data 235 elif self.parent_class == u'SASdata':236 if isinstance(self.current_dataset, plottable_2D):237 self.process_2d_data_object(data_set, key, unit)238 else:239 self.process_1d_data_object(data_set, key, unit)240 241 break242 elif self.parent_class == u'SAStransmission_spectrum':243 self.process_trans_spectrum(data_set, key)244 break245 405 else: 246 406 new_key = self._create_unique_key( … … 250 410 else: 251 411 # I don't know if this reachable code 252 self.errors.append("ShouldNeverHappenException") 253 254 def process_1d_data_object(self, data_set, key, unit): 255 """ 256 SASdata processor method for 1d data items 257 :param data_set: data from HDF5 file 258 :param key: canSAS_class attribute 259 :param unit: unit attribute 260 """ 261 if key == self.i_name: 262 if self.multi_frame: 263 for x in range(0, data_set.shape[0]): 264 self.data_frames.append(data_set[x].flatten()) 265 else: 266 self.current_dataset.y = data_set.flatten() 267 self.current_dataset.yaxis("Intensity", unit) 268 elif key == self.i_uncertainties_name: 269 if self.multi_frame: 270 for x in range(0, data_set.shape[0]): 271 self.data_uncertainty_frames.append(data_set[x].flatten()) 272 self.current_dataset.dy = data_set.flatten() 273 elif key in self.q_names: 274 self.current_dataset.xaxis("Q", unit) 275 self.current_dataset.x = data_set.flatten() 276 elif key in self.q_resolution_names: 277 if (len(self.q_resolution_names) > 1 278 and np.where(self.q_resolution_names == key)[0] == 0): 279 self.current_dataset.dxw = data_set.flatten() 280 elif (len(self.q_resolution_names) > 1 281 and np.where(self.q_resolution_names == key)[0] == 1): 282 self.current_dataset.dxl = data_set.flatten() 283 else: 284 self.current_dataset.dx = data_set.flatten() 285 elif key in self.q_uncertainty_names: 286 if (len(self.q_uncertainty_names) > 1 287 and np.where(self.q_uncertainty_names == key)[0] == 0): 288 self.current_dataset.dxw = data_set.flatten() 289 elif (len(self.q_uncertainty_names) > 1 290 and np.where(self.q_uncertainty_names == key)[0] == 1): 291 self.current_dataset.dxl = data_set.flatten() 292 else: 293 self.current_dataset.dx = data_set.flatten() 294 elif key == self.mask_name: 295 self.current_dataset.mask = data_set.flatten() 296 elif key == u'wavelength': 297 self.current_datainfo.source.wavelength = data_set[0] 298 self.current_datainfo.source.wavelength_unit = unit 299 300 def process_2d_data_object(self, data_set, key, unit): 301 if key == self.i_name: 302 self.current_dataset.data = data_set 303 self.current_dataset.zaxis("Intensity", unit) 304 elif key == self.i_uncertainties_name: 305 self.current_dataset.err_data = data_set.flatten() 306 elif key in self.q_names: 307 self.current_dataset.xaxis("Q_x", unit) 308 self.current_dataset.yaxis("Q_y", unit) 309 if self.q_names[0] == self.q_names[1]: 310 # All q data in a single array 311 self.current_dataset.qx_data = data_set[0] 312 self.current_dataset.qy_data = data_set[1] 313 elif self.q_names.index(key) == 0: 314 self.current_dataset.qx_data = data_set 315 elif self.q_names.index(key) == 1: 316 self.current_dataset.qy_data = data_set 317 elif key in self.q_uncertainty_names or key in self.q_resolution_names: 318 if ((self.q_uncertainty_names[0] == self.q_uncertainty_names[1]) or 319 (self.q_resolution_names[0] == self.q_resolution_names[1])): 320 # All q data in a single array 321 self.current_dataset.dqx_data = data_set[0].flatten() 322 self.current_dataset.dqy_data = data_set[1].flatten() 323 elif (self.q_uncertainty_names.index(key) == 0 or 324 self.q_resolution_names.index(key) == 0): 325 self.current_dataset.dqx_data = data_set.flatten() 326 elif (self.q_uncertainty_names.index(key) == 1 or 327 self.q_resolution_names.index(key) == 1): 328 self.current_dataset.dqy_data = data_set.flatten() 329 self.current_dataset.yaxis("Q_y", unit) 330 elif key == self.mask_name: 331 self.current_dataset.mask = data_set.flatten() 332 elif key == u'Qy': 333 self.current_dataset.yaxis("Q_y", unit) 334 self.current_dataset.qy_data = data_set.flatten() 335 elif key == u'Qydev': 336 self.current_dataset.dqy_data = data_set.flatten() 337 elif key == u'Qx': 338 self.current_dataset.xaxis("Q_x", unit) 339 self.current_dataset.qx_data = data_set.flatten() 340 elif key == u'Qxdev': 341 self.current_dataset.dqx_data = data_set.flatten() 342 343 def process_trans_spectrum(self, data_set, key): 344 """ 345 SAStransmission_spectrum processor 346 :param data_set: data from HDF5 file 347 :param key: canSAS_class attribute 348 """ 349 if key == u'T': 350 self.trans_spectrum.transmission = data_set.flatten() 351 elif key == u'Tdev': 352 self.trans_spectrum.transmission_deviation = data_set.flatten() 353 elif key == u'lambda': 354 self.trans_spectrum.wavelength = data_set.flatten() 355 356 def process_sample(self, data_point, key): 357 """ 358 SASsample processor 359 :param data_point: Single point from an HDF5 data file 360 :param key: class name data_point was taken from 361 """ 362 if key == u'Title': 363 self.current_datainfo.sample.name = data_point 364 elif key == u'name': 365 self.current_datainfo.sample.name = data_point 366 elif key == u'ID': 367 self.current_datainfo.sample.name = data_point 368 elif key == u'thickness': 369 self.current_datainfo.sample.thickness = data_point 370 elif key == u'temperature': 371 self.current_datainfo.sample.temperature = data_point 372 elif key == u'transmission': 373 self.current_datainfo.sample.transmission = data_point 374 elif key == u'x_position': 375 self.current_datainfo.sample.position.x = data_point 376 elif key == u'y_position': 377 self.current_datainfo.sample.position.y = data_point 378 elif key == u'pitch': 379 self.current_datainfo.sample.orientation.x = data_point 380 elif key == u'yaw': 381 self.current_datainfo.sample.orientation.y = data_point 382 elif key == u'roll': 383 self.current_datainfo.sample.orientation.z = data_point 384 elif key == u'details': 385 self.current_datainfo.sample.details.append(data_point) 386 387 def process_detector(self, data_point, key, unit): 388 """ 389 SASdetector processor 390 :param data_point: Single point from an HDF5 data file 391 :param key: class name data_point was taken from 392 :param unit: unit attribute from data set 393 """ 394 if key == u'name': 395 self.detector.name = data_point 396 elif key == u'SDD': 397 self.detector.distance = float(data_point) 398 self.detector.distance_unit = unit 399 elif key == u'slit_length': 400 self.detector.slit_length = float(data_point) 401 self.detector.slit_length_unit = unit 402 elif key == u'x_position': 403 self.detector.offset.x = float(data_point) 404 self.detector.offset_unit = unit 405 elif key == u'y_position': 406 self.detector.offset.y = float(data_point) 407 self.detector.offset_unit = unit 408 elif key == u'pitch': 409 self.detector.orientation.x = float(data_point) 410 self.detector.orientation_unit = unit 411 elif key == u'roll': 412 self.detector.orientation.z = float(data_point) 413 self.detector.orientation_unit = unit 414 elif key == u'yaw': 415 self.detector.orientation.y = float(data_point) 416 self.detector.orientation_unit = unit 417 elif key == u'beam_center_x': 418 self.detector.beam_center.x = float(data_point) 419 self.detector.beam_center_unit = unit 420 elif key == u'beam_center_y': 421 self.detector.beam_center.y = float(data_point) 422 self.detector.beam_center_unit = unit 423 elif key == u'x_pixel_size': 424 self.detector.pixel_size.x = float(data_point) 425 self.detector.pixel_size_unit = unit 426 elif key == u'y_pixel_size': 427 self.detector.pixel_size.y = float(data_point) 428 self.detector.pixel_size_unit = unit 429 430 def process_collimation(self, data_point, key, unit): 431 """ 432 SAScollimation processor 433 :param data_point: Single point from an HDF5 data file 434 :param key: class name data_point was taken from 435 :param unit: unit attribute from data set 436 """ 437 if key == u'distance': 438 self.collimation.length = data_point 439 self.collimation.length_unit = unit 440 elif key == u'name': 441 self.collimation.name = data_point 442 443 def process_aperture(self, data_point, key): 444 """ 445 SASaperture processor 446 :param data_point: Single point from an HDF5 data file 447 :param key: class name data_point was taken from 448 """ 449 if key == u'shape': 450 self.aperture.shape = data_point 451 elif key == u'x_gap': 452 self.aperture.size.x = data_point 453 elif key == u'y_gap': 454 self.aperture.size.y = data_point 455 456 def process_source(self, data_point, key, unit): 457 """ 458 SASsource processor 459 :param data_point: Single point from an HDF5 data file 460 :param key: class name data_point was taken from 461 :param unit: unit attribute from data set 462 """ 463 if key == u'incident_wavelength': 464 self.current_datainfo.source.wavelength = data_point 465 self.current_datainfo.source.wavelength_unit = unit 466 elif key == u'wavelength_max': 467 self.current_datainfo.source.wavelength_max = data_point 468 self.current_datainfo.source.wavelength_max_unit = unit 469 elif key == u'wavelength_min': 470 self.current_datainfo.source.wavelength_min = data_point 471 self.current_datainfo.source.wavelength_min_unit = unit 472 elif key == u'incident_wavelength_spread': 473 self.current_datainfo.source.wavelength_spread = data_point 474 self.current_datainfo.source.wavelength_spread_unit = unit 475 elif key == u'beam_size_x': 476 self.current_datainfo.source.beam_size.x = data_point 477 self.current_datainfo.source.beam_size_unit = unit 478 elif key == u'beam_size_y': 479 self.current_datainfo.source.beam_size.y = data_point 480 self.current_datainfo.source.beam_size_unit = unit 481 elif key == u'beam_shape': 482 self.current_datainfo.source.beam_shape = data_point 483 elif key == u'radiation': 484 self.current_datainfo.source.radiation = data_point 485 486 def process_process(self, data_point, key): 487 """ 488 SASprocess processor 489 :param data_point: Single point from an HDF5 data file 490 :param key: class name data_point was taken from 491 """ 492 term_match = re.compile(u'^term[0-9]+$') 493 if key == u'Title': # CanSAS 2.0 494 self.process.name = data_point 495 elif key == u'name': # NXcanSAS 496 self.process.name = data_point 497 elif key == u'description': 498 self.process.description = data_point 499 elif key == u'date': 500 self.process.date = data_point 501 elif term_match.match(key): 502 self.process.term.append(data_point) 503 else: 504 self.process.notes.append(data_point) 412 self.errors.add("ShouldNeverHappenException") 505 413 506 414 def add_intermediate(self): … … 532 440 self.data2d.append(self.current_dataset) 533 441 elif isinstance(self.current_dataset, plottable_1D): 534 if self.multi_frame: 535 for x in range(0, len(self.data_frames)): 536 self.current_dataset.y = self.data_frames[x] 537 if len(self.data_uncertainty_frames) > x: 538 self.current_dataset.dy = \ 539 self.data_uncertainty_frames[x] 540 self.data1d.append(self.current_dataset) 541 else: 542 self.data1d.append(self.current_dataset) 442 self.data1d.append(self.current_dataset) 543 443 544 444 def final_data_cleanup(self): … … 552 452 spectrum_list = [] 553 453 for spectrum in self.current_datainfo.trans_spectrum: 454 spectrum.transmission = np.delete(spectrum.transmission, [0]) 554 455 spectrum.transmission = spectrum.transmission.astype(np.float64) 456 spectrum.transmission_deviation = np.delete( 457 spectrum.transmission_deviation, [0]) 555 458 spectrum.transmission_deviation = \ 556 459 spectrum.transmission_deviation.astype(np.float64) 460 spectrum.wavelength = np.delete(spectrum.wavelength, [0]) 557 461 spectrum.wavelength = spectrum.wavelength.astype(np.float64) 558 462 if len(spectrum.transmission) > 0: … … 562 466 # Append errors to dataset and reset class errors 563 467 self.current_datainfo.errors = self.errors 564 self.errors = []468 self.errors.clear() 565 469 566 470 # Combine all plottables with datainfo and append each to output 567 471 # Type cast data arrays to float64 and find min/max as appropriate 568 472 for dataset in self.data2d: 473 zeros = np.ones(dataset.data.size, dtype=bool) 474 try: 475 for i in range(0, dataset.mask.size - 1): 476 zeros[i] = dataset.mask[i] 477 except: 478 self.errors.add(sys.exc_value) 479 dataset.mask = zeros 569 480 # Calculate the actual Q matrix 570 481 try: … … 573 484 * dataset.qx_data 574 485 + dataset.qy_data 575 * dataset.qy_data) .flatten()486 * dataset.qy_data) 576 487 except: 577 488 dataset.q_data = None 578 489 579 490 if dataset.data.ndim == 2: 580 dataset.y_bins = np.unique(dataset.qy_data.flatten()) 581 dataset.x_bins = np.unique(dataset.qx_data.flatten()) 491 (n_rows, n_cols) = dataset.data.shape 492 dataset.y_bins = dataset.qy_data[0::n_cols] 493 dataset.x_bins = dataset.qx_data[:n_cols] 582 494 dataset.data = dataset.data.flatten() 583 dataset.qx_data = dataset.qx_data.flatten()584 dataset.qy_data = dataset.qy_data.flatten()585 586 try:587 iter(dataset.mask)588 dataset.mask = np.invert(np.asarray(dataset.mask, dtype=bool))589 except TypeError:590 dataset.mask = np.ones(dataset.data.shape, dtype=bool)591 495 self.current_dataset = dataset 592 496 self.send_to_output() … … 607 511 if self.current_datainfo and self.current_dataset: 608 512 self.final_data_cleanup() 609 self.data_frames = []610 self.data_uncertainty_frames = []611 513 self.data1d = [] 612 514 self.data2d = [] 613 515 self.current_datainfo = DataInfo() 614 516 615 def _initialize_new_data_set(self, value=None): 517 518 def _initialize_new_data_set(self, parent_list=None): 616 519 """ 617 520 A private class method to generate a new 1D or 2D data object based on … … 621 524 :param parent_list: List of names of parent elements 622 525 """ 623 if self._is_2d_not_multi_frame(value): 526 527 if parent_list is None: 528 parent_list = [] 529 if self._find_intermediate(parent_list, "Qx"): 624 530 self.current_dataset = plottable_2D() 625 531 else: … … 629 535 self.current_datainfo.filename = self.raw_data.filename 630 536 631 @staticmethod 632 def as_list_or_array(iterable): 633 """ 634 Return value as a list if not already a list or array. 635 :param iterable: 537 def _find_intermediate(self, parent_list, basename=""): 538 """ 539 A private class used to find an entry by either using a direct key or 540 knowing the approximate basename. 541 542 :param parent_list: List of parents nodes in the HDF5 file 543 :param basename: Approximate name of an entry to search for 636 544 :return: 637 545 """ 638 if not (isinstance(iterable, np.ndarray) or isinstance(iterable, list)): 639 iterable = iterable.split(",") if isinstance(iterable, basestring)\ 640 else [iterable] 641 return iterable 642 643 def _find_data_attributes(self, value): 644 """ 645 A class to find the indices for Q, the name of the Qdev and Idev, and 646 the name of the mask. 647 :param value: SASdata/NXdata HDF5 Group 648 """ 649 # Initialize values to base types 650 self.mask_name = u'' 651 self.i_name = u'' 652 self.i_node = u'' 653 self.i_uncertainties_name = u'' 654 self.q_names = [] 655 self.q_uncertainty_names = [] 656 self.q_resolution_names = [] 657 # Get attributes 658 attrs = value.attrs 659 signal = attrs.get("signal", "I") 660 if isinstance(signal, bytes): 661 signal = signal.decode() 662 i_axes = attrs.get("I_axes", ["Q"]) 663 if isinstance(i_axes, bytes): 664 i_axes = i_axes.decode() 665 q_indices = attrs.get("Q_indices", [0]) 666 if isinstance(q_indices, bytes): 667 q_indices = q_indices.decode() 668 i_axes = self.as_list_or_array(i_axes) 669 keys = value.keys() 670 # Assign attributes to appropriate class variables 671 self.q_names = [i_axes[int(v)] for v in self.as_list_or_array(q_indices)] 672 self.mask_name = attrs.get("mask") 673 if isinstance(self.mask_name, bytes): 674 self.mask_name = self.mask_name.decode() 675 self.i_name = signal 676 self.i_node = value.get(self.i_name) 677 678 for item in self.q_names: 679 if item in keys: 680 q_vals = value.get(item) 681 if q_vals.attrs.get("uncertainties") is not None: 682 self.q_uncertainty_names = q_vals.attrs.get("uncertainties") 683 elif q_vals.attrs.get("uncertainty") is not None: 684 self.q_uncertainty_names = q_vals.attrs.get("uncertainty") 685 if isinstance(self.q_uncertainty_names, basestring): 686 self.q_uncertainty_names = self.q_uncertainty_names.split(",") 687 if q_vals.attrs.get("resolutions") is not None: 688 self.q_resolution_names = q_vals.attrs.get("resolutions") 689 if isinstance(self.q_resolution_names, basestring): 690 self.q_resolution_names = self.q_resolution_names.split(",") 691 if self.i_name in keys: 692 i_vals = value.get(self.i_name) 693 self.i_uncertainties_name = i_vals.attrs.get("uncertainties") 694 if self.i_uncertainties_name is None: 695 self.i_uncertainties_name = i_vals.attrs.get("uncertainty") 696 if isinstance(self.i_uncertainties_name, bytes): 697 key = self.i_uncertainties_name 698 self.i_uncertainties_name = key.decode() if isinstance(key, bytes) else key 699 700 def _is_2d_not_multi_frame(self, value, i_base="", q_base=""): 701 """ 702 A private class to determine if the data set is 1d or 2d. 703 704 :param value: Nexus/NXcanSAS data group 705 :param basename: Approximate name of an entry to search for 706 :return: True if 2D, otherwise false 707 """ 708 i_basename = i_base if i_base != "" else self.i_name 709 i_vals = value.get(i_basename) 710 q_basename = q_base if q_base != "" else self.q_names 711 q_vals = value.get(q_basename[0]) 712 self.multi_frame = (i_vals is not None and q_vals is not None 713 and len(i_vals.shape) != 1 714 and len(q_vals.shape) == 1) 715 return (i_vals is not None and len(i_vals.shape) != 1 716 and not self.multi_frame) 546 547 entry = False 548 key_prog = re.compile(basename) 549 top = self.raw_data 550 for parent in parent_list: 551 top = top.get(parent) 552 for key in top.keys(): 553 if key_prog.match(key): 554 entry = True 555 break 556 return entry 717 557 718 558 def _create_unique_key(self, dictionary, name, numb=0): … … 743 583 if unit is None: 744 584 unit = h5attr(value, u'unit') 585 # Convert the unit formats 586 if unit == "1/A": 587 unit = "A^{-1}" 588 elif unit == "1/cm": 589 unit = "cm^{-1}" 745 590 return unit -
src/sas/sascalc/dataloader/readers/danse_reader.py
r8db20a9 rb8080e1 180 180 detector.beam_center.y = center_y * pixel 181 181 182 self.current_dataset = self.set_default_2d_units(self.current_dataset) 182 183 self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}') 184 self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}') 185 self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}") 186 183 187 self.current_dataset.x_bins = x_vals 184 188 self.current_dataset.y_bins = y_vals -
src/sas/sascalc/dataloader/readers/red2d_reader.py
r8db20a9 rc8321cfc 317 317 318 318 # Units of axes 319 self.current_dataset = self.set_default_2d_units(self.current_dataset) 319 self.current_dataset.xaxis(r"\rm{Q_{x}}", 'A^{-1}') 320 self.current_dataset.yaxis(r"\rm{Q_{y}}", 'A^{-1}') 321 self.current_dataset.zaxis(r"\rm{Intensity}", "cm^{-1}") 320 322 321 323 # Store loading process information -
src/sas/sascalc/file_converter/nxcansas_writer.py
r8db20a9 r574adc7 8 8 import os 9 9 10 from sas.sascalc.dataloader.readers.cansas_reader_HDF5 import Reader 10 from sas.sascalc.dataloader.readers.cansas_reader_HDF5 import Reader as Cansas2Reader 11 11 from sas.sascalc.dataloader.data_info import Data1D, Data2D 12 12 13 class NXcanSASWriter( Reader):13 class NXcanSASWriter(Cansas2Reader): 14 14 """ 15 15 A class for writing in NXcanSAS data files. Any number of data sets may be … … 87 87 entry[names[2]].attrs['units'] = units 88 88 89 valid_data = all([is instance(d, (Data1D, Data2D)) for d in dataset])89 valid_data = all([issubclass(d.__class__, (Data1D, Data2D)) for d in dataset]) 90 90 if not valid_data: 91 raise ValueError("All entries of dataset must be Data1D or Data2D" 92 "objects") 91 raise ValueError("All entries of dataset must be Data1D or Data2D objects") 93 92 94 93 # Get run name and number from first Data object … … 110 109 sasentry.attrs['version'] = '1.0' 111 110 112 for i, data_obj in enumerate(dataset): 113 data_entry = sasentry.create_group("sasdata{0:0=2d}".format(i+1)) 111 i = 1 112 113 for data_obj in dataset: 114 data_entry = sasentry.create_group("sasdata{0:0=2d}".format(i)) 114 115 data_entry.attrs['canSAS_class'] = 'SASdata' 115 116 if isinstance(data_obj, Data1D): … … 117 118 elif isinstance(data_obj, Data2D): 118 119 self._write_2d_data(data_obj, data_entry) 120 i += 1 119 121 120 122 data_info = dataset[0] … … 146 148 sample_entry.create_dataset('details', data=details) 147 149 148 # Instrum ent metadata150 # Instrumment metadata 149 151 instrument_entry = sasentry.create_group('sasinstrument') 150 152 instrument_entry.attrs['canSAS_class'] = 'SASinstrument' … … 174 176 units=data_info.source.beam_size_unit, write_fn=_write_h5_float) 175 177 178 176 179 # Collimation metadata 177 180 if len(data_info.collimation) > 0: 178 for i, coll_info in enumerate(data_info.collimation): 181 i = 1 182 for coll_info in data_info.collimation: 179 183 collimation_entry = instrument_entry.create_group( 180 'sascollimation{0:0=2d}'.format(i + 1))184 'sascollimation{0:0=2d}'.format(i)) 181 185 collimation_entry.attrs['canSAS_class'] = 'SAScollimation' 182 186 if coll_info.length is not None: 183 187 _write_h5_float(collimation_entry, coll_info.length, 'SDD') 184 collimation_entry['SDD'].attrs['units'] =\ 185 coll_info.length_unit 188 collimation_entry['SDD'].attrs['units'] = coll_info.length_unit 186 189 if coll_info.name is not None: 187 190 collimation_entry['name'] = _h5_string(coll_info.name) 188 191 else: 189 # Create a blank one - at least 1 collimation required by format 190 instrument_entry.create_group('sascollimation01') 192 # Create a blank one - at least 1 set of collimation metadata 193 # required by format 194 collimation_entry = instrument_entry.create_group('sascollimation01') 191 195 192 196 # Detector metadata 193 197 if len(data_info.detector) > 0: 194 198 i = 1 195 for i, det_info in enumerate(data_info.detector):199 for det_info in data_info.detector: 196 200 detector_entry = instrument_entry.create_group( 197 'sasdetector{0:0=2d}'.format(i + 1))201 'sasdetector{0:0=2d}'.format(i)) 198 202 detector_entry.attrs['canSAS_class'] = 'SASdetector' 199 203 if det_info.distance is not None: 200 204 _write_h5_float(detector_entry, det_info.distance, 'SDD') 201 detector_entry['SDD'].attrs['units'] =\ 202 det_info.distance_unit 205 detector_entry['SDD'].attrs['units'] = det_info.distance_unit 203 206 if det_info.name is not None: 204 207 detector_entry['name'] = _h5_string(det_info.name) … … 206 209 detector_entry['name'] = _h5_string('') 207 210 if det_info.slit_length is not None: 208 _write_h5_float(detector_entry, det_info.slit_length, 209 'slit_length') 210 detector_entry['slit_length'].attrs['units'] =\ 211 det_info.slit_length_unit 211 _write_h5_float(detector_entry, det_info.slit_length, 'slit_length') 212 detector_entry['slit_length'].attrs['units'] = det_info.slit_length_unit 212 213 _write_h5_vector(detector_entry, det_info.offset) 213 214 # NXcanSAS doesn't save information about pitch, only roll … … 223 224 names=['x_pixel_size', 'y_pixel_size'], 224 225 write_fn=_write_h5_float, units=det_info.pixel_size_unit) 226 227 i += 1 225 228 else: 226 229 # Create a blank one - at least 1 detector required by format … … 228 231 detector_entry.attrs['canSAS_class'] = 'SASdetector' 229 232 detector_entry.attrs['name'] = '' 230 231 # Process meta data232 for i, process in enumerate(data_info.process):233 process_entry = sasentry.create_group('sasprocess{0:0=2d}'.format(234 i + 1))235 process_entry.attrs['canSAS_class'] = 'SASprocess'236 if process.name:237 name = _h5_string(process.name)238 process_entry.create_dataset('name', data=name)239 if process.date:240 date = _h5_string(process.date)241 process_entry.create_dataset('date', data=date)242 if process.description:243 desc = _h5_string(process.description)244 process_entry.create_dataset('description', data=desc)245 for j, term in enumerate(process.term):246 # Don't save empty terms247 if term:248 h5_term = _h5_string(term)249 process_entry.create_dataset('term{0:0=2d}'.format(250 j + 1), data=h5_term)251 for j, note in enumerate(process.notes):252 # Don't save empty notes253 if note:254 h5_note = _h5_string(note)255 process_entry.create_dataset('note{0:0=2d}'.format(256 j + 1), data=h5_note)257 258 # Transmission Spectrum259 for i, trans in enumerate(data_info.trans_spectrum):260 trans_entry = sasentry.create_group(261 'sastransmission_spectrum{0:0=2d}'.format(i + 1))262 trans_entry.attrs['canSAS_class'] = 'SAStransmission_spectrum'263 trans_entry.attrs['signal'] = 'T'264 trans_entry.attrs['T_axes'] = 'T'265 trans_entry.attrs['name'] = trans.name266 if trans.timestamp is not '':267 trans_entry.attrs['timestamp'] = trans.timestamp268 transmission = trans_entry.create_dataset('T',269 data=trans.transmission)270 transmission.attrs['unertainties'] = 'Tdev'271 trans_entry.create_dataset('Tdev',272 data=trans.transmission_deviation)273 trans_entry.create_dataset('lambda', data=trans.wavelength)274 233 275 234 note_entry = sasentry.create_group('sasnote'.format(i)) … … 295 254 data_entry.attrs['signal'] = 'I' 296 255 data_entry.attrs['I_axes'] = 'Q' 297 data_entry.attrs['Q_indices'] = [0] 298 q_entry = data_entry.create_dataset('Q', data=data_obj.x) 299 q_entry.attrs['units'] = data_obj.x_unit 300 i_entry = data_entry.create_dataset('I', data=data_obj.y) 301 i_entry.attrs['units'] = data_obj.y_unit 302 if data_obj.dy is not None: 303 i_entry.attrs['uncertainties'] = 'Idev' 304 i_dev_entry = data_entry.create_dataset('Idev', data=data_obj.dy) 305 i_dev_entry.attrs['units'] = data_obj.y_unit 306 if data_obj.dx is not None: 307 q_entry.attrs['resolutions'] = 'dQ' 308 dq_entry = data_entry.create_dataset('dQ', data=data_obj.dx) 309 dq_entry.attrs['units'] = data_obj.x_unit 310 elif data_obj.dxl is not None: 311 q_entry.attrs['resolutions'] = ['dQl','dQw'] 312 dql_entry = data_entry.create_dataset('dQl', data=data_obj.dxl) 313 dql_entry.attrs['units'] = data_obj.x_unit 314 dqw_entry = data_entry.create_dataset('dQw', data=data_obj.dxw) 315 dqw_entry.attrs['units'] = data_obj.x_unit 256 data_entry.attrs['I_uncertainties'] = 'Idev' 257 data_entry.attrs['Q_indicies'] = 0 258 259 dI = data_obj.dy 260 if dI is None: 261 dI = np.zeros((data_obj.y.shape)) 262 263 data_entry.create_dataset('Q', data=data_obj.x) 264 data_entry.create_dataset('I', data=data_obj.y) 265 data_entry.create_dataset('Idev', data=dI) 316 266 317 267 def _write_2d_data(self, data, data_entry): … … 323 273 """ 324 274 data_entry.attrs['signal'] = 'I' 325 data_entry.attrs['I_axes'] = 'Qx,Qy' 326 data_entry.attrs['Q_indices'] = [0,1] 275 data_entry.attrs['I_axes'] = 'Q,Q' 276 data_entry.attrs['I_uncertainties'] = 'Idev' 277 data_entry.attrs['Q_indicies'] = [0,1] 327 278 328 279 (n_rows, n_cols) = (len(data.y_bins), len(data.x_bins)) 329 280 330 if (n_rows == 0 and n_cols == 0) or (n_cols*n_rows != data.data.size):281 if n_rows == 0 and n_cols == 0: 331 282 # Calculate rows and columns, assuming detector is square 332 283 # Same logic as used in PlotPanel.py _get_bins … … 337 288 raise ValueError("Unable to calculate dimensions of 2D data") 338 289 339 intensity = np.reshape(data.data, (n_rows, n_cols)) 340 qx = np.reshape(data.qx_data, (n_rows, n_cols)) 290 I = np.reshape(data.data, (n_rows, n_cols)) 291 dI = np.zeros((n_rows, n_cols)) 292 if not all(data.err_data == [None]): 293 dI = np.reshape(data.err_data, (n_rows, n_cols)) 294 qx = np.reshape(data.qx_data, (n_rows, n_cols)) 341 295 qy = np.reshape(data.qy_data, (n_rows, n_cols)) 342 296 343 i_entry = data_entry.create_dataset('I', data=intensity) 344 i_entry.attrs['units'] = data.I_unit 345 qx_entry = data_entry.create_dataset('Qx', data=qx) 346 qx_entry.attrs['units'] = data.Q_unit 347 qy_entry = data_entry.create_dataset('Qy', data=qy) 348 qy_entry.attrs['units'] = data.Q_unit 349 if (data.err_data is not None 350 and not all(v is None for v in data.err_data)): 351 d_i = np.reshape(data.err_data, (n_rows, n_cols)) 352 i_entry.attrs['uncertainties'] = 'Idev' 353 i_dev_entry = data_entry.create_dataset('Idev', data=d_i) 354 i_dev_entry.attrs['units'] = data.I_unit 355 if (data.dqx_data is not None 356 and not all(v is None for v in data.dqx_data)): 357 qx_entry.attrs['resolutions'] = 'dQx' 358 dqx_entry = data_entry.create_dataset('dQx', data=data.dqx_data) 359 dqx_entry.attrs['units'] = data.Q_unit 360 if (data.dqy_data is not None 361 and not all(v is None for v in data.dqy_data)): 362 qy_entry.attrs['resolutions'] = 'dQy' 363 dqy_entry = data_entry.create_dataset('dQy', data=data.dqy_data) 364 dqy_entry.attrs['units'] = data.Q_unit 365 if data.mask is not None and not all(v is None for v in data.mask): 366 data_entry.attrs['mask'] = "mask" 367 mask = np.invert(np.asarray(data.mask, dtype=bool)) 368 data_entry.create_dataset('mask', data=mask) 297 I_entry = data_entry.create_dataset('I', data=I) 298 I_entry.attrs['units'] = data.I_unit 299 Qx_entry = data_entry.create_dataset('Qx', data=qx) 300 Qx_entry.attrs['units'] = data.Q_unit 301 Qy_entry = data_entry.create_dataset('Qy', data=qy) 302 Qy_entry.attrs['units'] = data.Q_unit 303 Idev_entry = data_entry.create_dataset('Idev', data=dI) 304 Idev_entry.attrs['units'] = data.I_unit
Note: See TracChangeset
for help on using the changeset viewer.