Changeset c222c27 in sasview for src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py
- Timestamp:
- Nov 15, 2018 2:09:18 PM (6 years ago)
- Branches:
- master, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249
- Children:
- 9220e89c
- Parents:
- a165bee (diff), f560e23 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py
r61f329f0 ra165bee 1 1 """ 2 CanSAS 2Ddata reader for reading HDF5 formatted CanSAS files.2 NXcanSAS 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_plottable15 14 from ..loader_exceptions import FileContentsException, DefaultReaderException 16 15 from ..file_reader_base_class import FileReader, decode 17 16 17 18 18 def h5attr(node, key, default=None): 19 19 return decode(node.attrs.get(key, default)) 20 20 21 21 22 class Reader(FileReader): 22 23 """ 23 A class for reading in CanSAS v2.0 data files. The existing iteration opens24 Mantid generated HDF5 formatted files with file extension .h5/.H5. Any25 number of data sets may be present within the file and any dimensionality26 of data may be used. Currently 1D and 2D SAS data sets are supported, but27 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 files24 A class for reading in NXcanSAS data files. The current implementation has 25 been tested to load data generated by multiple facilities, all of which are 26 known to produce NXcanSAS standards compliant data. Any number of data sets 27 may be present within the file and any dimensionality of data may be used. 28 Currently 1D and 2D SAS data sets are supported, but should be immediately 29 extensible to SESANS data. 30 31 Any number of SASdata groups may be present in a SASentry and the data 32 within each SASdata group can be a single 1D I(Q), multi-framed 1D I(Q), 33 2D I(Qx, Qy) or multi-framed 2D I(Qx, Qy). 33 34 34 35 :Dependencies: 35 The CanSAS HDF5 reader requires h5py => v2.5.0 or later.36 The NXcanSAS HDF5 reader requires h5py => v2.5.0 or later. 36 37 """ 37 38 38 39 # CanSAS version 39 40 cansas_version = 2.0 40 # Logged warnings or messages41 logging = None42 # List of errors for the current data set43 errors = None44 # Raw file contents to be processed45 raw_data = None46 # List of plottable1D objects that should be linked to the current_datainfo47 data1d = None48 # List of plottable2D objects that should be linked to the current_datainfo49 data2d = None50 41 # Data type name 51 type_name = " CanSAS 2.0"42 type_name = "NXcanSAS" 52 43 # Wildcards 53 type = [" CanSAS 2.0 HDF5 Files (*.h5)|*.h5"]44 type = ["NXcanSAS HDF5 Files (*.h5)|*.h5|"] 54 45 # List of allowed extensions 55 46 ext = ['.h5', '.H5'] … … 81 72 except Exception as e: 82 73 if extension not in self.ext: 83 msg = "CanSAS2.0 HDF5 Reader could not load file {}".format(basename + extension) 74 msg = "NXcanSAS Reader could not load file {}".format( 75 basename + extension) 84 76 raise DefaultReaderException(msg) 85 77 raise FileContentsException(e.message) … … 95 87 self.raw_data.close() 96 88 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.") 89 for data_set in self.output: 90 if isinstance(data_set, Data1D): 91 if data_set.x.size < 5: 92 exception = FileContentsException( 93 "Fewer than 5 data points found.") 94 data_set.errors.append(exception) 102 95 103 96 def reset_state(self): … … 109 102 self.data2d = [] 110 103 self.raw_data = None 111 self.errors = set() 104 self.multi_frame = False 105 self.data_frames = [] 106 self.data_uncertainty_frames = [] 107 self.errors = [] 112 108 self.logging = [] 109 self.q_names = [] 110 self.mask_name = u'' 111 self.i_name = u'' 112 self.i_node = u'' 113 self.i_uncertainties_name = u'' 114 self.q_uncertainty_names = [] 115 self.q_resolution_names = [] 113 116 self.parent_class = u'' 114 117 self.detector = Detector() … … 131 134 value = data.get(key) 132 135 class_name = h5attr(value, u'canSAS_class') 136 if isinstance(class_name, (list, tuple, np.ndarray)): 137 class_name = class_name[0] 133 138 if class_name is None: 134 139 class_name = h5attr(value, u'NX_class') … … 140 145 if isinstance(value, h5py.Group): 141 146 # Set parent class before recursion 147 last_parent_class = self.parent_class 142 148 self.parent_class = class_name 143 149 parent_list.append(key) … … 147 153 self.add_data_set(key) 148 154 elif class_prog.match(u'SASdata'): 149 self._initialize_new_data_set(parent_list) 155 self._find_data_attributes(value) 156 self._initialize_new_data_set(value) 150 157 # Recursion step to access data within the group 151 158 self.read_children(value, parent_list) 159 self.add_intermediate() 152 160 # Reset parent class when returning from recursive method 153 self.parent_class = class_name 154 self.add_intermediate() 161 self.parent_class = last_parent_class 155 162 parent_list.remove(key) 156 163 157 164 elif isinstance(value, h5py.Dataset): 158 165 # If this is a dataset, store the data appropriately 159 data_set = data[key][:]166 data_set = value.value 160 167 unit = self._get_unit(value) 161 162 # I and Q Data163 if key == u'I':164 if isinstance(self.current_dataset, plottable_2D):165 self.current_dataset.data = data_set166 self.current_dataset.zaxis("Intensity", unit)167 else:168 self.current_dataset.y = data_set.flatten()169 self.current_dataset.yaxis("Intensity", unit)170 continue171 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 continue177 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 continue184 elif key == u'Qdev':185 self.current_dataset.dx = data_set.flatten()186 continue187 elif key == u'dQw':188 self.current_dataset.dxw = data_set.flatten()189 continue190 elif key == u'dQl':191 self.current_dataset.dxl = data_set.flatten()192 continue193 elif key == u'Qy':194 self.current_dataset.yaxis("Q_y", unit)195 self.current_dataset.qy_data = data_set.flatten()196 continue197 elif key == u'Qydev':198 self.current_dataset.dqy_data = data_set.flatten()199 continue200 elif key == u'Qx':201 self.current_dataset.xaxis("Q_x", unit)202 self.current_dataset.qx_data = data_set.flatten()203 continue204 elif key == u'Qxdev':205 self.current_dataset.dqx_data = data_set.flatten()206 continue207 elif key == u'Mask':208 self.current_dataset.mask = data_set.flatten()209 continue210 # Transmission Spectrum211 elif (key == u'T'212 and self.parent_class == u'SAStransmission_spectrum'):213 self.trans_spectrum.transmission = data_set.flatten()214 continue215 elif (key == u'Tdev'216 and self.parent_class == u'SAStransmission_spectrum'):217 self.trans_spectrum.transmission_deviation = \218 data_set.flatten()219 continue220 elif (key == u'lambda'221 and self.parent_class == u'SAStransmission_spectrum'):222 self.trans_spectrum.wavelength = data_set.flatten()223 continue224 168 225 169 for data_point in data_set: … … 231 175 # Top Level Meta Data 232 176 if key == u'definition': 233 self.current_datainfo.meta_data['reader'] = data_point 177 if isinstance(data_set, basestring): 178 self.current_datainfo.meta_data['reader'] = data_set 179 break 180 else: 181 self.current_datainfo.meta_data[ 182 'reader'] = data_point 183 # Run 234 184 elif key == u'run': 235 self.current_datainfo.run.append(data_point)236 185 try: 237 186 run_name = h5attr(value, 'name') 238 run_dict = {data_ point: run_name}187 run_dict = {data_set: run_name} 239 188 self.current_datainfo.run_name = run_dict 240 189 except Exception: 241 190 pass 191 if isinstance(data_set, basestring): 192 self.current_datainfo.run.append(data_set) 193 break 194 else: 195 self.current_datainfo.run.append(data_point) 196 # Title 242 197 elif key == u'title': 243 self.current_datainfo.title = data_point 198 if isinstance(data_set, basestring): 199 self.current_datainfo.title = data_set 200 break 201 else: 202 self.current_datainfo.title = data_point 203 # Note 244 204 elif key == u'SASnote': 245 self.current_datainfo.notes.append(data_ point)246 205 self.current_datainfo.notes.append(data_set) 206 break 247 207 # Sample Information 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 208 elif self.parent_class == u'SASsample': 209 self.process_sample(data_point, key) 282 210 # Instrumental Information 283 211 elif (key == u'name' 284 212 and self.parent_class == u'SASinstrument'): 285 213 self.current_datainfo.instrument = data_point 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 214 # Detector 215 elif self.parent_class == u'SASdetector': 216 self.process_detector(data_point, key, unit) 217 # Collimation 218 elif self.parent_class == u'SAScollimation': 219 self.process_collimation(data_point, key, unit) 220 # Aperture 221 elif self.parent_class == u'SASaperture': 222 self.process_aperture(data_point, key) 346 223 # Process Information 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 224 elif self.parent_class == u'SASprocess': # CanSAS 2.0 225 self.process_process(data_point, key) 363 226 # Source 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 227 elif self.parent_class == u'SASsource': 228 self.process_source(data_point, key, unit) 404 229 # Everything else goes in meta_data 230 elif self.parent_class == u'SASdata': 231 if isinstance(self.current_dataset, plottable_2D): 232 self.process_2d_data_object(data_set, key, unit) 233 else: 234 self.process_1d_data_object(data_set, key, unit) 235 236 break 237 elif self.parent_class == u'SAStransmission_spectrum': 238 self.process_trans_spectrum(data_set, key) 239 break 405 240 else: 406 241 new_key = self._create_unique_key( … … 410 245 else: 411 246 # I don't know if this reachable code 412 self.errors.add("ShouldNeverHappenException") 247 self.errors.append("ShouldNeverHappenException") 248 249 def process_1d_data_object(self, data_set, key, unit): 250 """ 251 SASdata processor method for 1d data items 252 :param data_set: data from HDF5 file 253 :param key: canSAS_class attribute 254 :param unit: unit attribute 255 """ 256 if key == self.i_name: 257 if self.multi_frame: 258 for x in range(0, data_set.shape[0]): 259 self.data_frames.append(data_set[x].flatten()) 260 else: 261 self.current_dataset.y = data_set.flatten() 262 self.current_dataset.yaxis("Intensity", unit) 263 elif key == self.i_uncertainties_name: 264 if self.multi_frame: 265 for x in range(0, data_set.shape[0]): 266 self.data_uncertainty_frames.append(data_set[x].flatten()) 267 self.current_dataset.dy = data_set.flatten() 268 elif key in self.q_names: 269 self.current_dataset.xaxis("Q", unit) 270 self.current_dataset.x = data_set.flatten() 271 elif key in self.q_resolution_names: 272 if (len(self.q_resolution_names) > 1 273 and np.where(self.q_resolution_names == key)[0] == 0): 274 self.current_dataset.dxw = data_set.flatten() 275 elif (len(self.q_resolution_names) > 1 276 and np.where(self.q_resolution_names == key)[0] == 1): 277 self.current_dataset.dxl = data_set.flatten() 278 else: 279 self.current_dataset.dx = data_set.flatten() 280 elif key in self.q_uncertainty_names: 281 if (len(self.q_uncertainty_names) > 1 282 and np.where(self.q_uncertainty_names == key)[0] == 0): 283 self.current_dataset.dxw = data_set.flatten() 284 elif (len(self.q_uncertainty_names) > 1 285 and np.where(self.q_uncertainty_names == key)[0] == 1): 286 self.current_dataset.dxl = data_set.flatten() 287 else: 288 self.current_dataset.dx = data_set.flatten() 289 elif key == self.mask_name: 290 self.current_dataset.mask = data_set.flatten() 291 elif key == u'wavelength': 292 self.current_datainfo.source.wavelength = data_set[0] 293 self.current_datainfo.source.wavelength_unit = unit 294 295 def process_2d_data_object(self, data_set, key, unit): 296 if key == self.i_name: 297 self.current_dataset.data = data_set 298 self.current_dataset.zaxis("Intensity", unit) 299 elif key == self.i_uncertainties_name: 300 self.current_dataset.err_data = data_set.flatten() 301 elif key in self.q_names: 302 self.current_dataset.xaxis("Q_x", unit) 303 self.current_dataset.yaxis("Q_y", unit) 304 if self.q_names[0] == self.q_names[1]: 305 # All q data in a single array 306 self.current_dataset.qx_data = data_set[0] 307 self.current_dataset.qy_data = data_set[1] 308 elif self.q_names.index(key) == 0: 309 self.current_dataset.qx_data = data_set 310 elif self.q_names.index(key) == 1: 311 self.current_dataset.qy_data = data_set 312 elif key in self.q_uncertainty_names or key in self.q_resolution_names: 313 if ((self.q_uncertainty_names[0] == self.q_uncertainty_names[1]) or 314 (self.q_resolution_names[0] == self.q_resolution_names[1])): 315 # All q data in a single array 316 self.current_dataset.dqx_data = data_set[0].flatten() 317 self.current_dataset.dqy_data = data_set[1].flatten() 318 elif (self.q_uncertainty_names.index(key) == 0 or 319 self.q_resolution_names.index(key) == 0): 320 self.current_dataset.dqx_data = data_set.flatten() 321 elif (self.q_uncertainty_names.index(key) == 1 or 322 self.q_resolution_names.index(key) == 1): 323 self.current_dataset.dqy_data = data_set.flatten() 324 self.current_dataset.yaxis("Q_y", unit) 325 elif key == self.mask_name: 326 self.current_dataset.mask = data_set.flatten() 327 elif key == u'Qy': 328 self.current_dataset.yaxis("Q_y", unit) 329 self.current_dataset.qy_data = data_set.flatten() 330 elif key == u'Qydev': 331 self.current_dataset.dqy_data = data_set.flatten() 332 elif key == u'Qx': 333 self.current_dataset.xaxis("Q_x", unit) 334 self.current_dataset.qx_data = data_set.flatten() 335 elif key == u'Qxdev': 336 self.current_dataset.dqx_data = data_set.flatten() 337 338 def process_trans_spectrum(self, data_set, key): 339 """ 340 SAStransmission_spectrum processor 341 :param data_set: data from HDF5 file 342 :param key: canSAS_class attribute 343 """ 344 if key == u'T': 345 self.trans_spectrum.transmission = data_set.flatten() 346 elif key == u'Tdev': 347 self.trans_spectrum.transmission_deviation = data_set.flatten() 348 elif key == u'lambda': 349 self.trans_spectrum.wavelength = data_set.flatten() 350 351 def process_sample(self, data_point, key): 352 """ 353 SASsample processor 354 :param data_point: Single point from an HDF5 data file 355 :param key: class name data_point was taken from 356 """ 357 if key == u'Title': 358 self.current_datainfo.sample.name = data_point 359 elif key == u'name': 360 self.current_datainfo.sample.name = data_point 361 elif key == u'ID': 362 self.current_datainfo.sample.name = data_point 363 elif key == u'thickness': 364 self.current_datainfo.sample.thickness = data_point 365 elif key == u'temperature': 366 self.current_datainfo.sample.temperature = data_point 367 elif key == u'transmission': 368 self.current_datainfo.sample.transmission = data_point 369 elif key == u'x_position': 370 self.current_datainfo.sample.position.x = data_point 371 elif key == u'y_position': 372 self.current_datainfo.sample.position.y = data_point 373 elif key == u'pitch': 374 self.current_datainfo.sample.orientation.x = data_point 375 elif key == u'yaw': 376 self.current_datainfo.sample.orientation.y = data_point 377 elif key == u'roll': 378 self.current_datainfo.sample.orientation.z = data_point 379 elif key == u'details': 380 self.current_datainfo.sample.details.append(data_point) 381 382 def process_detector(self, data_point, key, unit): 383 """ 384 SASdetector processor 385 :param data_point: Single point from an HDF5 data file 386 :param key: class name data_point was taken from 387 :param unit: unit attribute from data set 388 """ 389 if key == u'name': 390 self.detector.name = data_point 391 elif key == u'SDD': 392 self.detector.distance = float(data_point) 393 self.detector.distance_unit = unit 394 elif key == u'slit_length': 395 self.detector.slit_length = float(data_point) 396 self.detector.slit_length_unit = unit 397 elif key == u'x_position': 398 self.detector.offset.x = float(data_point) 399 self.detector.offset_unit = unit 400 elif key == u'y_position': 401 self.detector.offset.y = float(data_point) 402 self.detector.offset_unit = unit 403 elif key == u'pitch': 404 self.detector.orientation.x = float(data_point) 405 self.detector.orientation_unit = unit 406 elif key == u'roll': 407 self.detector.orientation.z = float(data_point) 408 self.detector.orientation_unit = unit 409 elif key == u'yaw': 410 self.detector.orientation.y = float(data_point) 411 self.detector.orientation_unit = unit 412 elif key == u'beam_center_x': 413 self.detector.beam_center.x = float(data_point) 414 self.detector.beam_center_unit = unit 415 elif key == u'beam_center_y': 416 self.detector.beam_center.y = float(data_point) 417 self.detector.beam_center_unit = unit 418 elif key == u'x_pixel_size': 419 self.detector.pixel_size.x = float(data_point) 420 self.detector.pixel_size_unit = unit 421 elif key == u'y_pixel_size': 422 self.detector.pixel_size.y = float(data_point) 423 self.detector.pixel_size_unit = unit 424 425 def process_collimation(self, data_point, key, unit): 426 """ 427 SAScollimation processor 428 :param data_point: Single point from an HDF5 data file 429 :param key: class name data_point was taken from 430 :param unit: unit attribute from data set 431 """ 432 if key == u'distance': 433 self.collimation.length = data_point 434 self.collimation.length_unit = unit 435 elif key == u'name': 436 self.collimation.name = data_point 437 438 def process_aperture(self, data_point, key): 439 """ 440 SASaperture processor 441 :param data_point: Single point from an HDF5 data file 442 :param key: class name data_point was taken from 443 """ 444 if key == u'shape': 445 self.aperture.shape = data_point 446 elif key == u'x_gap': 447 self.aperture.size.x = data_point 448 elif key == u'y_gap': 449 self.aperture.size.y = data_point 450 451 def process_source(self, data_point, key, unit): 452 """ 453 SASsource processor 454 :param data_point: Single point from an HDF5 data file 455 :param key: class name data_point was taken from 456 :param unit: unit attribute from data set 457 """ 458 if key == u'incident_wavelength': 459 self.current_datainfo.source.wavelength = data_point 460 self.current_datainfo.source.wavelength_unit = unit 461 elif key == u'wavelength_max': 462 self.current_datainfo.source.wavelength_max = data_point 463 self.current_datainfo.source.wavelength_max_unit = unit 464 elif key == u'wavelength_min': 465 self.current_datainfo.source.wavelength_min = data_point 466 self.current_datainfo.source.wavelength_min_unit = unit 467 elif key == u'incident_wavelength_spread': 468 self.current_datainfo.source.wavelength_spread = data_point 469 self.current_datainfo.source.wavelength_spread_unit = unit 470 elif key == u'beam_size_x': 471 self.current_datainfo.source.beam_size.x = data_point 472 self.current_datainfo.source.beam_size_unit = unit 473 elif key == u'beam_size_y': 474 self.current_datainfo.source.beam_size.y = data_point 475 self.current_datainfo.source.beam_size_unit = unit 476 elif key == u'beam_shape': 477 self.current_datainfo.source.beam_shape = data_point 478 elif key == u'radiation': 479 self.current_datainfo.source.radiation = data_point 480 481 def process_process(self, data_point, key): 482 """ 483 SASprocess processor 484 :param data_point: Single point from an HDF5 data file 485 :param key: class name data_point was taken from 486 """ 487 term_match = re.compile(u'^term[0-9]+$') 488 if key == u'Title': # CanSAS 2.0 489 self.process.name = data_point 490 elif key == u'name': # NXcanSAS 491 self.process.name = data_point 492 elif key == u'description': 493 self.process.description = data_point 494 elif key == u'date': 495 self.process.date = data_point 496 elif term_match.match(key): 497 self.process.term.append(data_point) 498 else: 499 self.process.notes.append(data_point) 413 500 414 501 def add_intermediate(self): … … 440 527 self.data2d.append(self.current_dataset) 441 528 elif isinstance(self.current_dataset, plottable_1D): 442 self.data1d.append(self.current_dataset) 529 if self.multi_frame: 530 for x in range(0, len(self.data_frames)): 531 self.current_dataset.y = self.data_frames[x] 532 if len(self.data_uncertainty_frames) > x: 533 self.current_dataset.dy = \ 534 self.data_uncertainty_frames[x] 535 self.data1d.append(self.current_dataset) 536 else: 537 self.data1d.append(self.current_dataset) 443 538 444 539 def final_data_cleanup(self): … … 452 547 spectrum_list = [] 453 548 for spectrum in self.current_datainfo.trans_spectrum: 454 spectrum.transmission = np.delete(spectrum.transmission, [0])455 549 spectrum.transmission = spectrum.transmission.astype(np.float64) 456 spectrum.transmission_deviation = np.delete(457 spectrum.transmission_deviation, [0])458 550 spectrum.transmission_deviation = \ 459 551 spectrum.transmission_deviation.astype(np.float64) 460 spectrum.wavelength = np.delete(spectrum.wavelength, [0])461 552 spectrum.wavelength = spectrum.wavelength.astype(np.float64) 462 553 if len(spectrum.transmission) > 0: … … 466 557 # Append errors to dataset and reset class errors 467 558 self.current_datainfo.errors = self.errors 468 self.errors .clear()559 self.errors = [] 469 560 470 561 # Combine all plottables with datainfo and append each to output … … 476 567 zeros[i] = dataset.mask[i] 477 568 except: 478 self.errors.a dd(sys.exc_value)569 self.errors.append(sys.exc_value) 479 570 dataset.mask = zeros 480 571 # Calculate the actual Q matrix … … 490 581 if dataset.data.ndim == 2: 491 582 (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] 583 flat_qy = dataset.qy_data[0::n_cols].flatten() 584 # For 2D arrays of Qx and Qy, the Q value should be constant 585 # along each row -OR- each column. The direction is not 586 # specified in the NXcanSAS standard. 587 if flat_qy[0] == flat_qy[1]: 588 flat_qy = np.transpose(dataset.qy_data)[0::n_cols].flatten() 589 dataset.y_bins = np.unique(flat_qy) 590 flat_qx = dataset.qx_data[0::n_rows].flatten() 591 # For 2D arrays of Qx and Qy, the Q value should be constant 592 # along each row -OR- each column. The direction is not 593 # specified in the NXcanSAS standard. 594 if flat_qx[0] == flat_qx[1]: 595 flat_qx = np.transpose(dataset.qx_data)[0::n_rows].flatten() 596 dataset.x_bins = np.unique(flat_qx) 494 597 dataset.data = dataset.data.flatten() 598 dataset.qx_data = dataset.qx_data.flatten() 599 dataset.qy_data = dataset.qy_data.flatten() 495 600 self.current_dataset = dataset 496 601 self.send_to_output() … … 511 616 if self.current_datainfo and self.current_dataset: 512 617 self.final_data_cleanup() 618 self.data_frames = [] 619 self.data_uncertainty_frames = [] 513 620 self.data1d = [] 514 621 self.data2d = [] 515 622 self.current_datainfo = DataInfo() 516 623 517 518 def _initialize_new_data_set(self, parent_list=None): 624 def _initialize_new_data_set(self, value=None): 519 625 """ 520 626 A private class method to generate a new 1D or 2D data object based on … … 524 630 :param parent_list: List of names of parent elements 525 631 """ 526 527 if parent_list is None: 528 parent_list = [] 529 if self._find_intermediate(parent_list, "Qx"): 632 if self._is2d(value): 530 633 self.current_dataset = plottable_2D() 531 634 else: … … 535 638 self.current_datainfo.filename = self.raw_data.filename 536 639 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 640 @staticmethod 641 def check_is_list_or_array(iterable): 642 try: 643 iter(iterable) 644 if (not isinstance(iterable, np.ndarray) and not isinstance( 645 iterable, list)) or (isinstance(iterable, basestring)): 646 raise TypeError 647 except TypeError: 648 if isinstance(iterable, basestring): 649 iterable = iterable.split(",") 650 else: 651 iterable = [iterable] 652 return iterable 653 654 def _find_data_attributes(self, value): 655 """ 656 A class to find the indices for Q, the name of the Qdev and Idev, and 657 the name of the mask. 658 :param value: SASdata/NXdata HDF5 Group 659 """ 660 # Initialize values to base types 661 self.mask_name = u'' 662 self.i_name = u'' 663 self.i_node = u'' 664 self.i_uncertainties_name = u'' 665 self.q_names = [] 666 self.q_uncertainty_names = [] 667 self.q_resolution_names = [] 668 # Get attributes 669 attrs = value.attrs 670 signal = attrs.get("signal", "I") 671 i_axes = attrs.get("I_axes", ["Q"]) 672 q_indices = attrs.get("Q_indices", [0]) 673 q_indices = map(int, self.check_is_list_or_array(q_indices)) 674 i_axes = self.check_is_list_or_array(i_axes) 675 keys = value.keys() 676 # Assign attributes to appropriate class variables 677 self.mask_name = attrs.get("mask") 678 for val in q_indices: 679 self.q_names.append(i_axes[val]) 680 self.i_name = signal 681 self.i_node = value.get(self.i_name) 682 for item in self.q_names: 683 if item in keys: 684 q_vals = value.get(item) 685 if q_vals.attrs.get("uncertainties") is not None: 686 self.q_uncertainty_names = q_vals.attrs.get("uncertainties") 687 elif q_vals.attrs.get("uncertainty") is not None: 688 self.q_uncertainty_names = q_vals.attrs.get("uncertainty") 689 if isinstance(self.q_uncertainty_names, basestring): 690 self.q_uncertainty_names = self.q_uncertainty_names.split(",") 691 if q_vals.attrs.get("resolutions") is not None: 692 self.q_resolution_names = q_vals.attrs.get("resolutions") 693 if isinstance(self.q_resolution_names, basestring): 694 self.q_resolution_names = self.q_resolution_names.split(",") 695 if self.i_name in keys: 696 i_vals = value.get(self.i_name) 697 self.i_uncertainties_name = i_vals.attrs.get("uncertainties") 698 if self.i_uncertainties_name is None: 699 self.i_uncertainties_name = i_vals.attrs.get("uncertainty") 700 701 def _is2d(self, value, i_base="", q_base=[]): 702 """ 703 A private class to determine if the data set is 1d or 2d. 704 705 :param value: Nexus/NXcanSAS data group 543 706 :param basename: Approximate name of an entry to search for 544 :return: 545 """ 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 707 :return: True if 2D, otherwise false 708 """ 709 i_basename = i_base if i_base != "" else self.i_name 710 i_vals = value.get(i_basename) 711 q_basename = q_base if q_base != [] else self.q_names 712 q_vals = value.get(q_basename[0]) 713 self.multi_frame = True if (i_vals is not None and q_vals is not None 714 and len(i_vals.shape) != 1 715 and len(q_vals.shape) == 1) else False 716 return (i_vals is not None and i_vals.shape is not None 717 and len(i_vals.shape) != 1 and not self.multi_frame) 557 718 558 719 def _create_unique_key(self, dictionary, name, numb=0): … … 583 744 if unit is None: 584 745 unit = h5attr(value, u'unit') 585 # Convert the unit formats586 if unit == "1/A":587 unit = "A^{-1}"588 elif unit == "1/cm":589 unit = "cm^{-1}"590 746 return unit
Note: See TracChangeset
for help on using the changeset viewer.