Ignore:
Timestamp:
Aug 29, 2018 8:01:23 AM (6 years ago)
Author:
Piotr Rozyczko <rozyczko@…>
Branches:
ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
9463ca2
Parents:
ce30949
git-author:
Piotr Rozyczko <rozyczko@…> (08/29/18 07:59:56)
git-committer:
Piotr Rozyczko <rozyczko@…> (08/29/18 08:01:23)
Message:

cherry picking sascalc changes from master SASVIEW-996
minor unit test fixes

File:
1 edited

Legend:

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

    rc416a17 rb8080e1  
    99import sys 
    1010 
    11 from sas.sascalc.dataloader.data_info import plottable_1D, plottable_2D,\ 
     11from ..data_info import plottable_1D, plottable_2D,\ 
    1212    Data1D, Data2D, DataInfo, Process, Aperture, Collimation, \ 
    1313    TransmissionSpectrum, Detector 
    14 from sas.sascalc.dataloader.data_info import combine_data_info_with_plottable 
    15  
    16  
    17 class Reader(): 
     14from ..data_info import combine_data_info_with_plottable 
     15from ..loader_exceptions import FileContentsException, DefaultReaderException 
     16from ..file_reader_base_class import FileReader, decode 
     17 
     18def h5attr(node, key, default=None): 
     19    return decode(node.attrs.get(key, default)) 
     20 
     21class Reader(FileReader): 
    1822    """ 
    1923    A class for reading in CanSAS v2.0 data files. The existing iteration opens 
     
    2529    Any number of SASdata sets may be present in a SASentry and the data within 
    2630    can be either 1D I(Q) or 2D I(Qx, Qy). 
     31 
    2732    Also supports reading NXcanSAS formatted HDF5 files 
    2833 
     
    3944    # Raw file contents to be processed 
    4045    raw_data = None 
    41     # Data info currently being read in 
    42     current_datainfo = None 
    43     # SASdata set currently being read in 
    44     current_dataset = None 
    4546    # List of plottable1D objects that should be linked to the current_datainfo 
    4647    data1d = None 
     
    5556    # Flag to bypass extension check 
    5657    allow_all = True 
    57     # List of files to return 
    58     output = None 
    59  
    60     def read(self, filename): 
     58 
     59    def get_file_contents(self): 
    6160        """ 
    6261        This is the general read method that all SasView data_loaders must have. 
     
    6665        """ 
    6766        # Reinitialize when loading a new data file to reset all class variables 
    68         self.reset_class_variables() 
     67        self.reset_state() 
     68 
     69        filename = self.f_open.name 
     70        self.f_open.close() # IO handled by h5py 
     71 
    6972        # Check that the file exists 
    7073        if os.path.isfile(filename): 
     
    7477            if extension in self.ext or self.allow_all: 
    7578                # Load the data file 
    76                 self.raw_data = h5py.File(filename, 'r') 
    77                 # Read in all child elements of top level SASroot 
    78                 self.read_children(self.raw_data, []) 
    79                 # Add the last data set to the list of outputs 
    80                 self.add_data_set() 
    81                 # Close the data file 
    82                 self.raw_data.close() 
    83         # Return data set(s) 
    84         return self.output 
    85  
    86     def reset_class_variables(self): 
     79                try: 
     80                    self.raw_data = h5py.File(filename, 'r') 
     81                except Exception as e: 
     82                    if extension not in self.ext: 
     83                        msg = "CanSAS2.0 HDF5 Reader could not load file {}".format(basename + extension) 
     84                        raise DefaultReaderException(msg) 
     85                    raise FileContentsException(e.message) 
     86                try: 
     87                    # Read in all child elements of top level SASroot 
     88                    self.read_children(self.raw_data, []) 
     89                    # Add the last data set to the list of outputs 
     90                    self.add_data_set() 
     91                except Exception as exc: 
     92                    raise FileContentsException(exc.message) 
     93                finally: 
     94                    # Close the data file 
     95                    self.raw_data.close() 
     96 
     97                for dataset in self.output: 
     98                    if isinstance(dataset, Data1D): 
     99                        if dataset.x.size < 5: 
     100                            self.output = [] 
     101                            raise FileContentsException("Fewer than 5 data points found.") 
     102 
     103    def reset_state(self): 
    87104        """ 
    88105        Create the reader object and define initial states for class variables 
    89106        """ 
    90         self.current_datainfo = None 
    91         self.current_dataset = None 
     107        super(Reader, self).reset_state() 
    92108        self.data1d = [] 
    93109        self.data2d = [] 
     
    95111        self.errors = set() 
    96112        self.logging = [] 
    97         self.output = [] 
    98113        self.parent_class = u'' 
    99114        self.detector = Detector() 
     
    115130            # Get all information for the current key 
    116131            value = data.get(key) 
    117             if value.attrs.get(u'canSAS_class') is not None: 
    118                 class_name = value.attrs.get(u'canSAS_class') 
    119             else: 
    120                 class_name = value.attrs.get(u'NX_class') 
     132            class_name = h5attr(value, u'canSAS_class') 
     133            if class_name is None: 
     134                class_name = h5attr(value, u'NX_class') 
    121135            if class_name is not None: 
    122136                class_prog = re.compile(class_name) 
     
    125139 
    126140            if isinstance(value, h5py.Group): 
     141                # Set parent class before recursion 
    127142                self.parent_class = class_name 
    128143                parent_list.append(key) 
     
    135150                # Recursion step to access data within the group 
    136151                self.read_children(value, parent_list) 
     152                # Reset parent class when returning from recursive method 
     153                self.parent_class = class_name 
    137154                self.add_intermediate() 
    138155                parent_list.remove(key) 
     
    165182                        self.current_dataset.x = data_set.flatten() 
    166183                    continue 
     184                elif key == u'Qdev': 
     185                    self.current_dataset.dx = data_set.flatten() 
     186                    continue 
     187                elif key == u'dQw': 
     188                    self.current_dataset.dxw = data_set.flatten() 
     189                    continue 
     190                elif key == u'dQl': 
     191                    self.current_dataset.dxl = data_set.flatten() 
     192                    continue 
    167193                elif key == u'Qy': 
    168194                    self.current_dataset.yaxis("Q_y", unit) 
     
    198224 
    199225                for data_point in data_set: 
     226                    if isinstance(data_point, np.ndarray): 
     227                        if data_point.dtype.char == 'S': 
     228                            data_point = decode(bytes(data_point)) 
     229                    else: 
     230                        data_point = decode(data_point) 
    200231                    # Top Level Meta Data 
    201232                    if key == u'definition': 
     
    203234                    elif key == u'run': 
    204235                        self.current_datainfo.run.append(data_point) 
     236                        try: 
     237                            run_name = h5attr(value, 'name') 
     238                            run_dict = {data_point: run_name} 
     239                            self.current_datainfo.run_name = run_dict 
     240                        except Exception: 
     241                            pass 
    205242                    elif key == u'title': 
    206243                        self.current_datainfo.title = data_point 
     
    411448        Data1D and Data2D objects 
    412449        """ 
    413  
    414450        # Type cast data arrays to float64 
    415451        if len(self.current_datainfo.trans_spectrum) > 0: 
     
    435471        # Type cast data arrays to float64 and find min/max as appropriate 
    436472        for dataset in self.data2d: 
    437             dataset.data = dataset.data.astype(np.float64) 
    438             dataset.err_data = dataset.err_data.astype(np.float64) 
    439             if dataset.qx_data is not None: 
    440                 dataset.xmin = np.min(dataset.qx_data) 
    441                 dataset.xmax = np.max(dataset.qx_data) 
    442                 dataset.qx_data = dataset.qx_data.astype(np.float64) 
    443             if dataset.dqx_data is not None: 
    444                 dataset.dqx_data = dataset.dqx_data.astype(np.float64) 
    445             if dataset.qy_data is not None: 
    446                 dataset.ymin = np.min(dataset.qy_data) 
    447                 dataset.ymax = np.max(dataset.qy_data) 
    448                 dataset.qy_data = dataset.qy_data.astype(np.float64) 
    449             if dataset.dqy_data is not None: 
    450                 dataset.dqy_data = dataset.dqy_data.astype(np.float64) 
    451             if dataset.q_data is not None: 
    452                 dataset.q_data = dataset.q_data.astype(np.float64) 
    453473            zeros = np.ones(dataset.data.size, dtype=bool) 
    454474            try: 
     
    473493                dataset.x_bins = dataset.qx_data[:n_cols] 
    474494                dataset.data = dataset.data.flatten() 
    475  
    476             final_dataset = combine_data_info_with_plottable( 
    477                 dataset, self.current_datainfo) 
    478             self.output.append(final_dataset) 
     495            self.current_dataset = dataset 
     496            self.send_to_output() 
    479497 
    480498        for dataset in self.data1d: 
    481             if dataset.x is not None: 
    482                 dataset.x = dataset.x.astype(np.float64) 
    483                 dataset.xmin = np.min(dataset.x) 
    484                 dataset.xmax = np.max(dataset.x) 
    485             if dataset.y is not None: 
    486                 dataset.y = dataset.y.astype(np.float64) 
    487                 dataset.ymin = np.min(dataset.y) 
    488                 dataset.ymax = np.max(dataset.y) 
    489             if dataset.dx is not None: 
    490                 dataset.dx = dataset.dx.astype(np.float64) 
    491             if dataset.dxl is not None: 
    492                 dataset.dxl = dataset.dxl.astype(np.float64) 
    493             if dataset.dxw is not None: 
    494                 dataset.dxw = dataset.dxw.astype(np.float64) 
    495             if dataset.dy is not None: 
    496                 dataset.dy = dataset.dy.astype(np.float64) 
    497             final_dataset = combine_data_info_with_plottable( 
    498                 dataset, self.current_datainfo) 
    499             self.output.append(final_dataset) 
     499            self.current_dataset = dataset 
     500            self.send_to_output() 
    500501 
    501502    def add_data_set(self, key=""): 
     
    579580        :return: unit for the value passed to the method 
    580581        """ 
    581         unit = value.attrs.get(u'units') 
     582        unit = h5attr(value, u'units') 
    582583        if unit is None: 
    583             unit = value.attrs.get(u'unit') 
     584            unit = h5attr(value, u'unit') 
    584585        # Convert the unit formats 
    585586        if unit == "1/A": 
Note: See TracChangeset for help on using the changeset viewer.