Ignore:
File:
1 edited

Legend:

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

    r109afbd r61f329f0  
    11""" 
    2     NXcanSAS data reader for reading HDF5 formatted CanSAS files. 
     2    CanSAS 2D data reader for reading HDF5 formatted CanSAS files. 
    33""" 
    44 
     
    1212    Data1D, Data2D, DataInfo, Process, Aperture, Collimation, \ 
    1313    TransmissionSpectrum, Detector 
     14from ..data_info import combine_data_info_with_plottable 
    1415from ..loader_exceptions import FileContentsException, DefaultReaderException 
    1516from ..file_reader_base_class import FileReader, decode 
    1617 
    17 try: 
    18   basestring 
    19 except NameError:  # CRUFT: python 2 support 
    20   basestring = str 
    21  
    22  
    2318def h5attr(node, key, default=None): 
    2419    return decode(node.attrs.get(key, default)) 
    2520 
    26  
    2721class Reader(FileReader): 
    2822    """ 
    29     A class for reading in NXcanSAS data files. The current implementation has 
    30     been tested to load data generated by multiple facilities, all of which are 
    31     known to produce NXcanSAS standards compliant data. Any number of data sets 
    32     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 immediately 
    34     extensible to SESANS data. 
    35  
    36     Any number of SASdata groups  may be present in a SASentry and the data 
    37     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 
    3933 
    4034    :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. 
    4236    """ 
    4337 
    4438    # CanSAS version 
    4539    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 
    4650    # Data type name 
    47     type_name = "NXcanSAS" 
     51    type_name = "CanSAS 2.0" 
    4852    # Wildcards 
    49     type = ["NXcanSAS HDF5 Files (*.h5)|*.h5|"] 
     53    type = ["CanSAS 2.0 HDF5 Files (*.h5)|*.h5"] 
    5054    # List of allowed extensions 
    5155    ext = ['.h5', '.H5'] 
     
    7781                except Exception as e: 
    7882                    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) 
    8184                        raise DefaultReaderException(msg) 
    8285                    raise FileContentsException(e.message) 
     
    9295                    self.raw_data.close() 
    9396 
    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.") 
    100102 
    101103    def reset_state(self): 
     
    107109        self.data2d = [] 
    108110        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() 
    113112        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 = [] 
    121113        self.parent_class = u'' 
    122114        self.detector = Detector() 
     
    139131            value = data.get(key) 
    140132            class_name = h5attr(value, u'canSAS_class') 
    141             if isinstance(class_name, (list, tuple, np.ndarray)): 
    142                 class_name = class_name[0] 
    143133            if class_name is None: 
    144134                class_name = h5attr(value, u'NX_class') 
     
    150140            if isinstance(value, h5py.Group): 
    151141                # Set parent class before recursion 
    152                 last_parent_class = self.parent_class 
    153142                self.parent_class = class_name 
    154143                parent_list.append(key) 
     
    158147                    self.add_data_set(key) 
    159148                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) 
    162150                # Recursion step to access data within the group 
    163151                self.read_children(value, parent_list) 
     152                # Reset parent class when returning from recursive method 
     153                self.parent_class = class_name 
    164154                self.add_intermediate() 
    165                 # Reset parent class when returning from recursive method 
    166                 self.parent_class = last_parent_class 
    167155                parent_list.remove(key) 
    168156 
    169157            elif isinstance(value, h5py.Dataset): 
    170158                # If this is a dataset, store the data appropriately 
    171                 data_set = value.value 
     159                data_set = data[key][:] 
    172160                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 
    173224 
    174225                for data_point in data_set: 
     
    180231                    # Top Level Meta Data 
    181232                    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 
    189234                    elif key == u'run': 
     235                        self.current_datainfo.run.append(data_point) 
    190236                        try: 
    191237                            run_name = h5attr(value, 'name') 
    192                             run_dict = {data_set: run_name} 
     238                            run_dict = {data_point: run_name} 
    193239                            self.current_datainfo.run_name = run_dict 
    194240                        except Exception: 
    195241                            pass 
    196                         if isinstance(data_set, basestring): 
    197                             self.current_datainfo.run.append(data_set) 
    198                             break 
    199                         else: 
    200                             self.current_datainfo.run.append(data_point) 
    201                     # Title 
    202242                    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 
    209244                    elif key == u'SASnote': 
    210                         self.current_datainfo.notes.append(data_set) 
    211                         break 
     245                        self.current_datainfo.notes.append(data_point) 
     246 
    212247                    # 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 
    215282                    # Instrumental Information 
    216283                    elif (key == u'name' 
    217284                          and self.parent_class == u'SASinstrument'): 
    218285                        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 
    228346                    # 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 
    231363                    # 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 
    234404                    # 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                         break 
    242                     elif self.parent_class == u'SAStransmission_spectrum': 
    243                         self.process_trans_spectrum(data_set, key) 
    244                         break 
    245405                    else: 
    246406                        new_key = self._create_unique_key( 
     
    250410            else: 
    251411                # 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") 
    505413 
    506414    def add_intermediate(self): 
     
    532440                self.data2d.append(self.current_dataset) 
    533441            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) 
    543443 
    544444    def final_data_cleanup(self): 
     
    552452            spectrum_list = [] 
    553453            for spectrum in self.current_datainfo.trans_spectrum: 
     454                spectrum.transmission = np.delete(spectrum.transmission, [0]) 
    554455                spectrum.transmission = spectrum.transmission.astype(np.float64) 
     456                spectrum.transmission_deviation = np.delete( 
     457                    spectrum.transmission_deviation, [0]) 
    555458                spectrum.transmission_deviation = \ 
    556459                    spectrum.transmission_deviation.astype(np.float64) 
     460                spectrum.wavelength = np.delete(spectrum.wavelength, [0]) 
    557461                spectrum.wavelength = spectrum.wavelength.astype(np.float64) 
    558462                if len(spectrum.transmission) > 0: 
     
    562466        # Append errors to dataset and reset class errors 
    563467        self.current_datainfo.errors = self.errors 
    564         self.errors = [] 
     468        self.errors.clear() 
    565469 
    566470        # Combine all plottables with datainfo and append each to output 
    567471        # Type cast data arrays to float64 and find min/max as appropriate 
    568472        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 
    569480            # Calculate the actual Q matrix 
    570481            try: 
     
    573484                                             * dataset.qx_data 
    574485                                             + dataset.qy_data 
    575                                              * dataset.qy_data).flatten() 
     486                                             * dataset.qy_data) 
    576487            except: 
    577488                dataset.q_data = None 
    578489 
    579490            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] 
    582494                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) 
    591495            self.current_dataset = dataset 
    592496            self.send_to_output() 
     
    607511        if self.current_datainfo and self.current_dataset: 
    608512            self.final_data_cleanup() 
    609         self.data_frames = [] 
    610         self.data_uncertainty_frames = [] 
    611513        self.data1d = [] 
    612514        self.data2d = [] 
    613515        self.current_datainfo = DataInfo() 
    614516 
    615     def _initialize_new_data_set(self, value=None): 
     517 
     518    def _initialize_new_data_set(self, parent_list=None): 
    616519        """ 
    617520        A private class method to generate a new 1D or 2D data object based on 
     
    621524        :param parent_list: List of names of parent elements 
    622525        """ 
    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"): 
    624530            self.current_dataset = plottable_2D() 
    625531        else: 
     
    629535        self.current_datainfo.filename = self.raw_data.filename 
    630536 
    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 
    636544        :return: 
    637545        """ 
    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         i_axes = attrs.get("I_axes", ["Q"]) 
    661         q_indices = attrs.get("Q_indices", [0]) 
    662         i_axes = self.as_list_or_array(i_axes) 
    663         keys = value.keys() 
    664         # Assign attributes to appropriate class variables 
    665         self.q_names = [i_axes[int(v)] for v in self.as_list_or_array(q_indices)] 
    666         self.mask_name = attrs.get("mask") 
    667         self.i_name = signal 
    668         self.i_node = value.get(self.i_name) 
    669         for item in self.q_names: 
    670             if item in keys: 
    671                 q_vals = value.get(item) 
    672                 if q_vals.attrs.get("uncertainties") is not None: 
    673                     self.q_uncertainty_names = q_vals.attrs.get("uncertainties") 
    674                 elif q_vals.attrs.get("uncertainty") is not None: 
    675                     self.q_uncertainty_names = q_vals.attrs.get("uncertainty") 
    676                 if isinstance(self.q_uncertainty_names, basestring): 
    677                     self.q_uncertainty_names = self.q_uncertainty_names.split(",") 
    678                 if q_vals.attrs.get("resolutions") is not None: 
    679                     self.q_resolution_names = q_vals.attrs.get("resolutions") 
    680                 if isinstance(self.q_resolution_names, basestring): 
    681                     self.q_resolution_names = self.q_resolution_names.split(",") 
    682         if self.i_name in keys: 
    683             i_vals = value.get(self.i_name) 
    684             self.i_uncertainties_name = i_vals.attrs.get("uncertainties") 
    685             if self.i_uncertainties_name is None: 
    686                 self.i_uncertainties_name = i_vals.attrs.get("uncertainty") 
    687  
    688     def _is_2d_not_multi_frame(self, value, i_base="", q_base=""): 
    689         """ 
    690         A private class to determine if the data set is 1d or 2d. 
    691  
    692         :param value: Nexus/NXcanSAS data group 
    693         :param basename: Approximate name of an entry to search for 
    694         :return: True if 2D, otherwise false 
    695         """ 
    696         i_basename = i_base if i_base != "" else self.i_name 
    697         i_vals = value.get(i_basename) 
    698         q_basename = q_base if q_base != "" else self.q_names 
    699         q_vals = value.get(q_basename[0]) 
    700         self.multi_frame = (i_vals is not None and q_vals is not None 
    701                             and len(i_vals.shape) != 1 
    702                             and len(q_vals.shape) == 1) 
    703         return (i_vals is not None and len(i_vals.shape) != 1 
    704                 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 
    705557 
    706558    def _create_unique_key(self, dictionary, name, numb=0): 
     
    731583        if unit is None: 
    732584            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}" 
    733590        return unit 
Note: See TracChangeset for help on using the changeset viewer.