source: sasview/src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py @ c9ecd1b

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalcmagnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since c9ecd1b was c9ecd1b, checked in by krzywon, 7 years ago

Comment NXcanSAS reader and remove unused variable from fitpanel.

  • Property mode set to 100644
File size: 27.8 KB
RevLine 
[68aa210]1"""
2    CanSAS 2D data reader for reading HDF5 formatted CanSAS files.
3"""
4
5import h5py
6import numpy as np
7import re
8import os
9import sys
10
[082239e]11from sas.sascalc.dataloader.data_info import plottable_1D, plottable_2D,\
12    Data1D, Data2D, DataInfo, Process, Aperture, Collimation, \
13    TransmissionSpectrum, Detector
[d72567e]14from sas.sascalc.dataloader.data_info import combine_data_info_with_plottable
15
[68aa210]16
17class Reader():
18    """
[082239e]19    A class for reading in CanSAS v2.0 data files. The existing iteration opens
20    Mantid generated HDF5 formatted files with file extension .h5/.H5. Any
21    number of data sets may be present within the file and any dimensionality
22    of data may be used. Currently 1D and 2D SAS data sets are supported, but
23    future implementations will include 1D and 2D SESANS data.
[d72567e]24
[082239e]25    Any number of SASdata sets may be present in a SASentry and the data within
26    can be either 1D I(Q) or 2D I(Qx, Qy).
[68aa210]27
[5e906207]28    Also supports reading NXcanSAS formatted HDF5 files
29
[68aa210]30    :Dependencies:
[d72567e]31        The CanSAS HDF5 reader requires h5py => v2.5.0 or later.
[68aa210]32    """
33
[082239e]34    # CanSAS version
[68aa210]35    cansas_version = 2.0
[082239e]36    # Logged warnings or messages
[68aa210]37    logging = None
[082239e]38    # List of errors for the current data set
[68aa210]39    errors = None
[082239e]40    # Raw file contents to be processed
[68aa210]41    raw_data = None
[082239e]42    # Data info currently being read in
[d72567e]43    current_datainfo = None
[082239e]44    # SASdata set currently being read in
[68aa210]45    current_dataset = None
[082239e]46    # List of plottable1D objects that should be linked to the current_datainfo
[d72567e]47    data1d = None
[082239e]48    # List of plottable2D objects that should be linked to the current_datainfo
[d72567e]49    data2d = None
[082239e]50    # Data type name
[ad52d31]51    type_name = "CanSAS 2.0"
[082239e]52    # Wildcards
[ad52d31]53    type = ["CanSAS 2.0 HDF5 Files (*.h5)|*.h5"]
[082239e]54    # List of allowed extensions
[68aa210]55    ext = ['.h5', '.H5']
[082239e]56    # Flag to bypass extension check
[54544637]57    allow_all = True
[082239e]58    # List of files to return
[68aa210]59    output = None
60
61    def read(self, filename):
62        """
[ad52d31]63        This is the general read method that all SasView data_loaders must have.
[68aa210]64
65        :param filename: A path for an HDF5 formatted CanSAS 2D data file.
[d72567e]66        :return: List of Data1D/2D objects and/or a list of errors.
[68aa210]67        """
[082239e]68        # Reinitialize when loading a new data file to reset all class variables
[d72567e]69        self.reset_class_variables()
[082239e]70        # Check that the file exists
[68aa210]71        if os.path.isfile(filename):
72            basename = os.path.basename(filename)
73            _, extension = os.path.splitext(basename)
74            # If the file type is not allowed, return empty list
75            if extension in self.ext or self.allow_all:
[082239e]76                # Load the data file
[68aa210]77                self.raw_data = h5py.File(filename, 'r')
[082239e]78                # Read in all child elements of top level SASroot
[d72567e]79                self.read_children(self.raw_data, [])
[082239e]80                # Add the last data set to the list of outputs
[68aa210]81                self.add_data_set()
[082239e]82                # Close the data file
[995f4eb]83                self.raw_data.close()
[082239e]84        # Return data set(s)
[68aa210]85        return self.output
86
[d72567e]87    def reset_class_variables(self):
88        """
89        Create the reader object and define initial states for class variables
90        """
91        self.current_datainfo = None
92        self.current_dataset = None
93        self.data1d = []
94        self.data2d = []
95        self.raw_data = None
96        self.errors = set()
97        self.logging = []
98        self.output = []
99        self.parent_class = u''
100        self.detector = Detector()
101        self.collimation = Collimation()
102        self.aperture = Aperture()
103        self.process = Process()
104        self.trans_spectrum = TransmissionSpectrum()
105
106    def read_children(self, data, parent_list):
[68aa210]107        """
[ad52d31]108        A recursive method for stepping through the hierarchical data file.
[68aa210]109
110        :param data: h5py Group object of any kind
111        :param parent: h5py Group parent name
112        """
113
[082239e]114        # Loop through each element of the parent and process accordingly
[68aa210]115        for key in data.keys():
[082239e]116            # Get all information for the current key
[68aa210]117            value = data.get(key)
[d398285]118            if value.attrs.get(u'canSAS_class') is not None:
119                class_name = value.attrs.get(u'canSAS_class')
120            else:
121                class_name = value.attrs.get(u'NX_class')
[68aa210]122            if class_name is not None:
123                class_prog = re.compile(class_name)
124            else:
125                class_prog = re.compile(value.name)
126
127            if isinstance(value, h5py.Group):
[c9ecd1b]128                # Set parent class before recursion
[d72567e]129                self.parent_class = class_name
130                parent_list.append(key)
[082239e]131                # If a new sasentry, store the current data sets and create
132                # a fresh Data1D/2D object
[68aa210]133                if class_prog.match(u'SASentry'):
134                    self.add_data_set(key)
[d72567e]135                elif class_prog.match(u'SASdata'):
136                    self._initialize_new_data_set(parent_list)
[082239e]137                # Recursion step to access data within the group
[d72567e]138                self.read_children(value, parent_list)
[c9ecd1b]139                # Reset parent class when returning from recursive method
140                self.parent_class = class_name
[d72567e]141                self.add_intermediate()
142                parent_list.remove(key)
[68aa210]143
144            elif isinstance(value, h5py.Dataset):
[082239e]145                # If this is a dataset, store the data appropriately
[68aa210]146                data_set = data[key][:]
[7bd6860a]147                unit = self._get_unit(value)
[ac370c5]148
[082239e]149                # I and Q Data
[7bd6860a]150                if key == u'I':
[082239e]151                    if isinstance(self.current_dataset, plottable_2D):
[ac370c5]152                        self.current_dataset.data = data_set
[7bd6860a]153                        self.current_dataset.zaxis("Intensity", unit)
154                    else:
155                        self.current_dataset.y = data_set.flatten()
156                        self.current_dataset.yaxis("Intensity", unit)
157                    continue
158                elif key == u'Idev':
[082239e]159                    if isinstance(self.current_dataset, plottable_2D):
[7bd6860a]160                        self.current_dataset.err_data = data_set.flatten()
161                    else:
162                        self.current_dataset.dy = data_set.flatten()
163                    continue
164                elif key == u'Q':
165                    self.current_dataset.xaxis("Q", unit)
[082239e]166                    if isinstance(self.current_dataset, plottable_2D):
[7bd6860a]167                        self.current_dataset.q = data_set.flatten()
168                    else:
169                        self.current_dataset.x = data_set.flatten()
170                    continue
[bbd0f37]171                elif key == u'Qdev':
172                    self.current_dataset.dx = data_set.flatten()
173                    continue
[082239e]174                elif key == u'dQw':
175                    self.current_dataset.dxw = data_set.flatten()
176                    continue
177                elif key == u'dQl':
178                    self.current_dataset.dxl = data_set.flatten()
179                    continue
[7bd6860a]180                elif key == u'Qy':
181                    self.current_dataset.yaxis("Q_y", unit)
182                    self.current_dataset.qy_data = data_set.flatten()
183                    continue
184                elif key == u'Qydev':
185                    self.current_dataset.dqy_data = data_set.flatten()
186                    continue
187                elif key == u'Qx':
188                    self.current_dataset.xaxis("Q_x", unit)
189                    self.current_dataset.qx_data = data_set.flatten()
190                    continue
191                elif key == u'Qxdev':
192                    self.current_dataset.dqx_data = data_set.flatten()
193                    continue
194                elif key == u'Mask':
195                    self.current_dataset.mask = data_set.flatten()
196                    continue
[082239e]197                # Transmission Spectrum
[c94280c]198                elif (key == u'T'
199                      and self.parent_class == u'SAStransmission_spectrum'):
[082239e]200                    self.trans_spectrum.transmission = data_set.flatten()
201                    continue
[c94280c]202                elif (key == u'Tdev'
203                      and self.parent_class == u'SAStransmission_spectrum'):
[082239e]204                    self.trans_spectrum.transmission_deviation = \
205                        data_set.flatten()
206                    continue
[c94280c]207                elif (key == u'lambda'
208                      and self.parent_class == u'SAStransmission_spectrum'):
[082239e]209                    self.trans_spectrum.wavelength = data_set.flatten()
210                    continue
[68aa210]211
212                for data_point in data_set:
[082239e]213                    # Top Level Meta Data
[68aa210]214                    if key == u'definition':
[d72567e]215                        self.current_datainfo.meta_data['reader'] = data_point
[68aa210]216                    elif key == u'run':
[d72567e]217                        self.current_datainfo.run.append(data_point)
[be88076]218                        try:
219                            run_name = value.attrs['name']
220                            run_dict = {data_point: run_name}
221                            self.current_datainfo.run_name = run_dict
222                        except:
223                            pass
[68aa210]224                    elif key == u'title':
[d72567e]225                        self.current_datainfo.title = data_point
[68aa210]226                    elif key == u'SASnote':
[d72567e]227                        self.current_datainfo.notes.append(data_point)
[68aa210]228
[082239e]229                    # Sample Information
230                    # CanSAS 2.0 format
231                    elif key == u'Title' and self.parent_class == u'SASsample':
[d72567e]232                        self.current_datainfo.sample.name = data_point
[082239e]233                    # NXcanSAS format
234                    elif key == u'name' and self.parent_class == u'SASsample':
[88d85c6]235                        self.current_datainfo.sample.name = data_point
[082239e]236                    # NXcanSAS format
237                    elif key == u'ID' and self.parent_class == u'SASsample':
238                        self.current_datainfo.sample.name = data_point
[c94280c]239                    elif (key == u'thickness'
240                          and self.parent_class == u'SASsample'):
[d72567e]241                        self.current_datainfo.sample.thickness = data_point
[c94280c]242                    elif (key == u'temperature'
243                          and self.parent_class == u'SASsample'):
[d72567e]244                        self.current_datainfo.sample.temperature = data_point
[c94280c]245                    elif (key == u'transmission'
246                          and self.parent_class == u'SASsample'):
[5e906207]247                        self.current_datainfo.sample.transmission = data_point
[c94280c]248                    elif (key == u'x_position'
249                          and self.parent_class == u'SASsample'):
[5e906207]250                        self.current_datainfo.sample.position.x = data_point
[c94280c]251                    elif (key == u'y_position'
252                          and self.parent_class == u'SASsample'):
[5e906207]253                        self.current_datainfo.sample.position.y = data_point
[082239e]254                    elif key == u'pitch' and self.parent_class == u'SASsample':
[5e906207]255                        self.current_datainfo.sample.orientation.x = data_point
[082239e]256                    elif key == u'yaw' and self.parent_class == u'SASsample':
257                        self.current_datainfo.sample.orientation.y = data_point
258                    elif key == u'roll' and self.parent_class == u'SASsample':
[5e906207]259                        self.current_datainfo.sample.orientation.z = data_point
[c94280c]260                    elif (key == u'details'
261                          and self.parent_class == u'SASsample'):
[5e906207]262                        self.current_datainfo.sample.details.append(data_point)
[68aa210]263
[082239e]264                    # Instrumental Information
[c94280c]265                    elif (key == u'name'
266                          and self.parent_class == u'SASinstrument'):
[d72567e]267                        self.current_datainfo.instrument = data_point
268                    elif key == u'name' and self.parent_class == u'SASdetector':
[ad52d31]269                        self.detector.name = data_point
[d72567e]270                    elif key == u'SDD' and self.parent_class == u'SASdetector':
271                        self.detector.distance = float(data_point)
[d398285]272                        self.detector.distance_unit = unit
[c94280c]273                    elif (key == u'slit_length'
274                          and self.parent_class == u'SASdetector'):
[5e906207]275                        self.detector.slit_length = float(data_point)
276                        self.detector.slit_length_unit = unit
[c94280c]277                    elif (key == u'x_position'
278                          and self.parent_class == u'SASdetector'):
[5e906207]279                        self.detector.offset.x = float(data_point)
280                        self.detector.offset_unit = unit
[c94280c]281                    elif (key == u'y_position'
282                          and self.parent_class == u'SASdetector'):
[5e906207]283                        self.detector.offset.y = float(data_point)
284                        self.detector.offset_unit = unit
[c94280c]285                    elif (key == u'pitch'
286                          and self.parent_class == u'SASdetector'):
[5e906207]287                        self.detector.orientation.x = float(data_point)
288                        self.detector.orientation_unit = unit
[082239e]289                    elif key == u'roll' and self.parent_class == u'SASdetector':
[5e906207]290                        self.detector.orientation.z = float(data_point)
291                        self.detector.orientation_unit = unit
[082239e]292                    elif key == u'yaw' and self.parent_class == u'SASdetector':
293                        self.detector.orientation.y = float(data_point)
294                        self.detector.orientation_unit = unit
[c94280c]295                    elif (key == u'beam_center_x'
296                          and self.parent_class == u'SASdetector'):
[5e906207]297                        self.detector.beam_center.x = float(data_point)
298                        self.detector.beam_center_unit = unit
[c94280c]299                    elif (key == u'beam_center_y'
300                          and self.parent_class == u'SASdetector'):
[5e906207]301                        self.detector.beam_center.y = float(data_point)
302                        self.detector.beam_center_unit = unit
[c94280c]303                    elif (key == u'x_pixel_size'
304                          and self.parent_class == u'SASdetector'):
[5e906207]305                        self.detector.pixel_size.x = float(data_point)
306                        self.detector.pixel_size_unit = unit
[c94280c]307                    elif (key == u'y_pixel_size'
308                          and self.parent_class == u'SASdetector'):
[5e906207]309                        self.detector.pixel_size.y = float(data_point)
310                        self.detector.pixel_size_unit = unit
[c94280c]311                    elif (key == u'distance'
312                          and self.parent_class == u'SAScollimation'):
[ad52d31]313                        self.collimation.length = data_point
[d398285]314                        self.collimation.length_unit = unit
[c94280c]315                    elif (key == u'name'
316                          and self.parent_class == u'SAScollimation'):
[ad52d31]317                        self.collimation.name = data_point
[c94280c]318                    elif (key == u'shape'
319                          and self.parent_class == u'SASaperture'):
[082239e]320                        self.aperture.shape = data_point
[c94280c]321                    elif (key == u'x_gap'
322                          and self.parent_class == u'SASaperture'):
[082239e]323                        self.aperture.size.x = data_point
[c94280c]324                    elif (key == u'y_gap'
325                          and self.parent_class == u'SASaperture'):
[082239e]326                        self.aperture.size.y = data_point
327
328                    # Process Information
[c94280c]329                    elif (key == u'Title'
330                          and self.parent_class == u'SASprocess'): # CanSAS 2.0
[68aa210]331                        self.process.name = data_point
[c94280c]332                    elif (key == u'name'
333                          and self.parent_class == u'SASprocess'): # NXcanSAS
[68aa210]334                        self.process.name = data_point
[c94280c]335                    elif (key == u'description'
336                          and self.parent_class == u'SASprocess'):
[68aa210]337                        self.process.description = data_point
[d72567e]338                    elif key == u'date' and self.parent_class == u'SASprocess':
[68aa210]339                        self.process.date = data_point
[082239e]340                    elif key == u'term' and self.parent_class == u'SASprocess':
341                        self.process.term = data_point
[d72567e]342                    elif self.parent_class == u'SASprocess':
[ad52d31]343                        self.process.notes.append(data_point)
344
[082239e]345                    # Source
[c94280c]346                    elif (key == u'wavelength'
347                          and self.parent_class == u'SASdata'):
[d72567e]348                        self.current_datainfo.source.wavelength = data_point
[5e906207]349                        self.current_datainfo.source.wavelength_unit = unit
[c94280c]350                    elif (key == u'incident_wavelength'
351                          and self.parent_class == 'SASsource'):
[5e906207]352                        self.current_datainfo.source.wavelength = data_point
353                        self.current_datainfo.source.wavelength_unit = unit
[c94280c]354                    elif (key == u'wavelength_max'
355                          and self.parent_class == u'SASsource'):
[5e906207]356                        self.current_datainfo.source.wavelength_max = data_point
357                        self.current_datainfo.source.wavelength_max_unit = unit
[c94280c]358                    elif (key == u'wavelength_min'
359                          and self.parent_class == u'SASsource'):
[5e906207]360                        self.current_datainfo.source.wavelength_min = data_point
361                        self.current_datainfo.source.wavelength_min_unit = unit
[c94280c]362                    elif (key == u'incident_wavelength_spread'
363                          and self.parent_class == u'SASsource'):
[082239e]364                        self.current_datainfo.source.wavelength_spread = \
365                            data_point
366                        self.current_datainfo.source.wavelength_spread_unit = \
367                            unit
[c94280c]368                    elif (key == u'beam_size_x'
369                          and self.parent_class == u'SASsource'):
[5e906207]370                        self.current_datainfo.source.beam_size.x = data_point
371                        self.current_datainfo.source.beam_size_unit = unit
[c94280c]372                    elif (key == u'beam_size_y'
373                          and self.parent_class == u'SASsource'):
[5e906207]374                        self.current_datainfo.source.beam_size.y = data_point
375                        self.current_datainfo.source.beam_size_unit = unit
[c94280c]376                    elif (key == u'beam_shape'
377                          and self.parent_class == u'SASsource'):
[5e906207]378                        self.current_datainfo.source.beam_shape = data_point
[c94280c]379                    elif (key == u'radiation'
380                          and self.parent_class == u'SASsource'):
[d72567e]381                        self.current_datainfo.source.radiation = data_point
[c94280c]382                    elif (key == u'transmission'
383                          and self.parent_class == u'SASdata'):
[d72567e]384                        self.current_datainfo.sample.transmission = data_point
[68aa210]385
[082239e]386                    # Everything else goes in meta_data
[68aa210]387                    else:
[082239e]388                        new_key = self._create_unique_key(
389                            self.current_datainfo.meta_data, key)
[d72567e]390                        self.current_datainfo.meta_data[new_key] = data_point
[68aa210]391
392            else:
[082239e]393                # I don't know if this reachable code
[68aa210]394                self.errors.add("ShouldNeverHappenException")
395
[d72567e]396    def add_intermediate(self):
[ad52d31]397        """
[082239e]398        This method stores any intermediate objects within the final data set
399        after fully reading the set.
[ad52d31]400
[082239e]401        :param parent: The NXclass name for the h5py Group object that just
402                       finished being processed
[ad52d31]403        """
404
[d72567e]405        if self.parent_class == u'SASprocess':
406            self.current_datainfo.process.append(self.process)
[ad52d31]407            self.process = Process()
[d72567e]408        elif self.parent_class == u'SASdetector':
409            self.current_datainfo.detector.append(self.detector)
[ad52d31]410            self.detector = Detector()
[d72567e]411        elif self.parent_class == u'SAStransmission_spectrum':
412            self.current_datainfo.trans_spectrum.append(self.trans_spectrum)
[ad52d31]413            self.trans_spectrum = TransmissionSpectrum()
[d72567e]414        elif self.parent_class == u'SAScollimation':
415            self.current_datainfo.collimation.append(self.collimation)
[ad52d31]416            self.collimation = Collimation()
[d72567e]417        elif self.parent_class == u'SASaperture':
[ad52d31]418            self.collimation.aperture.append(self.aperture)
419            self.aperture = Aperture()
[d72567e]420        elif self.parent_class == u'SASdata':
[082239e]421            if isinstance(self.current_dataset, plottable_2D):
[d72567e]422                self.data2d.append(self.current_dataset)
[082239e]423            elif isinstance(self.current_dataset, plottable_1D):
[d72567e]424                self.data1d.append(self.current_dataset)
[68aa210]425
426    def final_data_cleanup(self):
427        """
[082239e]428        Does some final cleanup and formatting on self.current_datainfo and
429        all data1D and data2D objects and then combines the data and info into
430        Data1D and Data2D objects
[68aa210]431        """
432
[082239e]433        # Type cast data arrays to float64
[d72567e]434        if len(self.current_datainfo.trans_spectrum) > 0:
[ad52d31]435            spectrum_list = []
[d72567e]436            for spectrum in self.current_datainfo.trans_spectrum:
[ad52d31]437                spectrum.transmission = np.delete(spectrum.transmission, [0])
438                spectrum.transmission = spectrum.transmission.astype(np.float64)
[082239e]439                spectrum.transmission_deviation = np.delete(
440                    spectrum.transmission_deviation, [0])
441                spectrum.transmission_deviation = \
442                    spectrum.transmission_deviation.astype(np.float64)
[ad52d31]443                spectrum.wavelength = np.delete(spectrum.wavelength, [0])
444                spectrum.wavelength = spectrum.wavelength.astype(np.float64)
[d72567e]445                if len(spectrum.transmission) > 0:
446                    spectrum_list.append(spectrum)
447            self.current_datainfo.trans_spectrum = spectrum_list
[68aa210]448
[082239e]449        # Append errors to dataset and reset class errors
[d72567e]450        self.current_datainfo.errors = self.errors
[68aa210]451        self.errors.clear()
452
[082239e]453        # Combine all plottables with datainfo and append each to output
454        # Type cast data arrays to float64 and find min/max as appropriate
[d72567e]455        for dataset in self.data2d:
456            dataset.data = dataset.data.astype(np.float64)
457            dataset.err_data = dataset.err_data.astype(np.float64)
458            if dataset.qx_data is not None:
459                dataset.xmin = np.min(dataset.qx_data)
460                dataset.xmax = np.max(dataset.qx_data)
461                dataset.qx_data = dataset.qx_data.astype(np.float64)
462            if dataset.dqx_data is not None:
463                dataset.dqx_data = dataset.dqx_data.astype(np.float64)
464            if dataset.qy_data is not None:
465                dataset.ymin = np.min(dataset.qy_data)
466                dataset.ymax = np.max(dataset.qy_data)
467                dataset.qy_data = dataset.qy_data.astype(np.float64)
468            if dataset.dqy_data is not None:
469                dataset.dqy_data = dataset.dqy_data.astype(np.float64)
470            if dataset.q_data is not None:
471                dataset.q_data = dataset.q_data.astype(np.float64)
472            zeros = np.ones(dataset.data.size, dtype=bool)
473            try:
[082239e]474                for i in range(0, dataset.mask.size - 1):
[d72567e]475                    zeros[i] = dataset.mask[i]
476            except:
477                self.errors.add(sys.exc_value)
478            dataset.mask = zeros
[082239e]479            # Calculate the actual Q matrix
[d72567e]480            try:
481                if dataset.q_data.size <= 1:
[54544637]482                    dataset.q_data = np.sqrt(dataset.qx_data
483                                             * dataset.qx_data
484                                             + dataset.qy_data
485                                             * dataset.qy_data)
[d72567e]486            except:
487                dataset.q_data = None
[ac370c5]488
489            if dataset.data.ndim == 2:
490                (n_rows, n_cols) = dataset.data.shape
[479799c]491                dataset.y_bins = dataset.qy_data[0::n_cols]
[ac370c5]492                dataset.x_bins = dataset.qx_data[:n_cols]
493                dataset.data = dataset.data.flatten()
494
[082239e]495            final_dataset = combine_data_info_with_plottable(
496                dataset, self.current_datainfo)
[d72567e]497            self.output.append(final_dataset)
498
499        for dataset in self.data1d:
500            if dataset.x is not None:
501                dataset.x = dataset.x.astype(np.float64)
502                dataset.xmin = np.min(dataset.x)
503                dataset.xmax = np.max(dataset.x)
504            if dataset.y is not None:
505                dataset.y = dataset.y.astype(np.float64)
506                dataset.ymin = np.min(dataset.y)
507                dataset.ymax = np.max(dataset.y)
508            if dataset.dx is not None:
509                dataset.dx = dataset.dx.astype(np.float64)
510            if dataset.dxl is not None:
511                dataset.dxl = dataset.dxl.astype(np.float64)
512            if dataset.dxw is not None:
513                dataset.dxw = dataset.dxw.astype(np.float64)
514            if dataset.dy is not None:
515                dataset.dy = dataset.dy.astype(np.float64)
[082239e]516            final_dataset = combine_data_info_with_plottable(
517                dataset, self.current_datainfo)
[d72567e]518            self.output.append(final_dataset)
519
[68aa210]520    def add_data_set(self, key=""):
521        """
[082239e]522        Adds the current_dataset to the list of outputs after preforming final
523        processing on the data and then calls a private method to generate a
524        new data set.
[68aa210]525
526        :param key: NeXus group name for current tree level
527        """
[d72567e]528
529        if self.current_datainfo and self.current_dataset:
[68aa210]530            self.final_data_cleanup()
[d72567e]531        self.data1d = []
532        self.data2d = []
533        self.current_datainfo = DataInfo()
[68aa210]534
[54ba66e]535
[082239e]536    def _initialize_new_data_set(self, parent_list=None):
[68aa210]537        """
[082239e]538        A private class method to generate a new 1D or 2D data object based on
539        the type of data within the set. Outside methods should call
540        add_data_set() to be sure any existing data is stored properly.
[68aa210]541
[d72567e]542        :param parent_list: List of names of parent elements
[68aa210]543        """
[d72567e]544
545        if parent_list is None:
546            parent_list = []
547        if self._find_intermediate(parent_list, "Qx"):
548            self.current_dataset = plottable_2D()
[68aa210]549        else:
550            x = np.array(0)
551            y = np.array(0)
[d72567e]552            self.current_dataset = plottable_1D(x, y)
553        self.current_datainfo.filename = self.raw_data.filename
[68aa210]554
[d72567e]555    def _find_intermediate(self, parent_list, basename=""):
[ad52d31]556        """
[082239e]557        A private class used to find an entry by either using a direct key or
558        knowing the approximate basename.
[ad52d31]559
[082239e]560        :param parent_list: List of parents nodes in the HDF5 file
[d72567e]561        :param basename: Approximate name of an entry to search for
[ad52d31]562        :return:
563        """
[d72567e]564
565        entry = False
566        key_prog = re.compile(basename)
567        top = self.raw_data
568        for parent in parent_list:
569            top = top.get(parent)
570        for key in top.keys():
[082239e]571            if key_prog.match(key):
[d72567e]572                entry = True
573                break
[ad52d31]574        return entry
575
[68aa210]576    def _create_unique_key(self, dictionary, name, numb=0):
577        """
578        Create a unique key value for any dictionary to prevent overwriting
579        Recurses until a unique key value is found.
580
581        :param dictionary: A dictionary with any number of entries
582        :param name: The index of the item to be added to dictionary
583        :param numb: The number to be appended to the name, starts at 0
[d72567e]584        :return: The new name for the dictionary entry
[68aa210]585        """
586        if dictionary.get(name) is not None:
587            numb += 1
588            name = name.split("_")[0]
589            name += "_{0}".format(numb)
590            name = self._create_unique_key(dictionary, name, numb)
[d398285]591        return name
592
593    def _get_unit(self, value):
594        """
595        Find the unit for a particular value within the h5py dictionary
596
597        :param value: attribute dictionary for a particular value set
[d72567e]598        :return: unit for the value passed to the method
[d398285]599        """
600        unit = value.attrs.get(u'units')
[54544637]601        if unit is None:
[d398285]602            unit = value.attrs.get(u'unit')
[082239e]603        # Convert the unit formats
[d398285]604        if unit == "1/A":
605            unit = "A^{-1}"
606        elif unit == "1/cm":
607            unit = "cm^{-1}"
[54ba66e]608        return unit
Note: See TracBrowser for help on using the repository browser.