Changeset fcba29a in sasview for src/sas/sascalc/dataloader/readers


Ignore:
Timestamp:
Aug 8, 2016 8:17:11 AM (8 years ago)
Author:
lewis
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
98d32be
Parents:
3931ea14 (diff), ab06de7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into file-converter

Location:
src/sas/sascalc/dataloader/readers
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/dataloader/readers/cansas_reader.py

    r8976865 rfcba29a  
    3434from xml.dom.minidom import parseString 
    3535 
     36## TODO: Refactor to load multiple <SASData> as separate Data1D objects 
     37## TODO: Refactor to allow invalid XML, but give a useful warning when loaded 
     38 
    3639_ZERO = 1e-16 
    3740PREPROCESS = "xmlpreprocess" 
     
    133136        return False 
    134137 
    135     def load_file_and_schema(self, xml_file): 
     138    def load_file_and_schema(self, xml_file, schema_path=""): 
    136139        """ 
    137140        Loads the file and associates a schema, if a known schema exists 
     
    149152        # Generic values for the cansas file based on the version 
    150153        cansas_defaults = CANSAS_NS.get(self.cansas_version, "1.0") 
    151         schema_path = "{0}/sas/sascalc/dataloader/readers/schema/{1}".format\ 
     154        if schema_path == "": 
     155            schema_path = "{0}/sas/sascalc/dataloader/readers/schema/{1}".format\ 
    152156                (base, cansas_defaults.get("schema")).replace("\\", "/") 
    153157 
     
    156160        return cansas_defaults 
    157161 
    158     def read(self, xml_file): 
     162    ## TODO: Test loading invalid CanSAS XML files and see if this works 
     163    ## TODO: Once works, try adding a warning that the data is invalid 
     164    def read(self, xml_file, schema_path=""): 
    159165        """ 
    160166        Validate and read in an xml_file file in the canSAS format. 
     
    174180            if extension in self.ext or self.allow_all: 
    175181                # Get the file location of 
    176                 cansas_defaults = self.load_file_and_schema(xml_file) 
     182                cansas_defaults = self.load_file_and_schema(xml_file, schema_path) 
    177183 
    178184                # Try to load the file, but raise an error if unable to. 
     
    225231                except: 
    226232                    # If the file does not match the schema, raise this error 
    227                     raise RuntimeError, "%s cannot be read" % xml_file 
     233                    schema_path = "{0}/sas/sascalc/dataloader/readers/schema/cansas1d_invalid.xsd" 
     234                    invalid_xml = self.find_invalid_xml() 
     235                    invalid_xml = "\n\nThe loaded xml file does not fully meet the CanSAS v1.x specification. SasView " + \ 
     236                                  "loaded as much of the data as possible.\n\n" + invalid_xml 
     237                    self.errors.add(invalid_xml) 
     238                    self.set_schema(schema_path) 
     239                    if self.is_cansas(): 
     240                        output = self.read(xml_file, schema_path) 
     241                    else: 
     242                        raise RuntimeError, "%s cannot be read" % xml_file 
    228243                return output 
    229244        # Return a list of parsed entries that dataloader can manage 
  • src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py

    rd398285 rd72567e  
    99import sys 
    1010 
    11 from sas.sascalc.dataloader.data_info import plottable_1D, plottable_2D, Data1D, Data2D, Sample, Source 
    12 from sas.sascalc.dataloader.data_info import Process, Aperture, Collimation, TransmissionSpectrum, Detector 
     11from sas.sascalc.dataloader.data_info import plottable_1D, plottable_2D, Data1D, Data2D, DataInfo, Process, Aperture 
     12from sas.sascalc.dataloader.data_info import Collimation, TransmissionSpectrum, Detector 
     13from sas.sascalc.dataloader.data_info import combine_data_info_with_plottable 
     14 
    1315 
    1416 
     
    1820    with file extension .h5/.H5. Any number of data sets may be present within the file and any dimensionality of data 
    1921    may be used. Currently 1D and 2D SAS data sets are supported, but future implementations will include 1D and 2D 
    20     SESANS data. This class assumes a single data set for each sasentry. 
     22    SESANS data. 
     23 
     24    Any number of SASdata sets may be present in a SASentry and the data within can be either 1D I(Q) or 2D I(Qx, Qy). 
    2125 
    2226    :Dependencies: 
    23         The CanSAS HDF5 reader requires h5py v2.5.0 or later. 
     27        The CanSAS HDF5 reader requires h5py => v2.5.0 or later. 
    2428    """ 
    2529 
     
    3236    ## Raw file contents to be processed 
    3337    raw_data = None 
    34     ## Data set being modified 
     38    ## Data info currently being read in 
     39    current_datainfo = None 
     40    ## SASdata set currently being read in 
    3541    current_dataset = None 
    36     ## For recursion and saving purposes, remember parent objects 
    37     parent_list = None 
     42    ## List of plottable1D objects that should be linked to the current_datainfo 
     43    data1d = None 
     44    ## List of plottable2D objects that should be linked to the current_datainfo 
     45    data2d = None 
    3846    ## Data type name 
    3947    type_name = "CanSAS 2.0" 
     
    4755    output = None 
    4856 
    49     def __init__(self): 
    50         """ 
    51         Create the reader object and define initial states for class variables 
    52         """ 
    53         self.current_dataset = None 
    54         self.datasets = [] 
    55         self.raw_data = None 
    56         self.errors = set() 
    57         self.logging = [] 
    58         self.parent_list = [] 
    59         self.output = [] 
    60         self.detector = Detector() 
    61         self.collimation = Collimation() 
    62         self.aperture = Aperture() 
    63         self.process = Process() 
    64         self.sample = Sample() 
    65         self.source = Source() 
    66         self.trans_spectrum  = TransmissionSpectrum() 
    67  
    6857    def read(self, filename): 
    6958        """ 
     
    7160 
    7261        :param filename: A path for an HDF5 formatted CanSAS 2D data file. 
    73         :return: List of Data1D/2D objects or a list of errors. 
     62        :return: List of Data1D/2D objects and/or a list of errors. 
    7463        """ 
    7564 
    7665        ## Reinitialize the class when loading a new data file to reset all class variables 
    77         self.__init__() 
     66        self.reset_class_variables() 
    7867        ## Check that the file exists 
    7968        if os.path.isfile(filename): 
     
    8574                self.raw_data = h5py.File(filename, 'r') 
    8675                ## Read in all child elements of top level SASroot 
    87                 self.read_children(self.raw_data) 
     76                self.read_children(self.raw_data, []) 
    8877                ## Add the last data set to the list of outputs 
    8978                self.add_data_set() 
     
    9180        return self.output 
    9281 
    93     def read_children(self, data, parent=u'SASroot'): 
     82    def reset_class_variables(self): 
     83        """ 
     84        Create the reader object and define initial states for class variables 
     85        """ 
     86        self.current_datainfo = None 
     87        self.current_dataset = None 
     88        self.data1d = [] 
     89        self.data2d = [] 
     90        self.raw_data = None 
     91        self.errors = set() 
     92        self.logging = [] 
     93        self.output = [] 
     94        self.parent_class = u'' 
     95        self.detector = Detector() 
     96        self.collimation = Collimation() 
     97        self.aperture = Aperture() 
     98        self.process = Process() 
     99        self.trans_spectrum = TransmissionSpectrum() 
     100 
     101    def read_children(self, data, parent_list): 
    94102        """ 
    95103        A recursive method for stepping through the hierarchical data file. 
     
    97105        :param data: h5py Group object of any kind 
    98106        :param parent: h5py Group parent name 
    99         :return: None 
    100         """ 
    101  
    102         ## Create regex for base sasentry and for parent 
    103         parent_prog = re.compile(parent) 
     107        """ 
    104108 
    105109        ## Loop through each element of the parent and process accordingly 
     
    107111            ## Get all information for the current key 
    108112            value = data.get(key) 
    109             attr_keys = value.attrs.keys() 
    110             attr_values = value.attrs.values() 
    111113            if value.attrs.get(u'canSAS_class') is not None: 
    112114                class_name = value.attrs.get(u'canSAS_class') 
     
    119121 
    120122            if isinstance(value, h5py.Group): 
    121                 ##TODO: Rework this for multiple SASdata objects within a single SASentry to allow for both 1D and 2D 
    122                 ##TODO:     data within the same SASentry - One 1D and one 2D data object for all SASdata sets? 
    123                 ## If this is a new sasentry, store the current data set and create a fresh Data1D/2D object 
     123                self.parent_class = class_name 
     124                parent_list.append(key) 
     125                ## If this is a new sasentry, store the current data sets and create a fresh Data1D/2D object 
    124126                if class_prog.match(u'SASentry'): 
    125127                    self.add_data_set(key) 
     128                elif class_prog.match(u'SASdata'): 
     129                    self._initialize_new_data_set(parent_list) 
    126130                ## Recursion step to access data within the group 
    127                 self.read_children(value, class_name) 
    128                 self.add_intermediate(class_name) 
     131                self.read_children(value, parent_list) 
     132                self.add_intermediate() 
     133                parent_list.remove(key) 
    129134 
    130135            elif isinstance(value, h5py.Dataset): 
     
    136141                    unit = self._get_unit(value) 
    137142                    if key == u'definition': 
    138                         self.current_dataset.meta_data['reader'] = data_point 
     143                        self.current_datainfo.meta_data['reader'] = data_point 
    139144                    elif key == u'run': 
    140                         self.current_dataset.run.append(data_point) 
     145                        self.current_datainfo.run.append(data_point) 
    141146                    elif key == u'title': 
    142                         self.current_dataset.title = data_point 
     147                        self.current_datainfo.title = data_point 
    143148                    elif key == u'SASnote': 
    144                         self.current_dataset.notes.append(data_point) 
     149                        self.current_datainfo.notes.append(data_point) 
    145150 
    146151                    ## I and Q Data 
    147152                    elif key == u'I': 
    148                         if type(self.current_dataset) is Data2D: 
     153                        if type(self.current_dataset) is plottable_2D: 
    149154                            self.current_dataset.data = np.append(self.current_dataset.data, data_point) 
    150155                            self.current_dataset.zaxis("Intensity", unit) 
     
    153158                            self.current_dataset.yaxis("Intensity", unit) 
    154159                    elif key == u'Idev': 
    155                         if type(self.current_dataset) is Data2D: 
     160                        if type(self.current_dataset) is plottable_2D: 
    156161                            self.current_dataset.err_data = np.append(self.current_dataset.err_data, data_point) 
    157162                        else: 
     
    159164                    elif key == u'Q': 
    160165                        self.current_dataset.xaxis("Q", unit) 
    161                         if type(self.current_dataset) is Data2D: 
     166                        if type(self.current_dataset) is plottable_2D: 
    162167                            self.current_dataset.q = np.append(self.current_dataset.q, data_point) 
    163168                        else: 
     
    177182 
    178183                    ## Sample Information 
    179                     elif key == u'Title' and parent == u'SASsample': 
    180                         self.sample.name = data_point 
    181                     elif key == u'thickness' and parent == u'SASsample': 
    182                         self.sample.thickness = data_point 
    183                     elif key == u'temperature' and parent == u'SASsample': 
    184                         self.sample.temperature = data_point 
     184                    elif key == u'Title' and self.parent_class == u'SASsample': 
     185                        self.current_datainfo.sample.name = data_point 
     186                    elif key == u'thickness' and self.parent_class == u'SASsample': 
     187                        self.current_datainfo.sample.thickness = data_point 
     188                    elif key == u'temperature' and self.parent_class == u'SASsample': 
     189                        self.current_datainfo.sample.temperature = data_point 
    185190 
    186191                    ## Instrumental Information 
    187                     elif key == u'name' and parent == u'SASinstrument': 
    188                         self.current_dataset.instrument = data_point 
    189                     elif key == u'name' and parent == u'SASdetector': 
     192                    elif key == u'name' and self.parent_class == u'SASinstrument': 
     193                        self.current_datainfo.instrument = data_point 
     194                    elif key == u'name' and self.parent_class == u'SASdetector': 
    190195                        self.detector.name = data_point 
    191                     elif key == u'SDD' and parent == u'SASdetector': 
    192                         self.detector.distance = data_point 
     196                    elif key == u'SDD' and self.parent_class == u'SASdetector': 
     197                        self.detector.distance = float(data_point) 
    193198                        self.detector.distance_unit = unit 
    194                     elif key == u'SSD' and parent == u'SAScollimation': 
     199                    elif key == u'SSD' and self.parent_class == u'SAScollimation': 
    195200                        self.collimation.length = data_point 
    196201                        self.collimation.length_unit = unit 
    197                     elif key == u'name' and parent == u'SAScollimation': 
     202                    elif key == u'name' and self.parent_class == u'SAScollimation': 
    198203                        self.collimation.name = data_point 
    199204 
    200205                    ## Process Information 
    201                     elif key == u'name' and parent == u'SASprocess': 
     206                    elif key == u'name' and self.parent_class == u'SASprocess': 
    202207                        self.process.name = data_point 
    203                     elif key == u'Title' and parent == u'SASprocess': 
     208                    elif key == u'Title' and self.parent_class == u'SASprocess': 
    204209                        self.process.name = data_point 
    205                     elif key == u'description' and parent == u'SASprocess': 
     210                    elif key == u'description' and self.parent_class == u'SASprocess': 
    206211                        self.process.description = data_point 
    207                     elif key == u'date' and parent == u'SASprocess': 
     212                    elif key == u'date' and self.parent_class == u'SASprocess': 
    208213                        self.process.date = data_point 
    209                     elif parent == u'SASprocess': 
     214                    elif self.parent_class == u'SASprocess': 
    210215                        self.process.notes.append(data_point) 
    211216 
    212217                    ## Transmission Spectrum 
    213                     elif key == u'T' and parent == u'SAStransmission_spectrum': 
     218                    elif key == u'T' and self.parent_class == u'SAStransmission_spectrum': 
    214219                        self.trans_spectrum.transmission.append(data_point) 
    215                     elif key == u'Tdev' and parent == u'SAStransmission_spectrum': 
     220                    elif key == u'Tdev' and self.parent_class == u'SAStransmission_spectrum': 
    216221                        self.trans_spectrum.transmission_deviation.append(data_point) 
    217                     elif key == u'lambda' and parent == u'SAStransmission_spectrum': 
     222                    elif key == u'lambda' and self.parent_class == u'SAStransmission_spectrum': 
    218223                        self.trans_spectrum.wavelength.append(data_point) 
    219224 
    220225                    ## Other Information 
    221                     elif key == u'wavelength' and parent == u'SASdata': 
    222                         self.source.wavelength = data_point 
    223                         self.source.wavelength.unit = unit 
    224                     elif key == u'radiation' and parent == u'SASsource': 
    225                         self.source.radiation = data_point 
    226                     elif key == u'transmission' and parent == u'SASdata': 
    227                         self.sample.transmission = data_point 
     226                    elif key == u'wavelength' and self.parent_class == u'SASdata': 
     227                        self.current_datainfo.source.wavelength = data_point 
     228                        self.current_datainfo.source.wavelength.unit = unit 
     229                    elif key == u'radiation' and self.parent_class == u'SASsource': 
     230                        self.current_datainfo.source.radiation = data_point 
     231                    elif key == u'transmission' and self.parent_class == u'SASdata': 
     232                        self.current_datainfo.sample.transmission = data_point 
    228233 
    229234                    ## Everything else goes in meta_data 
    230235                    else: 
    231                         new_key = self._create_unique_key(self.current_dataset.meta_data, key) 
    232                         self.current_dataset.meta_data[new_key] = data_point 
     236                        new_key = self._create_unique_key(self.current_datainfo.meta_data, key) 
     237                        self.current_datainfo.meta_data[new_key] = data_point 
    233238 
    234239            else: 
     
    236241                self.errors.add("ShouldNeverHappenException") 
    237242 
    238     def add_intermediate(self, parent): 
     243    def add_intermediate(self): 
    239244        """ 
    240245        This method stores any intermediate objects within the final data set after fully reading the set. 
    241246 
    242247        :param parent: The NXclass name for the h5py Group object that just finished being processed 
    243         :return: 
    244         """ 
    245  
    246         if parent == u'SASprocess': 
    247             self.current_dataset.process.append(self.process) 
     248        """ 
     249 
     250        if self.parent_class == u'SASprocess': 
     251            self.current_datainfo.process.append(self.process) 
    248252            self.process = Process() 
    249         elif parent == u'SASdetector': 
    250             self.current_dataset.detector.append(self.detector) 
     253        elif self.parent_class == u'SASdetector': 
     254            self.current_datainfo.detector.append(self.detector) 
    251255            self.detector = Detector() 
    252         elif parent == u'SAStransmission_spectrum': 
    253             self.current_dataset.trans_spectrum.append(self.trans_spectrum) 
     256        elif self.parent_class == u'SAStransmission_spectrum': 
     257            self.current_datainfo.trans_spectrum.append(self.trans_spectrum) 
    254258            self.trans_spectrum = TransmissionSpectrum() 
    255         elif parent == u'SASsource': 
    256             self.current_dataset.source = self.source 
    257             self.source = Source() 
    258         elif parent == u'SASsample': 
    259             self.current_dataset.sample = self.sample 
    260             self.sample = Sample() 
    261         elif parent == u'SAScollimation': 
    262             self.current_dataset.collimation.append(self.collimation) 
     259        elif self.parent_class == u'SAScollimation': 
     260            self.current_datainfo.collimation.append(self.collimation) 
    263261            self.collimation = Collimation() 
    264         elif parent == u'SASaperture': 
     262        elif self.parent_class == u'SASaperture': 
    265263            self.collimation.aperture.append(self.aperture) 
    266264            self.aperture = Aperture() 
     265        elif self.parent_class == u'SASdata': 
     266            if type(self.current_dataset) is plottable_2D: 
     267                self.data2d.append(self.current_dataset) 
     268            elif type(self.current_dataset) is plottable_1D: 
     269                self.data1d.append(self.current_dataset) 
    267270 
    268271    def final_data_cleanup(self): 
    269272        """ 
    270         Does some final cleanup and formatting on self.current_dataset 
    271         """ 
    272  
    273         ## Type cast data arrays to float64 and find min/max as appropriate 
    274         if type(self.current_dataset) is Data2D: 
    275             self.current_dataset.data = np.delete(self.current_dataset.data, [0]) 
    276             self.current_dataset.data = self.current_dataset.data.astype(np.float64) 
    277             self.current_dataset.err_data = np.delete(self.current_dataset.err_data, [0]) 
    278             self.current_dataset.err_data = self.current_dataset.err_data.astype(np.float64) 
    279             self.current_dataset.mask = np.delete(self.current_dataset.mask, [0]) 
    280             if self.current_dataset.qx_data is not None: 
    281                 self.current_dataset.qx_data = np.delete(self.current_dataset.qx_data, [0]) 
    282                 self.current_dataset.xmin = np.min(self.current_dataset.qx_data) 
    283                 self.current_dataset.xmax = np.max(self.current_dataset.qx_data) 
    284                 self.current_dataset.qx_data = self.current_dataset.qx_data.astype(np.float64) 
    285             if self.current_dataset.dqx_data is not None: 
    286                 self.current_dataset.dqx_data = np.delete(self.current_dataset.dqx_data, [0]) 
    287                 self.current_dataset.dqx_data = self.current_dataset.dqx_data.astype(np.float64) 
    288             if self.current_dataset.qy_data is not None: 
    289                 self.current_dataset.qy_data = np.delete(self.current_dataset.qy_data, [0]) 
    290                 self.current_dataset.ymin = np.min(self.current_dataset.qy_data) 
    291                 self.current_dataset.ymax = np.max(self.current_dataset.qy_data) 
    292                 self.current_dataset.qy_data = self.current_dataset.qy_data.astype(np.float64) 
    293             if self.current_dataset.dqy_data is not None: 
    294                 self.current_dataset.dqy_data = np.delete(self.current_dataset.dqy_data, [0]) 
    295                 self.current_dataset.dqy_data = self.current_dataset.dqy_data.astype(np.float64) 
    296             if self.current_dataset.q_data is not None: 
    297                 self.current_dataset.q_data = np.delete(self.current_dataset.q_data, [0]) 
    298                 self.current_dataset.q_data = self.current_dataset.q_data.astype(np.float64) 
    299             zeros = np.ones(self.current_dataset.data.size, dtype=bool) 
    300             try: 
    301                 for i in range (0, self.current_dataset.mask.size - 1): 
    302                     zeros[i] = self.current_dataset.mask[i] 
    303             except: 
    304                 self.errors.add(sys.exc_value) 
    305             self.current_dataset.mask = zeros 
    306  
    307             ## Calculate the actual Q matrix 
    308             try: 
    309                 if self.current_dataset.q_data.size <= 1: 
    310                     self.current_dataset.q_data = np.sqrt(self.current_dataset.qx_data * self.current_dataset.qx_data + 
    311                             self.current_dataset.qy_data * self.current_dataset.qy_data) 
    312             except: 
    313                 self.current_dataset.q_data = None 
    314  
    315         elif type(self.current_dataset) is Data1D: 
    316             if self.current_dataset.x is not None: 
    317                 self.current_dataset.x = np.delete(self.current_dataset.x, [0]) 
    318                 self.current_dataset.x = self.current_dataset.x.astype(np.float64) 
    319                 self.current_dataset.xmin = np.min(self.current_dataset.x) 
    320                 self.current_dataset.xmax = np.max(self.current_dataset.x) 
    321             if self.current_dataset.y is not None: 
    322                 self.current_dataset.y = np.delete(self.current_dataset.y, [0]) 
    323                 self.current_dataset.y = self.current_dataset.y.astype(np.float64) 
    324                 self.current_dataset.ymin = np.min(self.current_dataset.y) 
    325                 self.current_dataset.ymax = np.max(self.current_dataset.y) 
    326             if self.current_dataset.dx is not None: 
    327                 self.current_dataset.dx = np.delete(self.current_dataset.dx, [0]) 
    328                 self.current_dataset.dx = self.current_dataset.dx.astype(np.float64) 
    329             if self.current_dataset.dxl is not None: 
    330                 self.current_dataset.dxl = np.delete(self.current_dataset.dxl, [0]) 
    331                 self.current_dataset.dxl = self.current_dataset.dxl.astype(np.float64) 
    332             if self.current_dataset.dxw is not None: 
    333                 self.current_dataset.dxw = np.delete(self.current_dataset.dxw, [0]) 
    334                 self.current_dataset.dxw = self.current_dataset.dxw.astype(np.float64) 
    335             if self.current_dataset.dy is not None: 
    336                 self.current_dataset.dy = np.delete(self.current_dataset.dy, [0]) 
    337                 self.current_dataset.dy =self.current_dataset.dy.astype(np.float64) 
    338  
    339         if len(self.current_dataset.trans_spectrum) is not 0: 
     273        Does some final cleanup and formatting on self.current_datainfo and all data1D and data2D objects and then 
     274        combines the data and info into Data1D and Data2D objects 
     275        """ 
     276 
     277        ## Type cast data arrays to float64 
     278        if len(self.current_datainfo.trans_spectrum) > 0: 
    340279            spectrum_list = [] 
    341             for spectrum in self.current_dataset.trans_spectrum: 
     280            for spectrum in self.current_datainfo.trans_spectrum: 
    342281                spectrum.transmission = np.delete(spectrum.transmission, [0]) 
    343282                spectrum.transmission = spectrum.transmission.astype(np.float64) 
     
    346285                spectrum.wavelength = np.delete(spectrum.wavelength, [0]) 
    347286                spectrum.wavelength = spectrum.wavelength.astype(np.float64) 
    348                 spectrum_list.append(spectrum) 
    349             self.current_dataset.trans_spectrum = spectrum_list 
    350  
    351         else: 
    352             self.errors.add("ShouldNeverHappenException") 
    353  
    354         ## Append intermediate objects to data 
    355         self.current_dataset.sample = self.sample 
    356         self.current_dataset.source = self.source 
    357         self.current_dataset.collimation.append(self.collimation) 
     287                if len(spectrum.transmission) > 0: 
     288                    spectrum_list.append(spectrum) 
     289            self.current_datainfo.trans_spectrum = spectrum_list 
    358290 
    359291        ## Append errors to dataset and reset class errors 
    360         self.current_dataset.errors = self.errors 
     292        self.current_datainfo.errors = self.errors 
    361293        self.errors.clear() 
     294 
     295        ## Combine all plottables with datainfo and append each to output 
     296        ## Type cast data arrays to float64 and find min/max as appropriate 
     297        for dataset in self.data2d: 
     298            dataset.data = np.delete(dataset.data, [0]) 
     299            dataset.data = dataset.data.astype(np.float64) 
     300            dataset.err_data = np.delete(dataset.err_data, [0]) 
     301            dataset.err_data = dataset.err_data.astype(np.float64) 
     302            dataset.mask = np.delete(dataset.mask, [0]) 
     303            if dataset.qx_data is not None: 
     304                dataset.qx_data = np.delete(dataset.qx_data, [0]) 
     305                dataset.xmin = np.min(dataset.qx_data) 
     306                dataset.xmax = np.max(dataset.qx_data) 
     307                dataset.qx_data = dataset.qx_data.astype(np.float64) 
     308            if dataset.dqx_data is not None: 
     309                dataset.dqx_data = np.delete(dataset.dqx_data, [0]) 
     310                dataset.dqx_data = dataset.dqx_data.astype(np.float64) 
     311            if dataset.qy_data is not None: 
     312                dataset.qy_data = np.delete(dataset.qy_data, [0]) 
     313                dataset.ymin = np.min(dataset.qy_data) 
     314                dataset.ymax = np.max(dataset.qy_data) 
     315                dataset.qy_data = dataset.qy_data.astype(np.float64) 
     316            if dataset.dqy_data is not None: 
     317                dataset.dqy_data = np.delete(dataset.dqy_data, [0]) 
     318                dataset.dqy_data = dataset.dqy_data.astype(np.float64) 
     319            if dataset.q_data is not None: 
     320                dataset.q_data = np.delete(dataset.q_data, [0]) 
     321                dataset.q_data = dataset.q_data.astype(np.float64) 
     322            zeros = np.ones(dataset.data.size, dtype=bool) 
     323            try: 
     324                for i in range (0, dataset.mask.size - 1): 
     325                    zeros[i] = dataset.mask[i] 
     326            except: 
     327                self.errors.add(sys.exc_value) 
     328            dataset.mask = zeros 
     329            ## Calculate the actual Q matrix 
     330            try: 
     331                if dataset.q_data.size <= 1: 
     332                    dataset.q_data = np.sqrt(dataset.qx_data * dataset.qx_data + dataset.qy_data * dataset.qy_data) 
     333            except: 
     334                dataset.q_data = None 
     335            final_dataset = combine_data_info_with_plottable(dataset, self.current_datainfo) 
     336            self.output.append(final_dataset) 
     337 
     338        for dataset in self.data1d: 
     339            if dataset.x is not None: 
     340                dataset.x = np.delete(dataset.x, [0]) 
     341                dataset.x = dataset.x.astype(np.float64) 
     342                dataset.xmin = np.min(dataset.x) 
     343                dataset.xmax = np.max(dataset.x) 
     344            if dataset.y is not None: 
     345                dataset.y = np.delete(dataset.y, [0]) 
     346                dataset.y = dataset.y.astype(np.float64) 
     347                dataset.ymin = np.min(dataset.y) 
     348                dataset.ymax = np.max(dataset.y) 
     349            if dataset.dx is not None: 
     350                dataset.dx = np.delete(dataset.dx, [0]) 
     351                dataset.dx = dataset.dx.astype(np.float64) 
     352            if dataset.dxl is not None: 
     353                dataset.dxl = np.delete(dataset.dxl, [0]) 
     354                dataset.dxl = dataset.dxl.astype(np.float64) 
     355            if dataset.dxw is not None: 
     356                dataset.dxw = np.delete(dataset.dxw, [0]) 
     357                dataset.dxw = dataset.dxw.astype(np.float64) 
     358            if dataset.dy is not None: 
     359                dataset.dy = np.delete(dataset.dy, [0]) 
     360                dataset.dy = dataset.dy.astype(np.float64) 
     361            final_dataset = combine_data_info_with_plottable(dataset, self.current_datainfo) 
     362            self.output.append(final_dataset) 
    362363 
    363364    def add_data_set(self, key=""): 
     
    367368 
    368369        :param key: NeXus group name for current tree level 
    369         :return: None 
    370         """ 
    371         if self.current_dataset is not None: 
     370        """ 
     371 
     372        if self.current_datainfo and self.current_dataset: 
    372373            self.final_data_cleanup() 
    373             self.output.append(self.current_dataset) 
    374         self._initialize_new_data_set(key) 
    375  
    376     def _initialize_new_data_set(self, key=""): 
     374        self.data1d = [] 
     375        self.data2d = [] 
     376        self.current_datainfo = DataInfo() 
     377 
     378    def _initialize_new_data_set(self, parent_list = None): 
    377379        """ 
    378380        A private class method to generate a new 1D or 2D data object based on the type of data within the set. 
    379381        Outside methods should call add_data_set() to be sure any existing data is stored properly. 
    380382 
    381         :param key: NeXus group name for current tree level 
    382         :return: None 
    383         """ 
    384         entry = self._find_intermediate(key, "sasentry*") 
    385         data = entry.get("sasdata") 
    386         if data.get("Qx") is not None: 
    387             self.current_dataset = Data2D() 
     383        :param parent_list: List of names of parent elements 
     384        """ 
     385 
     386        if parent_list is None: 
     387            parent_list = [] 
     388        if self._find_intermediate(parent_list, "Qx"): 
     389            self.current_dataset = plottable_2D() 
    388390        else: 
    389391            x = np.array(0) 
    390392            y = np.array(0) 
    391             self.current_dataset = Data1D(x, y) 
    392         self.current_dataset.filename = self.raw_data.filename 
    393  
    394     def _find_intermediate(self, key="", basename=""): 
     393            self.current_dataset = plottable_1D(x, y) 
     394        self.current_datainfo.filename = self.raw_data.filename 
     395 
     396    def _find_intermediate(self, parent_list, basename=""): 
    395397        """ 
    396398        A private class used to find an entry by either using a direct key or knowing the approximate basename. 
    397399 
    398         :param key: Exact keyname of an entry 
    399         :param basename: Approximate name of an entry 
     400        :param parent_list: List of parents to the current level in the HDF5 file 
     401        :param basename: Approximate name of an entry to search for 
    400402        :return: 
    401403        """ 
    402         entry = [] 
    403         if key is not "": 
    404             entry = self.raw_data.get(key) 
    405         else: 
    406             key_prog = re.compile(basename) 
    407             for key in self.raw_data.keys(): 
    408                 if (key_prog.match(key)): 
    409                     entry = self.raw_data.get(key) 
    410                     break 
     404 
     405        entry = False 
     406        key_prog = re.compile(basename) 
     407        top = self.raw_data 
     408        for parent in parent_list: 
     409            top = top.get(parent) 
     410        for key in top.keys(): 
     411            if (key_prog.match(key)): 
     412                entry = True 
     413                break 
    411414        return entry 
    412415 
     
    419422        :param name: The index of the item to be added to dictionary 
    420423        :param numb: The number to be appended to the name, starts at 0 
     424        :return: The new name for the dictionary entry 
    421425        """ 
    422426        if dictionary.get(name) is not None: 
     
    432436 
    433437        :param value: attribute dictionary for a particular value set 
    434         :return: 
     438        :return: unit for the value passed to the method 
    435439        """ 
    436440        unit = value.attrs.get(u'units') 
    437441        if unit == None: 
    438442            unit = value.attrs.get(u'unit') 
    439  
    440443        ## Convert the unit formats 
    441444        if unit == "1/A": 
     
    443446        elif unit == "1/cm": 
    444447            unit = "cm^{-1}" 
    445  
    446448        return unit 
Note: See TracChangeset for help on using the changeset viewer.