Changeset eb98f24 in sasview


Ignore:
Timestamp:
Aug 18, 2016 8:35:43 AM (8 years ago)
Author:
lewis
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
afbd172
Parents:
8cb1a07
Message:

Refactor write method to its own class

The cansas_reader_HDF5 read method is designed for reading CanSAS 2.0 HDF5
formatted files, but will also read NXcanSAS files. The write method was
following the NXcanSAS spec, so has been moved to its own class to avoid
confusion between then two (very simillar) formats.

Location:
src/sas/sascalc
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py

    r8cb1a07 reb98f24  
    182182 
    183183                    ## Sample Information 
    184                     elif key == u'Title' and self.parent_class == u'SASsample': 
     184                    elif key == u'Title' and self.parent_class == u'SASsample': # CanSAS 2.0 format 
    185185                        self.current_datainfo.sample.name = data_point 
    186                     elif key == u'name' and self.parent_class == u'SASsample': 
     186                    elif key == u'name' and self.parent_class == u'SASsample': # NXcanSAS format 
    187187                        self.current_datainfo.sample.name = data_point 
    188188                    elif key == u'thickness' and self.parent_class == u'SASsample': 
     
    208208                    elif key == u'name' and self.parent_class == u'SASprocess': 
    209209                        self.process.name = data_point 
    210                     elif key == u'Title' and self.parent_class == u'SASprocess': 
     210                    elif key == u'Title' and self.parent_class == u'SASprocess': # CanSAS 2.0 format 
    211211                        self.process.name = data_point 
    212                     elif key == u'name' and self.parent_class == u'SASprocess': 
     212                    elif key == u'name' and self.parent_class == u'SASprocess': # NXcanSAS format 
    213213                        self.process.name = data_point 
    214214                    elif key == u'description' and self.parent_class == u'SASprocess': 
     
    380380        self.current_datainfo = DataInfo() 
    381381 
    382     def write(self, dataset, filename): 
    383         """ 
    384         Write an array of Data1d or Data2D objects to a CanSAS 2.0 file, as 
    385         one SASEntry with multiple SASData elements. The metadata of the first 
    386         elememt in the array will be written as the SASentry metadata 
    387         (detector, instrument, sample, etc) 
    388  
    389         :param dataset: A list of Data1D or Data2D objects to write 
    390         :param filename: Where to write the CanSAS 2.0 file 
    391         """ 
    392  
    393         def _h5_string(string): 
    394             """ 
    395             Convert a string to a numpy string in a numpy array. This way it is 
    396             written to the HDF5 file as a fixed length ASCII string and is 
    397             compatible with the Reader read() method. 
    398             """ 
    399             if not isinstance(string, str): 
    400                 raise ValueError("String should be of type str") 
    401  
    402             return np.array([np.string_(string)]) 
    403  
    404         def _h5_float(x): 
    405             if not (isinstance(x, list)): 
    406                 x = [x] 
    407             return np.array(x, dtype=np.float32) 
    408  
    409         valid_data = all([issubclass(d.__class__, (Data1D, Data2D)) for d in dataset]) 
    410         if not valid_data: 
    411             raise ValueError("All entries of dataset must be Data1D or Data2D objects") 
    412  
    413         # Get run name and number from first Data object 
    414         data_info = dataset[0] 
    415         run_number = '' 
    416         run_name = '' 
    417         if len(data_info.run) > 0: 
    418             run_number = data_info.run[0] 
    419             if len(data_info.run_name) > 0: 
    420                 run_name = data_info.run_name[run_number] 
    421  
    422         f = h5py.File(filename, 'w') 
    423         sasentry = f.create_group('sasentry01') 
    424         sasentry['definition'] = _h5_string('NXcanSAS') 
    425         sasentry['run'] = _h5_string(run_number) 
    426         sasentry['run'].attrs['name'] = run_name 
    427         sasentry['title'] = _h5_string(data_info.title) 
    428         sasentry.attrs['canSAS_class'] = 'SASentry' 
    429         sasentry.attrs['version'] = '1.0' 
    430  
    431         i = 1 
    432  
    433         for data_obj in dataset: 
    434             data_entry = sasentry.create_group("sasdata{0:0=2d}".format(i)) 
    435             data_entry.attrs['canSAS_class'] = 'SASdata' 
    436             if isinstance(data_obj, Data1D): 
    437                 self._write_1d_data(data_obj, data_entry) 
    438             elif isinstance(data_obj, Data2D): 
    439                 self._write_2d_data(data_obj, data_entry) 
    440             i += 1 
    441  
    442         data_info = dataset[0] 
    443         sample_entry = sasentry.create_group('sassample') 
    444         sample_entry.attrs['canSAS_class'] = 'SASsample' 
    445         sample_entry['name'] = _h5_string(data_info.sample.name) 
    446         sample_attrs = ['thickness', 'temperature'] 
    447         for key in sample_attrs: 
    448             if getattr(data_info.sample, key) is not None: 
    449                 sample_entry.create_dataset(key, data=np.array([getattr(data_info.sample, key)])) 
    450  
    451         instrument_entry = sasentry.create_group('sasinstrument') 
    452         instrument_entry.attrs['canSAS_class'] = 'SASinstrument' 
    453         instrument_entry['name'] = _h5_string(data_info.instrument) 
    454  
    455         source_entry = instrument_entry.create_group('sassource') 
    456         source_entry.attrs['canSAS_class'] = 'SASsource' 
    457         if data_info.source.radiation is None: 
    458             source_entry['radiation'] = _h5_string('neutron') 
    459         else: 
    460             source_entry['radiation'] = _h5_string(data_info.source.radiation) 
    461  
    462         if len(data_info.collimation) > 0: 
    463             i = 1 
    464             for coll_info in data_info.collimation: 
    465                 collimation_entry = instrument_entry.create_group( 
    466                     'sascollimation{0:0=2d}'.format(i)) 
    467                 collimation_entry.attrs['canSAS_class'] = 'SAScollimation' 
    468                 if coll_info.length is not None: 
    469                     collimation_entry['SDD'] = _h5_float(coll_info.length) 
    470                     collimation_entry['SDD'].attrs['units'] = coll_info.length_unit 
    471                 if coll_info.name is not None: 
    472                     collimation_entry['name'] = _h5_string(coll_info.name) 
    473         else: 
    474             collimation_entry = instrument_entry.create_group('sascollimation01') 
    475  
    476         if len(data_info.detector) > 0: 
    477             i = 1 
    478             for det_info in data_info.detector: 
    479                 detector_entry = instrument_entry.create_group( 
    480                     'sasdetector{0:0=2d}'.format(i)) 
    481                 detector_entry.attrs['canSAS_class'] = 'SASdetector' 
    482                 if det_info.distance is not None: 
    483                     detector_entry['SDD'] = _h5_float(det_info.distance) 
    484                     detector_entry['SDD'].attrs['units'] = det_info.distance_unit 
    485                 if det_info.name is not None: 
    486                     detector_entry['name'] = _h5_string(det_info.name) 
    487                 else: 
    488                     detector_entry['name'] = _h5_string('') 
    489                 i += 1 
    490         else: 
    491             detector_entry = instrument_entry.create_group('sasdetector01') 
    492             detector_entry.attrs['canSAS_class'] = 'SASdetector' 
    493             detector_entry.attrs['name'] = '' 
    494  
    495         # TODO: implement writing SASnote 
    496         note_entry = sasentry.create_group('sasnote{0:0=2d}'.format(i)) 
    497         note_entry.attrs['canSAS_class'] = 'SASnote' 
    498  
    499         f.close() 
    500  
    501     def _write_1d_data(self, data_obj, data_entry): 
    502         """ 
    503         Writes the contents of a Data1D object to a SASdata h5py Group 
    504  
    505         :param data_obj: A Data1D object to write to the file 
    506         :param data_entry: A h5py Group object representing the SASdata 
    507         """ 
    508         data_entry.attrs['signal'] = 'I' 
    509         data_entry.attrs['I_axes'] = 'Q' 
    510         data_entry.attrs['I_uncertainties'] = 'Idev' 
    511         data_entry.attrs['Q_indicies'] = 0 
    512         data_entry.create_dataset('Q', data=data_obj.x) 
    513         data_entry.create_dataset('I', data=data_obj.y) 
    514         data_entry.create_dataset('Idev', data=data_obj.dy) 
    515  
    516     def _write_2d_data(self, data, data_entry): 
    517         """ 
    518         Writes the contents of a Data2D object to a SASdata h5py Group 
    519  
    520         :param data: A Data2D object to write to the file 
    521         :param data_entry: A h5py Group object representing the SASdata 
    522         """ 
    523         data_entry.attrs['signal'] = 'I' 
    524         data_entry.attrs['I_axes'] = 'Q,Q' 
    525         data_entry.attrs['I_uncertainties'] = 'Idev' 
    526         data_entry.attrs['Q_indicies'] = [0,1] 
    527  
    528         # Calculate rows and columns, assuming detector is square 
    529         # Same logic as used in PlotPanel.py _get_bins 
    530         n_cols = int(np.floor(np.sqrt(len(data.qy_data)))) 
    531         n_rows = int(np.floor(len(data.qy_data) / n_cols)) 
    532  
    533         if n_rows * n_cols != len(data.qy_data): 
    534             raise ValueError("Unable to calculate dimensions of data") 
    535  
    536         I = np.reshape(data.data, (n_rows, n_cols)) 
    537         dI = np.reshape(data.err_data, (n_rows, n_cols)) 
    538         qx =  np.reshape(data.qx_data, (n_rows, n_cols)) 
    539         qy = np.reshape(data.qy_data, (n_rows, n_cols)) 
    540         I_entry = data_entry.create_dataset('I', data=I) 
    541         I_entry.attrs['units'] = data.I_unit 
    542         Qx_entry = data_entry.create_dataset('Qx', data=qx) 
    543         Qx_entry.attrs['units'] = data.Q_unit 
    544         Qy_entry = data_entry.create_dataset('Qy', data=qy) 
    545         Qy_entry.attrs['units'] = data.Q_unit 
    546  
    547382 
    548383    def _initialize_new_data_set(self, parent_list = None): 
Note: See TracChangeset for help on using the changeset viewer.