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

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

New method to read in dq and di data names.

  • Property mode set to 100644
File size: 26.5 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')
[0d93464]120            elif value.attrs.get(u'NX_class') is not None:
[d398285]121                class_name = value.attrs.get(u'NX_class')
[0d93464]122            else:
123                class_name = key
[68aa210]124            if class_name is not None:
125                class_prog = re.compile(class_name)
126            else:
127                class_prog = re.compile(value.name)
128
129            if isinstance(value, h5py.Group):
[d72567e]130                self.parent_class = class_name
131                parent_list.append(key)
[082239e]132                # If a new sasentry, store the current data sets and create
133                # a fresh Data1D/2D object
[68aa210]134                if class_prog.match(u'SASentry'):
135                    self.add_data_set(key)
[d72567e]136                elif class_prog.match(u'SASdata'):
137                    self._initialize_new_data_set(parent_list)
[9e0dd49]138                    self._find_data_attributes(value)
[082239e]139                # Recursion step to access data within the group
[d72567e]140                self.read_children(value, parent_list)
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
[68aa210]149                for data_point in data_set:
[082239e]150                    # Top Level Meta Data
[68aa210]151                    if key == u'definition':
[d72567e]152                        self.current_datainfo.meta_data['reader'] = data_point
[0d93464]153                    # Run
[68aa210]154                    elif key == u'run':
[d72567e]155                        self.current_datainfo.run.append(data_point)
[be88076]156                        try:
157                            run_name = value.attrs['name']
158                            run_dict = {data_point: run_name}
159                            self.current_datainfo.run_name = run_dict
160                        except:
161                            pass
[0d93464]162                    # Title
[68aa210]163                    elif key == u'title':
[d72567e]164                        self.current_datainfo.title = data_point
[0d93464]165                    # Note
[68aa210]166                    elif key == u'SASnote':
[d72567e]167                        self.current_datainfo.notes.append(data_point)
[082239e]168                    # Sample Information
[0d93464]169                    elif self.parent_class == u'SASsample':
170                        self.process_sample(data_point, key)
[082239e]171                    # Instrumental Information
[c94280c]172                    elif (key == u'name'
173                          and self.parent_class == u'SASinstrument'):
[d72567e]174                        self.current_datainfo.instrument = data_point
[0d93464]175                    # Detector
176                    elif self.parent_class == u'SASdetector':
177                        self.process_detector(data_point, key, unit)
178                    # Collimation
179                    elif self.parent_class == u'SAScollimation':
180                        self.process_collimation(data_point, key, unit)
181                    # Aperture
182                    elif self.parent_class == u'SASaperture':
183                        self.process_aperture(data_point, key)
[082239e]184                    # Process Information
[0d93464]185                    elif self.parent_class == u'SASprocess': # CanSAS 2.0
186                        self.process_process(data_point, key)
[082239e]187                    # Source
[0d93464]188                    elif self.parent_class == u'SASsource':
189                        self.process_source(data_point, key, unit)
[082239e]190                    # Everything else goes in meta_data
[0d93464]191                    elif self.parent_class == u'SASdata':
192                        self.process_data_object(data_set, key, unit)
193                        break
194                    elif self.parent_class == u'SAStransmission_spectrum':
195                        self.process_trans_spectrum(data_set, key)
196                        break
[68aa210]197                    else:
[082239e]198                        new_key = self._create_unique_key(
199                            self.current_datainfo.meta_data, key)
[d72567e]200                        self.current_datainfo.meta_data[new_key] = data_point
[68aa210]201
202            else:
[082239e]203                # I don't know if this reachable code
[68aa210]204                self.errors.add("ShouldNeverHappenException")
205
[0d93464]206    def process_data_object(self, data_set, key, unit):
207        """
208        SASdata processor method
209        :param data_set: data from HDF5 file
210        :param key: canSAS_class attribute
211        :param unit: unit attribute
212        """
213        # FIXME: check attributes of SASdata for Q, dQ, Mask, etc.
214        if key == u'I':
215            if isinstance(self.current_dataset, plottable_2D):
216                self.current_dataset.data = data_set
217                self.current_dataset.zaxis("Intensity", unit)
218            else:
219                self.current_dataset.y = data_set.flatten()
220                self.current_dataset.yaxis("Intensity", unit)
221        elif key == u'Idev':
222            if isinstance(self.current_dataset, plottable_2D):
223                self.current_dataset.err_data = data_set.flatten()
224            else:
225                self.current_dataset.dy = data_set.flatten()
226        elif key == u'Q':
227            self.current_dataset.xaxis("Q", unit)
228            if isinstance(self.current_dataset, plottable_2D):
229                self.current_dataset.q = data_set.flatten()
230            else:
231                self.current_dataset.x = data_set.flatten()
232        elif key == u'Qdev':
233            self.current_dataset.dx = data_set.flatten()
234        elif key == u'dQw':
235            self.current_dataset.dxw = data_set.flatten()
236        elif key == u'dQl':
237            self.current_dataset.dxl = data_set.flatten()
238        elif key == u'Qy':
239            self.current_dataset.yaxis("Q_y", unit)
240            self.current_dataset.qy_data = data_set.flatten()
241        elif key == u'Qydev':
242            self.current_dataset.dqy_data = data_set.flatten()
243        elif key == u'Qx':
244            self.current_dataset.xaxis("Q_x", unit)
245            self.current_dataset.qx_data = data_set.flatten()
246        elif key == u'Qxdev':
247            self.current_dataset.dqx_data = data_set.flatten()
248        elif key == u'Mask':
249            self.current_dataset.mask = data_set.flatten()
250        elif key == u'wavelength':
251            self.current_datainfo.source.wavelength = data_set[0]
252            self.current_datainfo.source.wavelength_unit = unit
253
254    def process_trans_spectrum(self, data_set, key):
255        """
256        SAStransmission_spectrum processor
257        :param data_set: data from HDF5 file
258        :param key: canSAS_class attribute
259        """
260        if key == u'T':
261            self.trans_spectrum.transmission = data_set.flatten()
262        elif key == u'Tdev':
263            self.trans_spectrum.transmission_deviation = data_set.flatten()
264        elif key == u'lambda':
265            self.trans_spectrum.wavelength = data_set.flatten()
266
267    def process_sample(self, data_point, key):
268        """
269        SASsample processor
270        :param data_point: Single point from an HDF5 data file
271        :param key: class name data_point was taken from
272        """
273        if key == u'Title':
274            self.current_datainfo.sample.name = data_point
275        elif key == u'name':
276            self.current_datainfo.sample.name = data_point
277        elif key == u'ID':
278            self.current_datainfo.sample.name = data_point
279        elif key == u'thickness':
280            self.current_datainfo.sample.thickness = data_point
281        elif key == u'temperature':
282            self.current_datainfo.sample.temperature = data_point
283        elif key == u'transmission':
284            self.current_datainfo.sample.transmission = data_point
285        elif key == u'x_position':
286            self.current_datainfo.sample.position.x = data_point
287        elif key == u'y_position':
288            self.current_datainfo.sample.position.y = data_point
289        elif key == u'pitch':
290            self.current_datainfo.sample.orientation.x = data_point
291        elif key == u'yaw':
292            self.current_datainfo.sample.orientation.y = data_point
293        elif key == u'roll':
294            self.current_datainfo.sample.orientation.z = data_point
295        elif key == u'details':
296            self.current_datainfo.sample.details.append(data_point)
297
298    def process_detector(self, data_point, key, unit):
299        """
300        SASdetector processor
301        :param data_point: Single point from an HDF5 data file
302        :param key: class name data_point was taken from
303        :param unit: unit attribute from data set
304        """
305        if key == u'name':
306            self.detector.name = data_point
307        elif key == u'SDD':
308            self.detector.distance = float(data_point)
309            self.detector.distance_unit = unit
310        elif key == u'slit_length':
311            self.detector.slit_length = float(data_point)
312            self.detector.slit_length_unit = unit
313        elif key == u'x_position':
314            self.detector.offset.x = float(data_point)
315            self.detector.offset_unit = unit
316        elif key == u'y_position':
317            self.detector.offset.y = float(data_point)
318            self.detector.offset_unit = unit
319        elif key == u'pitch':
320            self.detector.orientation.x = float(data_point)
321            self.detector.orientation_unit = unit
322        elif key == u'roll':
323            self.detector.orientation.z = float(data_point)
324            self.detector.orientation_unit = unit
325        elif key == u'yaw':
326            self.detector.orientation.y = float(data_point)
327            self.detector.orientation_unit = unit
328        elif key == u'beam_center_x':
329            self.detector.beam_center.x = float(data_point)
330            self.detector.beam_center_unit = unit
331        elif key == u'beam_center_y':
332            self.detector.beam_center.y = float(data_point)
333            self.detector.beam_center_unit = unit
334        elif key == u'x_pixel_size':
335            self.detector.pixel_size.x = float(data_point)
336            self.detector.pixel_size_unit = unit
337        elif key == u'y_pixel_size':
338            self.detector.pixel_size.y = float(data_point)
339            self.detector.pixel_size_unit = unit
340
341    def process_collimation(self, data_point, key, unit):
342        """
343        SAScollimation processor
344        :param data_point: Single point from an HDF5 data file
345        :param key: class name data_point was taken from
346        :param unit: unit attribute from data set
347        """
348        if key == u'distance':
349            self.collimation.length = data_point
350            self.collimation.length_unit = unit
351        elif key == u'name':
352            self.collimation.name = data_point
353
354    def process_aperture(self, data_point, key):
355        """
356        SASaperture processor
357        :param data_point: Single point from an HDF5 data file
358        :param key: class name data_point was taken from
359        """
360        if key == u'shape':
361            self.aperture.shape = data_point
362        elif key == u'x_gap':
363            self.aperture.size.x = data_point
364        elif key == u'y_gap':
365            self.aperture.size.y = data_point
366
367    def process_source(self, data_point, key, unit):
368        """
369        SASsource processor
370        :param data_point: Single point from an HDF5 data file
371        :param key: class name data_point was taken from
372        :param unit: unit attribute from data set
373        """
374        if key == u'incident_wavelength':
375            self.current_datainfo.source.wavelength = data_point
376            self.current_datainfo.source.wavelength_unit = unit
377        elif key == u'wavelength_max':
378            self.current_datainfo.source.wavelength_max = data_point
379            self.current_datainfo.source.wavelength_max_unit = unit
380        elif key == u'wavelength_min':
381            self.current_datainfo.source.wavelength_min = data_point
382            self.current_datainfo.source.wavelength_min_unit = unit
383        elif key == u'incident_wavelength_spread':
384            self.current_datainfo.source.wavelength_spread = data_point
385            self.current_datainfo.source.wavelength_spread_unit = unit
386        elif key == u'beam_size_x':
387            self.current_datainfo.source.beam_size.x = data_point
388            self.current_datainfo.source.beam_size_unit = unit
389        elif key == u'beam_size_y':
390            self.current_datainfo.source.beam_size.y = data_point
391            self.current_datainfo.source.beam_size_unit = unit
392        elif key == u'beam_shape':
393            self.current_datainfo.source.beam_shape = data_point
394        elif key == u'radiation':
395            self.current_datainfo.source.radiation = data_point
396
397    def process_process(self, data_point, key):
398        """
399        SASprocess processor
400        :param data_point: Single point from an HDF5 data file
401        :param key: class name data_point was taken from
402        """
403        if key == u'Title':  # CanSAS 2.0
404            self.process.name = data_point
405        elif key == u'name':  # NXcanSAS
406            self.process.name = data_point
407        elif key == u'description':
408            self.process.description = data_point
409        elif key == u'date':
410            self.process.date = data_point
411        elif key == u'term':
412            self.process.term = data_point
413        else:
414            self.process.notes.append(data_point)
415
[d72567e]416    def add_intermediate(self):
[ad52d31]417        """
[082239e]418        This method stores any intermediate objects within the final data set
419        after fully reading the set.
[ad52d31]420
[082239e]421        :param parent: The NXclass name for the h5py Group object that just
422                       finished being processed
[ad52d31]423        """
424
[d72567e]425        if self.parent_class == u'SASprocess':
426            self.current_datainfo.process.append(self.process)
[ad52d31]427            self.process = Process()
[d72567e]428        elif self.parent_class == u'SASdetector':
429            self.current_datainfo.detector.append(self.detector)
[ad52d31]430            self.detector = Detector()
[d72567e]431        elif self.parent_class == u'SAStransmission_spectrum':
432            self.current_datainfo.trans_spectrum.append(self.trans_spectrum)
[ad52d31]433            self.trans_spectrum = TransmissionSpectrum()
[d72567e]434        elif self.parent_class == u'SAScollimation':
435            self.current_datainfo.collimation.append(self.collimation)
[ad52d31]436            self.collimation = Collimation()
[d72567e]437        elif self.parent_class == u'SASaperture':
[ad52d31]438            self.collimation.aperture.append(self.aperture)
439            self.aperture = Aperture()
[d72567e]440        elif self.parent_class == u'SASdata':
[082239e]441            if isinstance(self.current_dataset, plottable_2D):
[d72567e]442                self.data2d.append(self.current_dataset)
[082239e]443            elif isinstance(self.current_dataset, plottable_1D):
[d72567e]444                self.data1d.append(self.current_dataset)
[68aa210]445
446    def final_data_cleanup(self):
447        """
[082239e]448        Does some final cleanup and formatting on self.current_datainfo and
449        all data1D and data2D objects and then combines the data and info into
450        Data1D and Data2D objects
[68aa210]451        """
452
[082239e]453        # Type cast data arrays to float64
[d72567e]454        if len(self.current_datainfo.trans_spectrum) > 0:
[ad52d31]455            spectrum_list = []
[d72567e]456            for spectrum in self.current_datainfo.trans_spectrum:
[ad52d31]457                spectrum.transmission = np.delete(spectrum.transmission, [0])
458                spectrum.transmission = spectrum.transmission.astype(np.float64)
[082239e]459                spectrum.transmission_deviation = np.delete(
460                    spectrum.transmission_deviation, [0])
461                spectrum.transmission_deviation = \
462                    spectrum.transmission_deviation.astype(np.float64)
[ad52d31]463                spectrum.wavelength = np.delete(spectrum.wavelength, [0])
464                spectrum.wavelength = spectrum.wavelength.astype(np.float64)
[d72567e]465                if len(spectrum.transmission) > 0:
466                    spectrum_list.append(spectrum)
467            self.current_datainfo.trans_spectrum = spectrum_list
[68aa210]468
[082239e]469        # Append errors to dataset and reset class errors
[d72567e]470        self.current_datainfo.errors = self.errors
[68aa210]471        self.errors.clear()
472
[082239e]473        # Combine all plottables with datainfo and append each to output
474        # Type cast data arrays to float64 and find min/max as appropriate
[d72567e]475        for dataset in self.data2d:
476            dataset.data = dataset.data.astype(np.float64)
477            dataset.err_data = dataset.err_data.astype(np.float64)
478            if dataset.qx_data is not None:
479                dataset.xmin = np.min(dataset.qx_data)
480                dataset.xmax = np.max(dataset.qx_data)
481                dataset.qx_data = dataset.qx_data.astype(np.float64)
482            if dataset.dqx_data is not None:
483                dataset.dqx_data = dataset.dqx_data.astype(np.float64)
484            if dataset.qy_data is not None:
485                dataset.ymin = np.min(dataset.qy_data)
486                dataset.ymax = np.max(dataset.qy_data)
487                dataset.qy_data = dataset.qy_data.astype(np.float64)
488            if dataset.dqy_data is not None:
489                dataset.dqy_data = dataset.dqy_data.astype(np.float64)
490            if dataset.q_data is not None:
491                dataset.q_data = dataset.q_data.astype(np.float64)
492            zeros = np.ones(dataset.data.size, dtype=bool)
493            try:
[082239e]494                for i in range(0, dataset.mask.size - 1):
[d72567e]495                    zeros[i] = dataset.mask[i]
496            except:
497                self.errors.add(sys.exc_value)
498            dataset.mask = zeros
[082239e]499            # Calculate the actual Q matrix
[d72567e]500            try:
501                if dataset.q_data.size <= 1:
[54544637]502                    dataset.q_data = np.sqrt(dataset.qx_data
503                                             * dataset.qx_data
504                                             + dataset.qy_data
505                                             * dataset.qy_data)
[d72567e]506            except:
507                dataset.q_data = None
[ac370c5]508
509            if dataset.data.ndim == 2:
510                (n_rows, n_cols) = dataset.data.shape
[479799c]511                dataset.y_bins = dataset.qy_data[0::n_cols]
[ac370c5]512                dataset.x_bins = dataset.qx_data[:n_cols]
513                dataset.data = dataset.data.flatten()
514
[082239e]515            final_dataset = combine_data_info_with_plottable(
516                dataset, self.current_datainfo)
[d72567e]517            self.output.append(final_dataset)
518
519        for dataset in self.data1d:
520            if dataset.x is not None:
521                dataset.x = dataset.x.astype(np.float64)
522                dataset.xmin = np.min(dataset.x)
523                dataset.xmax = np.max(dataset.x)
524            if dataset.y is not None:
525                dataset.y = dataset.y.astype(np.float64)
526                dataset.ymin = np.min(dataset.y)
527                dataset.ymax = np.max(dataset.y)
528            if dataset.dx is not None:
529                dataset.dx = dataset.dx.astype(np.float64)
530            if dataset.dxl is not None:
531                dataset.dxl = dataset.dxl.astype(np.float64)
532            if dataset.dxw is not None:
533                dataset.dxw = dataset.dxw.astype(np.float64)
534            if dataset.dy is not None:
535                dataset.dy = dataset.dy.astype(np.float64)
[082239e]536            final_dataset = combine_data_info_with_plottable(
537                dataset, self.current_datainfo)
[d72567e]538            self.output.append(final_dataset)
539
[68aa210]540    def add_data_set(self, key=""):
541        """
[082239e]542        Adds the current_dataset to the list of outputs after preforming final
543        processing on the data and then calls a private method to generate a
544        new data set.
[68aa210]545
546        :param key: NeXus group name for current tree level
547        """
[d72567e]548
549        if self.current_datainfo and self.current_dataset:
[68aa210]550            self.final_data_cleanup()
[d72567e]551        self.data1d = []
552        self.data2d = []
553        self.current_datainfo = DataInfo()
[68aa210]554
[54ba66e]555
[082239e]556    def _initialize_new_data_set(self, parent_list=None):
[68aa210]557        """
[082239e]558        A private class method to generate a new 1D or 2D data object based on
559        the type of data within the set. Outside methods should call
560        add_data_set() to be sure any existing data is stored properly.
[68aa210]561
[d72567e]562        :param parent_list: List of names of parent elements
[68aa210]563        """
[d72567e]564
565        if parent_list is None:
566            parent_list = []
567        if self._find_intermediate(parent_list, "Qx"):
568            self.current_dataset = plottable_2D()
[68aa210]569        else:
570            x = np.array(0)
571            y = np.array(0)
[d72567e]572            self.current_dataset = plottable_1D(x, y)
573        self.current_datainfo.filename = self.raw_data.filename
[68aa210]574
[9e0dd49]575    def _find_data_attributes(self, value):
576        attrs = value.attrs
577        signal = attrs.get("signal")
578        i_axes = attrs.get("I_axes")
579        q_indices = attrs.get("Q_indices")
580        mask = attrs.get("mask")
581        mask_indices = attrs.get("Mask_indices")
582        keys = value.keys()
583        self.q_name = i_axes[q_indices]
584        self.mask_name = mask[mask_indices]
585        self.i_name = signal
586        if self.q_name in keys:
587            q_vals = value.get(self.q_name)
588            self.q_uncertainties = q_vals.attrs.get("uncertainties")
589            self.q_resolutions = q_vals.attrs.get("resolutions")
590        if self.i_name in keys:
591            i_vals = value.get(self.i_name)
592            self.i_uncertainties = i_vals.attrs.get("uncertainties")
593
[d72567e]594    def _find_intermediate(self, parent_list, basename=""):
[ad52d31]595        """
[082239e]596        A private class used to find an entry by either using a direct key or
597        knowing the approximate basename.
[ad52d31]598
[082239e]599        :param parent_list: List of parents nodes in the HDF5 file
[d72567e]600        :param basename: Approximate name of an entry to search for
[ad52d31]601        :return:
602        """
[d72567e]603
604        entry = False
605        key_prog = re.compile(basename)
606        top = self.raw_data
607        for parent in parent_list:
608            top = top.get(parent)
609        for key in top.keys():
[082239e]610            if key_prog.match(key):
[d72567e]611                entry = True
612                break
[ad52d31]613        return entry
614
[68aa210]615    def _create_unique_key(self, dictionary, name, numb=0):
616        """
617        Create a unique key value for any dictionary to prevent overwriting
618        Recurses until a unique key value is found.
619
620        :param dictionary: A dictionary with any number of entries
621        :param name: The index of the item to be added to dictionary
622        :param numb: The number to be appended to the name, starts at 0
[d72567e]623        :return: The new name for the dictionary entry
[68aa210]624        """
625        if dictionary.get(name) is not None:
626            numb += 1
627            name = name.split("_")[0]
628            name += "_{0}".format(numb)
629            name = self._create_unique_key(dictionary, name, numb)
[d398285]630        return name
631
632    def _get_unit(self, value):
633        """
634        Find the unit for a particular value within the h5py dictionary
635
636        :param value: attribute dictionary for a particular value set
[d72567e]637        :return: unit for the value passed to the method
[d398285]638        """
639        unit = value.attrs.get(u'units')
[54544637]640        if unit is None:
[d398285]641            unit = value.attrs.get(u'unit')
[082239e]642        # Convert the unit formats
[d398285]643        if unit == "1/A":
644            unit = "A^{-1}"
645        elif unit == "1/cm":
646            unit = "cm^{-1}"
[54ba66e]647        return unit
Note: See TracBrowser for help on using the repository browser.