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

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

Merge branch 'master' into 4_1_issues

# Conflicts:
# src/sas/sascalc/dataloader/readers/cansas_reader.py

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