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

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 dcb91cf was dcb91cf, checked in by lewis, 7 years ago

Make suggested changes

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