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

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 5a8cdbb was 8dec7e7, checked in by lewis, 8 years ago

Raise DefaultReaderException? in NXcanSAS reader and handle correctly

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