Changeset 845144e in sasview for src/sas/sascalc


Ignore:
Timestamp:
Oct 17, 2018 4:30:31 PM (6 years ago)
Author:
krzywon
Branches:
master, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, unittest-saveload
Children:
9fb4572
Parents:
b204004 (diff), 67ed543 (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 ticket-1111

Location:
src/sas/sascalc
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/fit/pagestate.py

    r59873e1 r863ac2c  
    640640                if len(value.strip()) == 0: 
    641641                    continue 
    642                 title = value + " [" + repo_time + "]" 
     642                title = (value + " [" + repo_time + "] [SasView v" + 
     643                         SASVIEW_VERSION + "]") 
    643644                title_name = HEADER % title 
    644645            elif name == "data": 
  • src/sas/sascalc/data_util/nxsunit.py

    r574adc7 rb011ecb  
    136136    sld = { '10^-6 Angstrom^-2': 1e-6, 'Angstrom^-2': 1 } 
    137137    Q = { 'invA': 1, 'invAng': 1, 'invAngstroms': 1, '1/A': 1, 
     138          '1/Angstrom': 1, '1/angstrom': 1, 'A^{-1}': 1, 'cm^{-1}': 1e-8, 
    138139          '10^-3 Angstrom^-1': 1e-3, '1/cm': 1e-8, '1/m': 1e-10, 
    139           'nm^-1': 0.1, '1/nm': 0.1, 'n_m^-1': 0.1 } 
     140          'nm^{-1}': 1, 'nm^-1': 0.1, '1/nm': 0.1, 'n_m^-1': 0.1 } 
    140141 
    141142    _caret_optional(sld) 
     
    157158    # units for that particular dimension. 
    158159    # Note: don't have support for dimensionless units. 
    159     unknown = {None:1, '???':1, '': 1, 'a.u.': 1} 
     160    unknown = {None:1, '???':1, '': 1, 'a.u.': 1, 'Counts': 1, 'counts': 1} 
    160161 
    161162    def __init__(self, name): 
  • src/sas/sascalc/dataloader/data_info.py

    r9e6aeaf r4fdcc65  
    954954        _str += "Data:\n" 
    955955        _str += "   Type:         %s\n" % self.__class__.__name__ 
    956         _str += "   X- & Y-axis:  %s\t[%s]\n" % (self._yaxis, self._yunit) 
     956        _str += "   X-axis:       %s\t[%s]\n" % (self._xaxis, self._xunit) 
     957        _str += "   Y-axis:       %s\t[%s]\n" % (self._yaxis, self._yunit) 
    957958        _str += "   Z-axis:       %s\t[%s]\n" % (self._zaxis, self._zunit) 
    958959        _str += "   Length:       %g \n" % (len(self.data)) 
     
    983984                           qx_data=qx_data, qy_data=qy_data, 
    984985                           q_data=q_data, mask=mask) 
     986 
     987        clone._xaxis = self._xaxis 
     988        clone._yaxis = self._yaxis 
     989        clone._zaxis = self._zaxis 
     990        clone._xunit = self._xunit 
     991        clone._yunit = self._yunit 
     992        clone._zunit = self._zunit 
     993        clone.x_bins = self.x_bins 
     994        clone.y_bins = self.y_bins 
    985995 
    986996        clone.title = self.title 
     
    11531163def combine_data_info_with_plottable(data, datainfo): 
    11541164    """ 
    1155     A function that combines the DataInfo data in self.current_datainto with a plottable_1D or 2D data object. 
     1165    A function that combines the DataInfo data in self.current_datainto with a 
     1166    plottable_1D or 2D data object. 
    11561167 
    11571168    :param data: A plottable_1D or plottable_2D data object 
     
    11711182        final_dataset.yaxis(data._yaxis, data._yunit) 
    11721183    elif isinstance(data, plottable_2D): 
    1173         final_dataset = Data2D(data.data, data.err_data, data.qx_data, data.qy_data, data.q_data, 
    1174                                data.mask, data.dqx_data, data.dqy_data) 
     1184        final_dataset = Data2D(data.data, data.err_data, data.qx_data, 
     1185                               data.qy_data, data.q_data, data.mask, 
     1186                               data.dqx_data, data.dqy_data) 
    11751187        final_dataset.xaxis(data._xaxis, data._xunit) 
    11761188        final_dataset.yaxis(data._yaxis, data._yunit) 
    11771189        final_dataset.zaxis(data._zaxis, data._zunit) 
    1178         if len(data.data.shape) == 2: 
    1179             n_rows, n_cols = data.data.shape 
    1180             final_dataset.y_bins = data.qy_data[0::int(n_cols)] 
    1181             final_dataset.x_bins = data.qx_data[:int(n_cols)] 
     1190        final_dataset.y_bins = data.y_bins 
     1191        final_dataset.x_bins = data.x_bins 
    11821192    else: 
    1183         return_string = "Should Never Happen: _combine_data_info_with_plottable input is not a plottable1d or " + \ 
    1184                         "plottable2d data object" 
     1193        return_string = ("Should Never Happen: _combine_data_info_with_plottabl" 
     1194                         "e input is not a plottable1d or plottable2d data " 
     1195                         "object") 
    11851196        return return_string 
    11861197 
  • src/sas/sascalc/dataloader/file_reader_base_class.py

    r4a8d55c rb1ec23d  
    1616from .data_info import Data1D, Data2D, DataInfo, plottable_1D, plottable_2D,\ 
    1717    combine_data_info_with_plottable 
     18from sas.sascalc.data_util.nxsunit import Converter 
    1819 
    1920logger = logging.getLogger(__name__) 
     
    3637                       "load the file was made, but, should it be successful, " 
    3738                       "SasView cannot guarantee the accuracy of the data.") 
     39 
    3840 
    3941class FileReader(object): 
     
    98100                    if len(self.output) > 0: 
    99101                        # Sort the data that's been loaded 
    100                         self.sort_one_d_data() 
    101                         self.sort_two_d_data() 
     102                        self.convert_data_units() 
     103                        self.sort_data() 
    102104        else: 
    103105            msg = "Unable to find file at: {}\n".format(filepath) 
     
    140142        Returns the entire file as a string. 
    141143        """ 
    142         #return self.f_open.read() 
    143144        return decode(self.f_open.read()) 
    144145 
     
    166167        self.output.append(data_obj) 
    167168 
    168     def sort_one_d_data(self): 
     169    def sort_data(self): 
    169170        """ 
    170171        Sort 1D data along the X axis for consistency 
     
    174175                # Normalize the units for 
    175176                data.x_unit = self.format_unit(data.x_unit) 
     177                data._xunit = data.x_unit 
    176178                data.y_unit = self.format_unit(data.y_unit) 
     179                data._yunit = data.y_unit 
    177180                # Sort data by increasing x and remove 1st point 
    178181                ind = np.lexsort((data.y, data.x)) 
     
    203206                    data.ymin = np.min(data.y) 
    204207                    data.ymax = np.max(data.y) 
     208            elif isinstance(data, Data2D): 
     209                # Normalize the units for 
     210                data.Q_unit = self.format_unit(data.Q_unit) 
     211                data.I_unit = self.format_unit(data.I_unit) 
     212                data._xunit = data.Q_unit 
     213                data._yunit = data.Q_unit 
     214                data._zunit = data.I_unit 
     215                data.data = data.data.astype(np.float64) 
     216                data.qx_data = data.qx_data.astype(np.float64) 
     217                data.xmin = np.min(data.qx_data) 
     218                data.xmax = np.max(data.qx_data) 
     219                data.qy_data = data.qy_data.astype(np.float64) 
     220                data.ymin = np.min(data.qy_data) 
     221                data.ymax = np.max(data.qy_data) 
     222                data.q_data = np.sqrt(data.qx_data * data.qx_data 
     223                                         + data.qy_data * data.qy_data) 
     224                if data.err_data is not None: 
     225                    data.err_data = data.err_data.astype(np.float64) 
     226                if data.dqx_data is not None: 
     227                    data.dqx_data = data.dqx_data.astype(np.float64) 
     228                if data.dqy_data is not None: 
     229                    data.dqy_data = data.dqy_data.astype(np.float64) 
     230                if data.mask is not None: 
     231                    data.mask = data.mask.astype(dtype=bool) 
     232 
     233                n_rows, n_cols = data.data.shape 
     234                data.y_bins = data.qy_data[0::int(n_cols)] 
     235                data.x_bins = data.qx_data[:int(n_cols)] 
     236                data.data = data.data.flatten() 
     237                data = self._remove_nans_in_data(data) 
     238                if len(data.data) > 0: 
     239                    data.xmin = np.min(data.qx_data) 
     240                    data.xmax = np.max(data.qx_data) 
     241                    data.ymin = np.min(data.qy_data) 
     242                    data.ymax = np.max(data.qx_data) 
    205243 
    206244    @staticmethod 
     
    242280        return data 
    243281 
    244     def sort_two_d_data(self): 
    245         for dataset in self.output: 
    246             if isinstance(dataset, Data2D): 
    247                 # Normalize the units for 
    248                 dataset.x_unit = self.format_unit(dataset.Q_unit) 
    249                 dataset.y_unit = self.format_unit(dataset.I_unit) 
    250                 dataset.data = dataset.data.astype(np.float64) 
    251                 dataset.qx_data = dataset.qx_data.astype(np.float64) 
    252                 dataset.xmin = np.min(dataset.qx_data) 
    253                 dataset.xmax = np.max(dataset.qx_data) 
    254                 dataset.qy_data = dataset.qy_data.astype(np.float64) 
    255                 dataset.ymin = np.min(dataset.qy_data) 
    256                 dataset.ymax = np.max(dataset.qy_data) 
    257                 dataset.q_data = np.sqrt(dataset.qx_data * dataset.qx_data 
    258                                          + dataset.qy_data * dataset.qy_data) 
    259                 if dataset.err_data is not None: 
    260                     dataset.err_data = dataset.err_data.astype(np.float64) 
    261                 if dataset.dqx_data is not None: 
    262                     dataset.dqx_data = dataset.dqx_data.astype(np.float64) 
    263                 if dataset.dqy_data is not None: 
    264                     dataset.dqy_data = dataset.dqy_data.astype(np.float64) 
    265                 if dataset.mask is not None: 
    266                     dataset.mask = dataset.mask.astype(dtype=bool) 
    267  
    268                 if len(dataset.data.shape) == 2: 
    269                     n_rows, n_cols = dataset.data.shape 
    270                     dataset.y_bins = dataset.qy_data[0::int(n_cols)] 
    271                     dataset.x_bins = dataset.qx_data[:int(n_cols)] 
    272                 dataset.data = dataset.data.flatten() 
    273                 dataset = self._remove_nans_in_data(dataset) 
    274                 if len(dataset.data) > 0: 
    275                     dataset.xmin = np.min(dataset.qx_data) 
    276                     dataset.xmax = np.max(dataset.qx_data) 
    277                     dataset.ymin = np.min(dataset.qy_data) 
    278                     dataset.ymax = np.max(dataset.qx_data) 
     282    @staticmethod 
     283    def set_default_1d_units(data): 
     284        """ 
     285        Set the x and y axes to the default 1D units 
     286        :param data: 1D data set 
     287        :return: 
     288        """ 
     289        data.xaxis(r"\rm{Q}", '1/A') 
     290        data.yaxis(r"\rm{Intensity}", "1/cm") 
     291        return data 
     292 
     293    @staticmethod 
     294    def set_default_2d_units(data): 
     295        """ 
     296        Set the x and y axes to the default 2D units 
     297        :param data: 2D data set 
     298        :return: 
     299        """ 
     300        data.xaxis("\\rm{Q_{x}}", '1/A') 
     301        data.yaxis("\\rm{Q_{y}}", '1/A') 
     302        data.zaxis("\\rm{Intensity}", "1/cm") 
     303        return data 
     304 
     305    def convert_data_units(self, default_q_unit="1/A", default_i_unit="1/cm"): 
     306        """ 
     307        Converts al; data to the sasview default of units of A^{-1} for Q and 
     308        cm^{-1} for I. 
     309        :param default_q_unit: The default Q unit used by Sasview 
     310        :param default_i_unit: The default I unit used by Sasview 
     311        """ 
     312        new_output = [] 
     313        for data in self.output: 
     314            if data.isSesans: 
     315                new_output.append(data) 
     316                continue 
     317            file_x_unit = data._xunit 
     318            data_conv_x = Converter(file_x_unit) 
     319            file_y_unit = data._yunit 
     320            data_conv_y = Converter(file_y_unit) 
     321            if isinstance(data, Data1D): 
     322                try: 
     323                    data.x = data_conv_x(data.x, units=default_q_unit) 
     324                    data._xunit = default_q_unit 
     325                    data.x_unit = default_q_unit 
     326                    if data.dx is not None: 
     327                        data.dx = data_conv_x(data.dx, units=default_q_unit) 
     328                    if data.dxl is not None: 
     329                        data.dxl = data_conv_x(data.dxl, units=default_q_unit) 
     330                    if data.dxw is not None: 
     331                        data.dxw = data_conv_x(data.dxw, units=default_q_unit) 
     332                except KeyError: 
     333                    message = "Unable to convert Q units from {0} to 1/A." 
     334                    message.format(default_q_unit) 
     335                    data.errors.append(message) 
     336                try: 
     337                    data.y = data_conv_y(data.y, units=default_i_unit) 
     338                    data._yunit = default_i_unit 
     339                    data.y_unit = default_i_unit 
     340                    if data.dy is not None: 
     341                        data.dy = data_conv_y(data.dy, units=default_i_unit) 
     342                except KeyError: 
     343                    message = "Unable to convert I units from {0} to 1/cm." 
     344                    message.format(default_q_unit) 
     345                    data.errors.append(message) 
     346            elif isinstance(data, Data2D): 
     347                try: 
     348                    data.qx_data = data_conv_x(data.qx_data, 
     349                                               units=default_q_unit) 
     350                    if data.dqx_data is not None: 
     351                        data.dqx_data = data_conv_x(data.dqx_data, 
     352                                                    units=default_q_unit) 
     353                    data.qy_data = data_conv_y(data.qy_data, 
     354                                               units=default_q_unit) 
     355                    if data.dqy_data is not None: 
     356                        data.dqy_data = data_conv_y(data.dqy_data, 
     357                                                    units=default_q_unit) 
     358                except KeyError: 
     359                    message = "Unable to convert Q units from {0} to 1/A." 
     360                    message.format(default_q_unit) 
     361                    data.errors.append(message) 
     362                try: 
     363                    file_z_unit = data._zunit 
     364                    data_conv_z = Converter(file_z_unit) 
     365                    data.data = data_conv_z(data.data, units=default_i_unit) 
     366                    if data.err_data is not None: 
     367                        data.err_data = data_conv_z(data.err_data, 
     368                                                    units=default_i_unit) 
     369                except KeyError: 
     370                    message = "Unable to convert I units from {0} to 1/cm." 
     371                    message.format(default_q_unit) 
     372                    data.errors.append(message) 
     373            else: 
     374                # TODO: Throw error of some sort... 
     375                pass 
     376            new_output.append(data) 
     377        self.output = new_output 
    279378 
    280379    def format_unit(self, unit=None): 
     
    367466                    self.current_dataset.qy_data)) 
    368467            if has_error_dy: 
    369                 self.current_dataset.err_data = self.current_dataset.err_data[x != 0] 
     468                self.current_dataset.err_data = self.current_dataset.err_data[ 
     469                    x != 0] 
    370470            if has_error_dqx: 
    371                 self.current_dataset.dqx_data = self.current_dataset.dqx_data[x != 0] 
     471                self.current_dataset.dqx_data = self.current_dataset.dqx_data[ 
     472                    x != 0] 
    372473            if has_error_dqy: 
    373                 self.current_dataset.dqy_data = self.current_dataset.dqy_data[x != 0] 
     474                self.current_dataset.dqy_data = self.current_dataset.dqy_data[ 
     475                    x != 0] 
    374476            if has_mask: 
    375477                self.current_dataset.mask = self.current_dataset.mask[x != 0] 
  • src/sas/sascalc/dataloader/loader.py

    r4a8d55c rb1ec23d  
    367367            try: 
    368368                return fn(path, data) 
    369             except Exception: 
    370                 pass  # give other loaders a chance to succeed 
    371         # If we get here it is because all loaders failed 
    372         raise  # reraises last exception 
     369            except Exception as exc: 
     370                msg = "Saving file {} using the {} writer failed.\n".format( 
     371                    path, type(fn).__name__) 
     372                msg += str(exc) 
     373                logger.exception(msg)  # give other loaders a chance to succeed 
    373374 
    374375 
  • src/sas/sascalc/dataloader/readers/abs_reader.py

    rbd5c3b1 r35ac8df  
    225225            raise ValueError("ascii_reader: could not load file") 
    226226 
     227        self.current_dataset = self.set_default_1d_units(self.current_dataset) 
    227228        if data_conv_q is not None: 
    228229            self.current_dataset.xaxis("\\rm{Q}", base_q_unit) 
    229         else: 
    230             self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 
    231230        if data_conv_i is not None: 
    232231            self.current_dataset.yaxis("\\rm{Intensity}", base_i_unit) 
    233         else: 
    234             self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 
    235232 
    236233        # Store loading process information 
  • src/sas/sascalc/dataloader/readers/ascii_reader.py

    r9e6aeaf r3bab401  
    157157 
    158158        self.remove_empty_q_values() 
    159         self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 
    160         self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 
     159        self.current_dataset = self.set_default_1d_units(self.current_dataset) 
    161160 
    162161        # Store loading process information 
  • src/sas/sascalc/dataloader/readers/cansas_reader.py

    r2469df7 r058f6c3  
    812812            node.append(point) 
    813813            self.write_node(point, "Q", datainfo.x[i], 
    814                             {'unit': datainfo.x_unit}) 
     814                            {'unit': datainfo._xunit}) 
    815815            if len(datainfo.y) >= i: 
    816816                self.write_node(point, "I", datainfo.y[i], 
    817                                 {'unit': datainfo.y_unit}) 
     817                                {'unit': datainfo._yunit}) 
    818818            if datainfo.dy is not None and len(datainfo.dy) > i: 
    819819                self.write_node(point, "Idev", datainfo.dy[i], 
    820                                 {'unit': datainfo.y_unit}) 
     820                                {'unit': datainfo._yunit}) 
    821821            if datainfo.dx is not None and len(datainfo.dx) > i: 
    822822                self.write_node(point, "Qdev", datainfo.dx[i], 
    823                                 {'unit': datainfo.x_unit}) 
     823                                {'unit': datainfo._xunit}) 
    824824            if datainfo.dxw is not None and len(datainfo.dxw) > i: 
    825825                self.write_node(point, "dQw", datainfo.dxw[i], 
    826                                 {'unit': datainfo.x_unit}) 
     826                                {'unit': datainfo._xunit}) 
    827827            if datainfo.dxl is not None and len(datainfo.dxl) > i: 
    828828                self.write_node(point, "dQl", datainfo.dxl[i], 
    829                                 {'unit': datainfo.x_unit}) 
     829                                {'unit': datainfo._xunit}) 
    830830        if datainfo.isSesans: 
    831831            sesans_attrib = {'x_axis': datainfo._xaxis, 
  • src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py

    r61f329f0 rb204004  
    1212    Data1D, Data2D, DataInfo, Process, Aperture, Collimation, \ 
    1313    TransmissionSpectrum, Detector 
    14 from ..data_info import combine_data_info_with_plottable 
    1514from ..loader_exceptions import FileContentsException, DefaultReaderException 
    1615from ..file_reader_base_class import FileReader, decode 
    1716 
     17 
    1818def h5attr(node, key, default=None): 
    1919    return decode(node.attrs.get(key, default)) 
     20 
    2021 
    2122class Reader(FileReader): 
     
    3839    # CanSAS version 
    3940    cansas_version = 2.0 
    40     # Logged warnings or messages 
    41     logging = None 
    42     # List of errors for the current data set 
    43     errors = None 
    44     # Raw file contents to be processed 
    45     raw_data = None 
    46     # List of plottable1D objects that should be linked to the current_datainfo 
    47     data1d = None 
    48     # List of plottable2D objects that should be linked to the current_datainfo 
    49     data2d = None 
    5041    # Data type name 
    51     type_name = "CanSAS 2.0" 
     42    type_name = "NXcanSAS" 
    5243    # Wildcards 
    53     type = ["CanSAS 2.0 HDF5 Files (*.h5)|*.h5"] 
     44    type = ["NXcanSAS HDF5 Files (*.h5)|*.h5|"] 
    5445    # List of allowed extensions 
    5546    ext = ['.h5', '.H5'] 
     
    8172                except Exception as e: 
    8273                    if extension not in self.ext: 
    83                         msg = "CanSAS2.0 HDF5 Reader could not load file {}".format(basename + extension) 
     74                        msg = "NXcanSAS Reader could not load file {}".format( 
     75                            basename + extension) 
    8476                        raise DefaultReaderException(msg) 
    8577                    raise FileContentsException(e.message) 
     
    9587                    self.raw_data.close() 
    9688 
    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.") 
     89                for data_set in self.output: 
     90                    if isinstance(data_set, Data1D): 
     91                        if data_set.x.size < 5: 
     92                            exception = FileContentsException( 
     93                                "Fewer than 5 data points found.") 
     94                            data_set.errors.append(exception) 
    10295 
    10396    def reset_state(self): 
     
    111104        self.errors = set() 
    112105        self.logging = [] 
     106        self.q_names = [] 
     107        self.mask_name = u'' 
     108        self.i_name = u'' 
     109        self.i_node = u'' 
     110        self.i_uncertainties_name = u'' 
     111        self.q_uncertainty_names = [] 
     112        self.q_resolution_names = [] 
    113113        self.parent_class = u'' 
    114114        self.detector = Detector() 
     
    131131            value = data.get(key) 
    132132            class_name = h5attr(value, u'canSAS_class') 
     133            if isinstance(class_name, (list, tuple, np.ndarray)): 
     134                class_name = class_name[0] 
    133135            if class_name is None: 
    134136                class_name = h5attr(value, u'NX_class') 
     
    140142            if isinstance(value, h5py.Group): 
    141143                # Set parent class before recursion 
     144                last_parent_class = self.parent_class 
    142145                self.parent_class = class_name 
    143146                parent_list.append(key) 
     
    147150                    self.add_data_set(key) 
    148151                elif class_prog.match(u'SASdata'): 
    149                     self._initialize_new_data_set(parent_list) 
     152                    self._initialize_new_data_set(value) 
     153                    self._find_data_attributes(value) 
    150154                # Recursion step to access data within the group 
    151155                self.read_children(value, parent_list) 
     156                self.add_intermediate() 
    152157                # Reset parent class when returning from recursive method 
    153                 self.parent_class = class_name 
    154                 self.add_intermediate() 
     158                self.parent_class = last_parent_class 
    155159                parent_list.remove(key) 
    156160 
    157161            elif isinstance(value, h5py.Dataset): 
    158162                # If this is a dataset, store the data appropriately 
    159                 data_set = data[key][:] 
     163                data_set = value.value 
    160164                unit = self._get_unit(value) 
    161  
    162                 # I and Q Data 
    163                 if key == u'I': 
    164                     if isinstance(self.current_dataset, plottable_2D): 
    165                         self.current_dataset.data = data_set 
    166                         self.current_dataset.zaxis("Intensity", unit) 
    167                     else: 
    168                         self.current_dataset.y = data_set.flatten() 
    169                         self.current_dataset.yaxis("Intensity", unit) 
    170                     continue 
    171                 elif key == u'Idev': 
    172                     if isinstance(self.current_dataset, plottable_2D): 
    173                         self.current_dataset.err_data = data_set.flatten() 
    174                     else: 
    175                         self.current_dataset.dy = data_set.flatten() 
    176                     continue 
    177                 elif key == u'Q': 
    178                     self.current_dataset.xaxis("Q", unit) 
    179                     if isinstance(self.current_dataset, plottable_2D): 
    180                         self.current_dataset.q = data_set.flatten() 
    181                     else: 
    182                         self.current_dataset.x = data_set.flatten() 
    183                     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 
    193                 elif key == u'Qy': 
    194                     self.current_dataset.yaxis("Q_y", unit) 
    195                     self.current_dataset.qy_data = data_set.flatten() 
    196                     continue 
    197                 elif key == u'Qydev': 
    198                     self.current_dataset.dqy_data = data_set.flatten() 
    199                     continue 
    200                 elif key == u'Qx': 
    201                     self.current_dataset.xaxis("Q_x", unit) 
    202                     self.current_dataset.qx_data = data_set.flatten() 
    203                     continue 
    204                 elif key == u'Qxdev': 
    205                     self.current_dataset.dqx_data = data_set.flatten() 
    206                     continue 
    207                 elif key == u'Mask': 
    208                     self.current_dataset.mask = data_set.flatten() 
    209                     continue 
    210                 # Transmission Spectrum 
    211                 elif (key == u'T' 
    212                       and self.parent_class == u'SAStransmission_spectrum'): 
    213                     self.trans_spectrum.transmission = data_set.flatten() 
    214                     continue 
    215                 elif (key == u'Tdev' 
    216                       and self.parent_class == u'SAStransmission_spectrum'): 
    217                     self.trans_spectrum.transmission_deviation = \ 
    218                         data_set.flatten() 
    219                     continue 
    220                 elif (key == u'lambda' 
    221                       and self.parent_class == u'SAStransmission_spectrum'): 
    222                     self.trans_spectrum.wavelength = data_set.flatten() 
    223                     continue 
    224165 
    225166                for data_point in data_set: 
     
    232173                    if key == u'definition': 
    233174                        self.current_datainfo.meta_data['reader'] = data_point 
     175                    # Run 
    234176                    elif key == u'run': 
    235177                        self.current_datainfo.run.append(data_point) 
     
    240182                        except Exception: 
    241183                            pass 
     184                    # Title 
    242185                    elif key == u'title': 
    243186                        self.current_datainfo.title = data_point 
     187                    # Note 
    244188                    elif key == u'SASnote': 
    245189                        self.current_datainfo.notes.append(data_point) 
    246  
    247190                    # Sample Information 
    248                     # CanSAS 2.0 format 
    249                     elif key == u'Title' and self.parent_class == u'SASsample': 
    250                         self.current_datainfo.sample.name = data_point 
    251                     # NXcanSAS format 
    252                     elif key == u'name' and self.parent_class == u'SASsample': 
    253                         self.current_datainfo.sample.name = data_point 
    254                     # NXcanSAS format 
    255                     elif key == u'ID' and self.parent_class == u'SASsample': 
    256                         self.current_datainfo.sample.name = data_point 
    257                     elif (key == u'thickness' 
    258                           and self.parent_class == u'SASsample'): 
    259                         self.current_datainfo.sample.thickness = data_point 
    260                     elif (key == u'temperature' 
    261                           and self.parent_class == u'SASsample'): 
    262                         self.current_datainfo.sample.temperature = data_point 
    263                     elif (key == u'transmission' 
    264                           and self.parent_class == u'SASsample'): 
    265                         self.current_datainfo.sample.transmission = data_point 
    266                     elif (key == u'x_position' 
    267                           and self.parent_class == u'SASsample'): 
    268                         self.current_datainfo.sample.position.x = data_point 
    269                     elif (key == u'y_position' 
    270                           and self.parent_class == u'SASsample'): 
    271                         self.current_datainfo.sample.position.y = data_point 
    272                     elif key == u'pitch' and self.parent_class == u'SASsample': 
    273                         self.current_datainfo.sample.orientation.x = data_point 
    274                     elif key == u'yaw' and self.parent_class == u'SASsample': 
    275                         self.current_datainfo.sample.orientation.y = data_point 
    276                     elif key == u'roll' and self.parent_class == u'SASsample': 
    277                         self.current_datainfo.sample.orientation.z = data_point 
    278                     elif (key == u'details' 
    279                           and self.parent_class == u'SASsample'): 
    280                         self.current_datainfo.sample.details.append(data_point) 
    281  
     191                    elif self.parent_class == u'SASsample': 
     192                        self.process_sample(data_point, key) 
    282193                    # Instrumental Information 
    283194                    elif (key == u'name' 
    284195                          and self.parent_class == u'SASinstrument'): 
    285196                        self.current_datainfo.instrument = data_point 
    286                     elif key == u'name' and self.parent_class == u'SASdetector': 
    287                         self.detector.name = data_point 
    288                     elif key == u'SDD' and self.parent_class == u'SASdetector': 
    289                         self.detector.distance = float(data_point) 
    290                         self.detector.distance_unit = unit 
    291                     elif (key == u'slit_length' 
    292                           and self.parent_class == u'SASdetector'): 
    293                         self.detector.slit_length = float(data_point) 
    294                         self.detector.slit_length_unit = unit 
    295                     elif (key == u'x_position' 
    296                           and self.parent_class == u'SASdetector'): 
    297                         self.detector.offset.x = float(data_point) 
    298                         self.detector.offset_unit = unit 
    299                     elif (key == u'y_position' 
    300                           and self.parent_class == u'SASdetector'): 
    301                         self.detector.offset.y = float(data_point) 
    302                         self.detector.offset_unit = unit 
    303                     elif (key == u'pitch' 
    304                           and self.parent_class == u'SASdetector'): 
    305                         self.detector.orientation.x = float(data_point) 
    306                         self.detector.orientation_unit = unit 
    307                     elif key == u'roll' and self.parent_class == u'SASdetector': 
    308                         self.detector.orientation.z = float(data_point) 
    309                         self.detector.orientation_unit = unit 
    310                     elif key == u'yaw' and self.parent_class == u'SASdetector': 
    311                         self.detector.orientation.y = float(data_point) 
    312                         self.detector.orientation_unit = unit 
    313                     elif (key == u'beam_center_x' 
    314                           and self.parent_class == u'SASdetector'): 
    315                         self.detector.beam_center.x = float(data_point) 
    316                         self.detector.beam_center_unit = unit 
    317                     elif (key == u'beam_center_y' 
    318                           and self.parent_class == u'SASdetector'): 
    319                         self.detector.beam_center.y = float(data_point) 
    320                         self.detector.beam_center_unit = unit 
    321                     elif (key == u'x_pixel_size' 
    322                           and self.parent_class == u'SASdetector'): 
    323                         self.detector.pixel_size.x = float(data_point) 
    324                         self.detector.pixel_size_unit = unit 
    325                     elif (key == u'y_pixel_size' 
    326                           and self.parent_class == u'SASdetector'): 
    327                         self.detector.pixel_size.y = float(data_point) 
    328                         self.detector.pixel_size_unit = unit 
    329                     elif (key == u'distance' 
    330                           and self.parent_class == u'SAScollimation'): 
    331                         self.collimation.length = data_point 
    332                         self.collimation.length_unit = unit 
    333                     elif (key == u'name' 
    334                           and self.parent_class == u'SAScollimation'): 
    335                         self.collimation.name = data_point 
    336                     elif (key == u'shape' 
    337                           and self.parent_class == u'SASaperture'): 
    338                         self.aperture.shape = data_point 
    339                     elif (key == u'x_gap' 
    340                           and self.parent_class == u'SASaperture'): 
    341                         self.aperture.size.x = data_point 
    342                     elif (key == u'y_gap' 
    343                           and self.parent_class == u'SASaperture'): 
    344                         self.aperture.size.y = data_point 
    345  
     197                    # Detector 
     198                    elif self.parent_class == u'SASdetector': 
     199                        self.process_detector(data_point, key, unit) 
     200                    # Collimation 
     201                    elif self.parent_class == u'SAScollimation': 
     202                        self.process_collimation(data_point, key, unit) 
     203                    # Aperture 
     204                    elif self.parent_class == u'SASaperture': 
     205                        self.process_aperture(data_point, key) 
    346206                    # Process Information 
    347                     elif (key == u'Title' 
    348                           and self.parent_class == u'SASprocess'): # CanSAS 2.0 
    349                         self.process.name = data_point 
    350                     elif (key == u'name' 
    351                           and self.parent_class == u'SASprocess'): # NXcanSAS 
    352                         self.process.name = data_point 
    353                     elif (key == u'description' 
    354                           and self.parent_class == u'SASprocess'): 
    355                         self.process.description = data_point 
    356                     elif key == u'date' and self.parent_class == u'SASprocess': 
    357                         self.process.date = data_point 
    358                     elif key == u'term' and self.parent_class == u'SASprocess': 
    359                         self.process.term = data_point 
    360                     elif self.parent_class == u'SASprocess': 
    361                         self.process.notes.append(data_point) 
    362  
     207                    elif self.parent_class == u'SASprocess': # CanSAS 2.0 
     208                        self.process_process(data_point, key) 
    363209                    # Source 
    364                     elif (key == u'wavelength' 
    365                           and self.parent_class == u'SASdata'): 
    366                         self.current_datainfo.source.wavelength = data_point 
    367                         self.current_datainfo.source.wavelength_unit = unit 
    368                     elif (key == u'incident_wavelength' 
    369                           and self.parent_class == 'SASsource'): 
    370                         self.current_datainfo.source.wavelength = data_point 
    371                         self.current_datainfo.source.wavelength_unit = unit 
    372                     elif (key == u'wavelength_max' 
    373                           and self.parent_class == u'SASsource'): 
    374                         self.current_datainfo.source.wavelength_max = data_point 
    375                         self.current_datainfo.source.wavelength_max_unit = unit 
    376                     elif (key == u'wavelength_min' 
    377                           and self.parent_class == u'SASsource'): 
    378                         self.current_datainfo.source.wavelength_min = data_point 
    379                         self.current_datainfo.source.wavelength_min_unit = unit 
    380                     elif (key == u'incident_wavelength_spread' 
    381                           and self.parent_class == u'SASsource'): 
    382                         self.current_datainfo.source.wavelength_spread = \ 
    383                             data_point 
    384                         self.current_datainfo.source.wavelength_spread_unit = \ 
    385                             unit 
    386                     elif (key == u'beam_size_x' 
    387                           and self.parent_class == u'SASsource'): 
    388                         self.current_datainfo.source.beam_size.x = data_point 
    389                         self.current_datainfo.source.beam_size_unit = unit 
    390                     elif (key == u'beam_size_y' 
    391                           and self.parent_class == u'SASsource'): 
    392                         self.current_datainfo.source.beam_size.y = data_point 
    393                         self.current_datainfo.source.beam_size_unit = unit 
    394                     elif (key == u'beam_shape' 
    395                           and self.parent_class == u'SASsource'): 
    396                         self.current_datainfo.source.beam_shape = data_point 
    397                     elif (key == u'radiation' 
    398                           and self.parent_class == u'SASsource'): 
    399                         self.current_datainfo.source.radiation = data_point 
    400                     elif (key == u'transmission' 
    401                           and self.parent_class == u'SASdata'): 
    402                         self.current_datainfo.sample.transmission = data_point 
    403  
     210                    elif self.parent_class == u'SASsource': 
     211                        self.process_source(data_point, key, unit) 
    404212                    # Everything else goes in meta_data 
     213                    elif self.parent_class == u'SASdata': 
     214                        if isinstance(self.current_dataset, plottable_2D): 
     215                            self.process_2d_data_object(data_set, key, unit) 
     216                        else: 
     217                            self.process_1d_data_object(data_set, key, unit) 
     218 
     219                        break 
     220                    elif self.parent_class == u'SAStransmission_spectrum': 
     221                        self.process_trans_spectrum(data_set, key) 
     222                        break 
    405223                    else: 
    406224                        new_key = self._create_unique_key( 
     
    411229                # I don't know if this reachable code 
    412230                self.errors.add("ShouldNeverHappenException") 
     231 
     232    def process_1d_data_object(self, data_set, key, unit): 
     233        """ 
     234        SASdata processor method for 1d data items 
     235        :param data_set: data from HDF5 file 
     236        :param key: canSAS_class attribute 
     237        :param unit: unit attribute 
     238        """ 
     239        if key == self.i_name: 
     240            self.current_dataset.y = data_set.flatten() 
     241            self.current_dataset.yaxis("Intensity", unit) 
     242        elif key == self.i_uncertainties_name: 
     243            self.current_dataset.dy = data_set.flatten() 
     244        elif key in self.q_names: 
     245            self.current_dataset.xaxis("Q", unit) 
     246            self.current_dataset.x = data_set.flatten() 
     247        elif key in self.q_resolution_names: 
     248            if (len(self.q_resolution_names) > 1 
     249                    and np.where(self.q_resolution_names == key)[0] == 0): 
     250                self.current_dataset.dxw = data_set.flatten() 
     251            elif (len(self.q_resolution_names) > 1 
     252                  and np.where(self.q_resolution_names == key)[0] == 1): 
     253                self.current_dataset.dxl = data_set.flatten() 
     254            else: 
     255                self.current_dataset.dx = data_set.flatten() 
     256        elif key in self.q_uncertainty_names: 
     257            if (len(self.q_uncertainty_names) > 1 
     258                    and np.where(self.q_uncertainty_names == key)[0] == 0): 
     259                self.current_dataset.dxw = data_set.flatten() 
     260            elif (len(self.q_uncertainty_names) > 1 
     261                  and np.where(self.q_uncertainty_names == key)[0] == 1): 
     262                self.current_dataset.dxl = data_set.flatten() 
     263            else: 
     264                self.current_dataset.dx = data_set.flatten() 
     265        elif key == self.mask_name: 
     266            self.current_dataset.mask = data_set.flatten() 
     267        elif key == u'wavelength': 
     268            self.current_datainfo.source.wavelength = data_set[0] 
     269            self.current_datainfo.source.wavelength_unit = unit 
     270 
     271    def process_2d_data_object(self, data_set, key, unit): 
     272        if key == self.i_name: 
     273            self.current_dataset.data = data_set 
     274            self.current_dataset.zaxis("Intensity", unit) 
     275        elif key == self.i_uncertainties_name: 
     276            self.current_dataset.err_data = data_set.flatten() 
     277        elif key in self.q_names: 
     278            self.current_dataset.xaxis("Q_x", unit) 
     279            self.current_dataset.yaxis("Q_y", unit) 
     280            if self.q_names[0] == self.q_names[1]: 
     281                # All q data in a single array 
     282                self.current_dataset.qx_data = data_set[0] 
     283                self.current_dataset.qy_data = data_set[1] 
     284            elif self.q_names.index(key) == 0: 
     285                self.current_dataset.qx_data = data_set 
     286            elif self.q_names.index(key) == 1: 
     287                self.current_dataset.qy_data = data_set 
     288        elif key in self.q_uncertainty_names or key in self.q_resolution_names: 
     289            if ((self.q_uncertainty_names[0] == self.q_uncertainty_names[1]) or 
     290                    (self.q_resolution_names[0] == self.q_resolution_names[1])): 
     291                # All q data in a single array 
     292                self.current_dataset.dqx_data = data_set[0].flatten() 
     293                self.current_dataset.dqy_data = data_set[1].flatten() 
     294            elif (self.q_uncertainty_names.index(key) == 0 or 
     295                  self.q_resolution_names.index(key) == 0): 
     296                self.current_dataset.dqx_data = data_set.flatten() 
     297            elif (self.q_uncertainty_names.index(key) == 1 or 
     298                  self.q_resolution_names.index(key) == 1): 
     299                self.current_dataset.dqy_data = data_set.flatten() 
     300                self.current_dataset.yaxis("Q_y", unit) 
     301        elif key == self.mask_name: 
     302            self.current_dataset.mask = data_set.flatten() 
     303        elif key == u'Qy': 
     304            self.current_dataset.yaxis("Q_y", unit) 
     305            self.current_dataset.qy_data = data_set.flatten() 
     306        elif key == u'Qydev': 
     307            self.current_dataset.dqy_data = data_set.flatten() 
     308        elif key == u'Qx': 
     309            self.current_dataset.xaxis("Q_x", unit) 
     310            self.current_dataset.qx_data = data_set.flatten() 
     311        elif key == u'Qxdev': 
     312            self.current_dataset.dqx_data = data_set.flatten() 
     313 
     314    def process_trans_spectrum(self, data_set, key): 
     315        """ 
     316        SAStransmission_spectrum processor 
     317        :param data_set: data from HDF5 file 
     318        :param key: canSAS_class attribute 
     319        """ 
     320        if key == u'T': 
     321            self.trans_spectrum.transmission = data_set.flatten() 
     322        elif key == u'Tdev': 
     323            self.trans_spectrum.transmission_deviation = data_set.flatten() 
     324        elif key == u'lambda': 
     325            self.trans_spectrum.wavelength = data_set.flatten() 
     326 
     327    def process_sample(self, data_point, key): 
     328        """ 
     329        SASsample processor 
     330        :param data_point: Single point from an HDF5 data file 
     331        :param key: class name data_point was taken from 
     332        """ 
     333        if key == u'Title': 
     334            self.current_datainfo.sample.name = data_point 
     335        elif key == u'name': 
     336            self.current_datainfo.sample.name = data_point 
     337        elif key == u'ID': 
     338            self.current_datainfo.sample.name = data_point 
     339        elif key == u'thickness': 
     340            self.current_datainfo.sample.thickness = data_point 
     341        elif key == u'temperature': 
     342            self.current_datainfo.sample.temperature = data_point 
     343        elif key == u'transmission': 
     344            self.current_datainfo.sample.transmission = data_point 
     345        elif key == u'x_position': 
     346            self.current_datainfo.sample.position.x = data_point 
     347        elif key == u'y_position': 
     348            self.current_datainfo.sample.position.y = data_point 
     349        elif key == u'pitch': 
     350            self.current_datainfo.sample.orientation.x = data_point 
     351        elif key == u'yaw': 
     352            self.current_datainfo.sample.orientation.y = data_point 
     353        elif key == u'roll': 
     354            self.current_datainfo.sample.orientation.z = data_point 
     355        elif key == u'details': 
     356            self.current_datainfo.sample.details.append(data_point) 
     357 
     358    def process_detector(self, data_point, key, unit): 
     359        """ 
     360        SASdetector processor 
     361        :param data_point: Single point from an HDF5 data file 
     362        :param key: class name data_point was taken from 
     363        :param unit: unit attribute from data set 
     364        """ 
     365        if key == u'name': 
     366            self.detector.name = data_point 
     367        elif key == u'SDD': 
     368            self.detector.distance = float(data_point) 
     369            self.detector.distance_unit = unit 
     370        elif key == u'slit_length': 
     371            self.detector.slit_length = float(data_point) 
     372            self.detector.slit_length_unit = unit 
     373        elif key == u'x_position': 
     374            self.detector.offset.x = float(data_point) 
     375            self.detector.offset_unit = unit 
     376        elif key == u'y_position': 
     377            self.detector.offset.y = float(data_point) 
     378            self.detector.offset_unit = unit 
     379        elif key == u'pitch': 
     380            self.detector.orientation.x = float(data_point) 
     381            self.detector.orientation_unit = unit 
     382        elif key == u'roll': 
     383            self.detector.orientation.z = float(data_point) 
     384            self.detector.orientation_unit = unit 
     385        elif key == u'yaw': 
     386            self.detector.orientation.y = float(data_point) 
     387            self.detector.orientation_unit = unit 
     388        elif key == u'beam_center_x': 
     389            self.detector.beam_center.x = float(data_point) 
     390            self.detector.beam_center_unit = unit 
     391        elif key == u'beam_center_y': 
     392            self.detector.beam_center.y = float(data_point) 
     393            self.detector.beam_center_unit = unit 
     394        elif key == u'x_pixel_size': 
     395            self.detector.pixel_size.x = float(data_point) 
     396            self.detector.pixel_size_unit = unit 
     397        elif key == u'y_pixel_size': 
     398            self.detector.pixel_size.y = float(data_point) 
     399            self.detector.pixel_size_unit = unit 
     400 
     401    def process_collimation(self, data_point, key, unit): 
     402        """ 
     403        SAScollimation processor 
     404        :param data_point: Single point from an HDF5 data file 
     405        :param key: class name data_point was taken from 
     406        :param unit: unit attribute from data set 
     407        """ 
     408        if key == u'distance': 
     409            self.collimation.length = data_point 
     410            self.collimation.length_unit = unit 
     411        elif key == u'name': 
     412            self.collimation.name = data_point 
     413 
     414    def process_aperture(self, data_point, key): 
     415        """ 
     416        SASaperture processor 
     417        :param data_point: Single point from an HDF5 data file 
     418        :param key: class name data_point was taken from 
     419        """ 
     420        if key == u'shape': 
     421            self.aperture.shape = data_point 
     422        elif key == u'x_gap': 
     423            self.aperture.size.x = data_point 
     424        elif key == u'y_gap': 
     425            self.aperture.size.y = data_point 
     426 
     427    def process_source(self, data_point, key, unit): 
     428        """ 
     429        SASsource processor 
     430        :param data_point: Single point from an HDF5 data file 
     431        :param key: class name data_point was taken from 
     432        :param unit: unit attribute from data set 
     433        """ 
     434        if key == u'incident_wavelength': 
     435            self.current_datainfo.source.wavelength = data_point 
     436            self.current_datainfo.source.wavelength_unit = unit 
     437        elif key == u'wavelength_max': 
     438            self.current_datainfo.source.wavelength_max = data_point 
     439            self.current_datainfo.source.wavelength_max_unit = unit 
     440        elif key == u'wavelength_min': 
     441            self.current_datainfo.source.wavelength_min = data_point 
     442            self.current_datainfo.source.wavelength_min_unit = unit 
     443        elif key == u'incident_wavelength_spread': 
     444            self.current_datainfo.source.wavelength_spread = data_point 
     445            self.current_datainfo.source.wavelength_spread_unit = unit 
     446        elif key == u'beam_size_x': 
     447            self.current_datainfo.source.beam_size.x = data_point 
     448            self.current_datainfo.source.beam_size_unit = unit 
     449        elif key == u'beam_size_y': 
     450            self.current_datainfo.source.beam_size.y = data_point 
     451            self.current_datainfo.source.beam_size_unit = unit 
     452        elif key == u'beam_shape': 
     453            self.current_datainfo.source.beam_shape = data_point 
     454        elif key == u'radiation': 
     455            self.current_datainfo.source.radiation = data_point 
     456 
     457    def process_process(self, data_point, key): 
     458        """ 
     459        SASprocess processor 
     460        :param data_point: Single point from an HDF5 data file 
     461        :param key: class name data_point was taken from 
     462        """ 
     463        term_match = re.compile(u'^term[0-9]+$') 
     464        if key == u'Title':  # CanSAS 2.0 
     465            self.process.name = data_point 
     466        elif key == u'name':  # NXcanSAS 
     467            self.process.name = data_point 
     468        elif key == u'description': 
     469            self.process.description = data_point 
     470        elif key == u'date': 
     471            self.process.date = data_point 
     472        elif term_match.match(key): 
     473            self.process.term.append(data_point) 
     474        else: 
     475            self.process.notes.append(data_point) 
    413476 
    414477    def add_intermediate(self): 
     
    452515            spectrum_list = [] 
    453516            for spectrum in self.current_datainfo.trans_spectrum: 
    454                 spectrum.transmission = np.delete(spectrum.transmission, [0]) 
    455517                spectrum.transmission = spectrum.transmission.astype(np.float64) 
    456                 spectrum.transmission_deviation = np.delete( 
    457                     spectrum.transmission_deviation, [0]) 
    458518                spectrum.transmission_deviation = \ 
    459519                    spectrum.transmission_deviation.astype(np.float64) 
    460                 spectrum.wavelength = np.delete(spectrum.wavelength, [0]) 
    461520                spectrum.wavelength = spectrum.wavelength.astype(np.float64) 
    462521                if len(spectrum.transmission) > 0: 
     
    490549            if dataset.data.ndim == 2: 
    491550                (n_rows, n_cols) = dataset.data.shape 
    492                 dataset.y_bins = dataset.qy_data[0::n_cols] 
    493                 dataset.x_bins = dataset.qx_data[:n_cols] 
     551                flat_qy = dataset.qy_data[0::n_cols].flatten() 
     552                # For 2D arrays of Qx and Qy, the Q value should be constant 
     553                # along each row -OR- each column. The direction is not 
     554                # specified in the NXcanSAS standard. 
     555                if flat_qy[0] == flat_qy[1]: 
     556                    flat_qy = np.transpose(dataset.qy_data)[0::n_cols].flatten() 
     557                dataset.y_bins = np.unique(flat_qy) 
     558                flat_qx = dataset.qx_data[0::n_rows].flatten() 
     559                # For 2D arrays of Qx and Qy, the Q value should be constant 
     560                # along each row -OR- each column. The direction is not 
     561                # specified in the NXcanSAS standard. 
     562                if flat_qx[0] == flat_qx[1]: 
     563                    flat_qx = np.transpose(dataset.qx_data)[0::n_rows].flatten() 
     564                dataset.x_bins = np.unique(flat_qx) 
    494565                dataset.data = dataset.data.flatten() 
     566                dataset.qx_data = dataset.qx_data.flatten() 
     567                dataset.qy_data = dataset.qy_data.flatten() 
    495568            self.current_dataset = dataset 
    496569            self.send_to_output() 
     
    515588        self.current_datainfo = DataInfo() 
    516589 
    517  
    518     def _initialize_new_data_set(self, parent_list=None): 
     590    def _initialize_new_data_set(self, value=None): 
    519591        """ 
    520592        A private class method to generate a new 1D or 2D data object based on 
     
    524596        :param parent_list: List of names of parent elements 
    525597        """ 
    526  
    527         if parent_list is None: 
    528             parent_list = [] 
    529         if self._find_intermediate(parent_list, "Qx"): 
     598        if self._is2d(value): 
    530599            self.current_dataset = plottable_2D() 
    531600        else: 
     
    534603            self.current_dataset = plottable_1D(x, y) 
    535604        self.current_datainfo.filename = self.raw_data.filename 
    536  
    537     def _find_intermediate(self, parent_list, basename=""): 
    538         """ 
    539         A private class used to find an entry by either using a direct key or 
    540         knowing the approximate basename. 
     605        self.mask_name = u'' 
     606        self.i_name = u'' 
     607        self.i_node = u'' 
     608        self.i_uncertainties_name = u'' 
     609        self.q_names = [] 
     610        self.q_uncertainty_names = [] 
     611        self.q_resolution_names = [] 
     612 
     613    @staticmethod 
     614    def check_is_list_or_array(iterable): 
     615        try: 
     616            iter(iterable) 
     617            if (not isinstance(iterable, np.ndarray) and not isinstance( 
     618                    iterable, list)) or (isinstance(iterable, basestring)): 
     619                raise TypeError 
     620        except TypeError: 
     621            iterable = iterable.split(",") 
     622        return iterable 
     623 
     624    def _find_data_attributes(self, value): 
     625        """ 
     626        A class to find the indices for Q, the name of the Qdev and Idev, and 
     627        the name of the mask. 
     628        :param value: SASdata/NXdata HDF5 Group 
     629        """ 
     630        attrs = value.attrs 
     631        signal = attrs.get("signal", "I") 
     632        i_axes = attrs.get("I_axes", ["Q"]) 
     633        q_indices = attrs.get("Q_indices", [0]) 
     634        q_indices = map(int, self.check_is_list_or_array(q_indices)) 
     635        i_axes = self.check_is_list_or_array(i_axes) 
     636        keys = value.keys() 
     637        self.mask_name = attrs.get("mask") 
     638        for val in q_indices: 
     639            self.q_names.append(i_axes[val]) 
     640        self.i_name = signal 
     641        self.i_node = value.get(self.i_name) 
     642        for item in self.q_names: 
     643            if item in keys: 
     644                q_vals = value.get(item) 
     645                if q_vals.attrs.get("uncertainties") is not None: 
     646                    self.q_uncertainty_names = q_vals.attrs.get("uncertainties") 
     647                elif q_vals.attrs.get("uncertainty") is not None: 
     648                    self.q_uncertainty_names = q_vals.attrs.get("uncertainty") 
     649                if isinstance(self.q_uncertainty_names, basestring): 
     650                    self.q_uncertainty_names = self.q_uncertainty_names.split(",") 
     651                if q_vals.attrs.get("resolutions") is not None: 
     652                    self.q_resolution_names = q_vals.attrs.get("resolutions") 
     653                if isinstance(self.q_resolution_names, basestring): 
     654                    self.q_resolution_names = self.q_resolution_names.split(",") 
     655        if self.i_name in keys: 
     656            i_vals = value.get(self.i_name) 
     657            self.i_uncertainties_name = i_vals.attrs.get("uncertainties") 
     658            if self.i_uncertainties_name is None: 
     659                self.i_uncertainties_name = i_vals.attrs.get("uncertainty") 
     660 
     661    def _is2d(self, value, basename="I"): 
     662        """ 
     663        A private class to determine if the data set is 1d or 2d. 
    541664 
    542665        :param parent_list: List of parents nodes in the HDF5 file 
    543666        :param basename: Approximate name of an entry to search for 
    544         :return: 
    545         """ 
    546  
    547         entry = False 
    548         key_prog = re.compile(basename) 
    549         top = self.raw_data 
    550         for parent in parent_list: 
    551             top = top.get(parent) 
    552         for key in top.keys(): 
    553             if key_prog.match(key): 
    554                 entry = True 
    555                 break 
    556         return entry 
     667        :return: True if 2D, otherwise false 
     668        """ 
     669 
     670        vals = value.get(basename) 
     671        return (vals is not None and vals.shape is not None 
     672                and len(vals.shape) != 1) 
    557673 
    558674    def _create_unique_key(self, dictionary, name, numb=0): 
     
    583699        if unit is None: 
    584700            unit = h5attr(value, u'unit') 
    585         # Convert the unit formats 
    586         if unit == "1/A": 
    587             unit = "A^{-1}" 
    588         elif unit == "1/cm": 
    589             unit = "cm^{-1}" 
    590701        return unit 
  • src/sas/sascalc/dataloader/readers/danse_reader.py

    r2469df7 rfc51d06  
    180180        detector.beam_center.y = center_y * pixel 
    181181 
    182  
    183         self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}') 
    184         self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}') 
    185         self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}") 
    186  
     182        self.current_dataset = self.set_default_2d_units(self.current_dataset) 
    187183        self.current_dataset.x_bins = x_vals 
    188184        self.current_dataset.y_bins = y_vals 
  • src/sas/sascalc/dataloader/readers/red2d_reader.py

    rc8321cfc r058f6c3  
    317317 
    318318        # Units of axes 
    319         self.current_dataset.xaxis(r"\rm{Q_{x}}", 'A^{-1}') 
    320         self.current_dataset.yaxis(r"\rm{Q_{y}}", 'A^{-1}') 
    321         self.current_dataset.zaxis(r"\rm{Intensity}", "cm^{-1}") 
     319        self.current_dataset = self.set_default_2d_units(self.current_dataset) 
    322320 
    323321        # Store loading process information 
  • src/sas/sascalc/file_converter/nxcansas_writer.py

    r574adc7 r2ca5d57b  
    88import os 
    99 
    10 from sas.sascalc.dataloader.readers.cansas_reader_HDF5 import Reader as Cansas2Reader 
     10from sas.sascalc.dataloader.readers.cansas_reader_HDF5 import Reader 
    1111from sas.sascalc.dataloader.data_info import Data1D, Data2D 
    1212 
    13 class NXcanSASWriter(Cansas2Reader): 
     13class NXcanSASWriter(Reader): 
    1414    """ 
    1515    A class for writing in NXcanSAS data files. Any number of data sets may be 
     
    8787                    entry[names[2]].attrs['units'] = units 
    8888 
    89         valid_data = all([issubclass(d.__class__, (Data1D, Data2D)) for d in dataset]) 
     89        valid_data = all([issubclass(d.__class__, (Data1D, Data2D)) for d in 
     90                          dataset]) 
    9091        if not valid_data: 
    91             raise ValueError("All entries of dataset must be Data1D or Data2D objects") 
     92            raise ValueError("All entries of dataset must be Data1D or Data2D" 
     93                             "objects") 
    9294 
    9395        # Get run name and number from first Data object 
     
    109111        sasentry.attrs['version'] = '1.0' 
    110112 
    111         i = 1 
    112  
    113         for data_obj in dataset: 
    114             data_entry = sasentry.create_group("sasdata{0:0=2d}".format(i)) 
     113        for i, data_obj in enumerate(dataset): 
     114            data_entry = sasentry.create_group("sasdata{0:0=2d}".format(i+1)) 
    115115            data_entry.attrs['canSAS_class'] = 'SASdata' 
    116116            if isinstance(data_obj, Data1D): 
     
    118118            elif isinstance(data_obj, Data2D): 
    119119                self._write_2d_data(data_obj, data_entry) 
    120             i += 1 
    121120 
    122121        data_info = dataset[0] 
     
    148147                sample_entry.create_dataset('details', data=details) 
    149148 
    150         # Instrumment metadata 
     149        # Instrument metadata 
    151150        instrument_entry = sasentry.create_group('sasinstrument') 
    152151        instrument_entry.attrs['canSAS_class'] = 'SASinstrument' 
     
    176175            units=data_info.source.beam_size_unit, write_fn=_write_h5_float) 
    177176 
    178  
    179177        # Collimation metadata 
    180178        if len(data_info.collimation) > 0: 
    181             i = 1 
    182             for coll_info in data_info.collimation: 
     179            for i, coll_info in enumerate(data_info.collimation): 
    183180                collimation_entry = instrument_entry.create_group( 
    184                     'sascollimation{0:0=2d}'.format(i)) 
     181                    'sascollimation{0:0=2d}'.format(i + 1)) 
    185182                collimation_entry.attrs['canSAS_class'] = 'SAScollimation' 
    186183                if coll_info.length is not None: 
    187184                    _write_h5_float(collimation_entry, coll_info.length, 'SDD') 
    188                     collimation_entry['SDD'].attrs['units'] = coll_info.length_unit 
     185                    collimation_entry['SDD'].attrs['units'] =\ 
     186                        coll_info.length_unit 
    189187                if coll_info.name is not None: 
    190188                    collimation_entry['name'] = _h5_string(coll_info.name) 
    191189        else: 
    192             # Create a blank one - at least 1 set of collimation metadata 
    193             # required by format 
    194             collimation_entry = instrument_entry.create_group('sascollimation01') 
     190            # Create a blank one - at least 1 collimation required by format 
     191            instrument_entry.create_group('sascollimation01') 
    195192 
    196193        # Detector metadata 
    197194        if len(data_info.detector) > 0: 
    198195            i = 1 
    199             for det_info in data_info.detector: 
     196            for i, det_info in enumerate(data_info.detector): 
    200197                detector_entry = instrument_entry.create_group( 
    201                     'sasdetector{0:0=2d}'.format(i)) 
     198                    'sasdetector{0:0=2d}'.format(i + 1)) 
    202199                detector_entry.attrs['canSAS_class'] = 'SASdetector' 
    203200                if det_info.distance is not None: 
    204201                    _write_h5_float(detector_entry, det_info.distance, 'SDD') 
    205                     detector_entry['SDD'].attrs['units'] = det_info.distance_unit 
     202                    detector_entry['SDD'].attrs['units'] =\ 
     203                        det_info.distance_unit 
    206204                if det_info.name is not None: 
    207205                    detector_entry['name'] = _h5_string(det_info.name) 
     
    209207                    detector_entry['name'] = _h5_string('') 
    210208                if det_info.slit_length is not None: 
    211                     _write_h5_float(detector_entry, det_info.slit_length, 'slit_length') 
    212                     detector_entry['slit_length'].attrs['units'] = det_info.slit_length_unit 
     209                    _write_h5_float(detector_entry, det_info.slit_length, 
     210                                    'slit_length') 
     211                    detector_entry['slit_length'].attrs['units'] =\ 
     212                        det_info.slit_length_unit 
    213213                _write_h5_vector(detector_entry, det_info.offset) 
    214214                # NXcanSAS doesn't save information about pitch, only roll 
     
    224224                    names=['x_pixel_size', 'y_pixel_size'], 
    225225                    write_fn=_write_h5_float, units=det_info.pixel_size_unit) 
    226  
    227                 i += 1 
    228226        else: 
    229227            # Create a blank one - at least 1 detector required by format 
     
    231229            detector_entry.attrs['canSAS_class'] = 'SASdetector' 
    232230            detector_entry.attrs['name'] = '' 
     231 
     232        # Process meta data 
     233        for i, process in enumerate(data_info.process): 
     234            process_entry = sasentry.create_group('sasprocess{0:0=2d}'.format( 
     235                i + 1)) 
     236            process_entry.attrs['canSAS_class'] = 'SASprocess' 
     237            if process.name: 
     238                name = _h5_string(process.name) 
     239                process_entry.create_dataset('name', data=name) 
     240            if process.date: 
     241                date = _h5_string(process.date) 
     242                process_entry.create_dataset('date', data=date) 
     243            if process.description: 
     244                desc = _h5_string(process.description) 
     245                process_entry.create_dataset('description', data=desc) 
     246            for j, term in enumerate(process.term): 
     247                # Don't save empty terms 
     248                if term: 
     249                    h5_term = _h5_string(term) 
     250                    process_entry.create_dataset('term{0:0=2d}'.format( 
     251                        j + 1), data=h5_term) 
     252            for j, note in enumerate(process.notes): 
     253                # Don't save empty notes 
     254                if note: 
     255                    h5_note = _h5_string(note) 
     256                    process_entry.create_dataset('note{0:0=2d}'.format( 
     257                        j + 1), data=h5_note) 
     258 
     259        # Transmission Spectrum 
     260        for i, trans in enumerate(data_info.trans_spectrum): 
     261            trans_entry = sasentry.create_group( 
     262                'sastransmission_spectrum{0:0=2d}'.format(i + 1)) 
     263            trans_entry.attrs['canSAS_class'] = 'SAStransmission_spectrum' 
     264            trans_entry.attrs['signal'] = 'T' 
     265            trans_entry.attrs['T_axes'] = 'T' 
     266            trans_entry.attrs['name'] = trans.name 
     267            if trans.timestamp is not '': 
     268                trans_entry.attrs['timestamp'] = trans.timestamp 
     269            transmission = trans_entry.create_dataset('T', 
     270                                                      data=trans.transmission) 
     271            transmission.attrs['unertainties'] = 'Tdev' 
     272            trans_entry.create_dataset('Tdev', 
     273                                       data=trans.transmission_deviation) 
     274            trans_entry.create_dataset('lambda', data=trans.wavelength) 
    233275 
    234276        note_entry = sasentry.create_group('sasnote'.format(i)) 
     
    254296        data_entry.attrs['signal'] = 'I' 
    255297        data_entry.attrs['I_axes'] = 'Q' 
    256         data_entry.attrs['I_uncertainties'] = 'Idev' 
    257         data_entry.attrs['Q_indicies'] = 0 
    258  
    259         dI = data_obj.dy 
    260         if dI is None: 
    261             dI = np.zeros((data_obj.y.shape)) 
    262  
    263         data_entry.create_dataset('Q', data=data_obj.x) 
    264         data_entry.create_dataset('I', data=data_obj.y) 
    265         data_entry.create_dataset('Idev', data=dI) 
     298        data_entry.attrs['Q_indices'] = [0] 
     299        q_entry = data_entry.create_dataset('Q', data=data_obj.x) 
     300        q_entry.attrs['units'] = data_obj.x_unit 
     301        i_entry = data_entry.create_dataset('I', data=data_obj.y) 
     302        i_entry.attrs['units'] = data_obj.y_unit 
     303        if data_obj.dy is not None: 
     304            i_entry.attrs['uncertainties'] = 'Idev' 
     305            i_dev_entry = data_entry.create_dataset('Idev', data=data_obj.dy) 
     306            i_dev_entry.attrs['units'] = data_obj.y_unit 
     307        if data_obj.dx is not None: 
     308            q_entry.attrs['resolutions'] = 'dQ' 
     309            dq_entry = data_entry.create_dataset('dQ', data=data_obj.dx) 
     310            dq_entry.attrs['units'] = data_obj.x_unit 
     311        elif data_obj.dxl is not None: 
     312            q_entry.attrs['resolutions'] = ['dQl','dQw'] 
     313            dql_entry = data_entry.create_dataset('dQl', data=data_obj.dxl) 
     314            dql_entry.attrs['units'] = data_obj.x_unit 
     315            dqw_entry = data_entry.create_dataset('dQw', data=data_obj.dxw) 
     316            dqw_entry.attrs['units'] = data_obj.x_unit 
    266317 
    267318    def _write_2d_data(self, data, data_entry): 
     
    273324        """ 
    274325        data_entry.attrs['signal'] = 'I' 
    275         data_entry.attrs['I_axes'] = 'Q,Q' 
    276         data_entry.attrs['I_uncertainties'] = 'Idev' 
    277         data_entry.attrs['Q_indicies'] = [0,1] 
     326        data_entry.attrs['I_axes'] = 'Qx,Qy' 
     327        data_entry.attrs['Q_indices'] = [0,1] 
    278328 
    279329        (n_rows, n_cols) = (len(data.y_bins), len(data.x_bins)) 
     
    288338                raise ValueError("Unable to calculate dimensions of 2D data") 
    289339 
    290         I = np.reshape(data.data, (n_rows, n_cols)) 
    291         dI = np.zeros((n_rows, n_cols)) 
    292         if not all(data.err_data == [None]): 
    293             dI = np.reshape(data.err_data, (n_rows, n_cols)) 
    294         qx =  np.reshape(data.qx_data, (n_rows, n_cols)) 
     340        intensity = np.reshape(data.data, (n_rows, n_cols)) 
     341        qx = np.reshape(data.qx_data, (n_rows, n_cols)) 
    295342        qy = np.reshape(data.qy_data, (n_rows, n_cols)) 
    296343 
    297         I_entry = data_entry.create_dataset('I', data=I) 
    298         I_entry.attrs['units'] = data.I_unit 
    299         Qx_entry = data_entry.create_dataset('Qx', data=qx) 
    300         Qx_entry.attrs['units'] = data.Q_unit 
    301         Qy_entry = data_entry.create_dataset('Qy', data=qy) 
    302         Qy_entry.attrs['units'] = data.Q_unit 
    303         Idev_entry = data_entry.create_dataset('Idev', data=dI) 
    304         Idev_entry.attrs['units'] = data.I_unit 
     344        i_entry = data_entry.create_dataset('I', data=intensity) 
     345        i_entry.attrs['units'] = data.I_unit 
     346        qx_entry = data_entry.create_dataset('Qx', data=qx) 
     347        qx_entry.attrs['units'] = data.Q_unit 
     348        qy_entry = data_entry.create_dataset('Qy', data=qy) 
     349        qy_entry.attrs['units'] = data.Q_unit 
     350        if data.err_data is not None and not all(data.err_data == [None]): 
     351            d_i = np.reshape(data.err_data, (n_rows, n_cols)) 
     352            i_entry.attrs['uncertainties'] = 'Idev' 
     353            i_dev_entry = data_entry.create_dataset('Idev', data=d_i) 
     354            i_dev_entry.attrs['units'] = data.I_unit 
     355        if data.dqx_data is not None and not all(data.dqx_data == [None]): 
     356            qx_entry.attrs['resolutions'] = 'dQx' 
     357            dqx_entry = data_entry.create_dataset('dQx', data=data.dqx_data) 
     358            dqx_entry.attrs['units'] = data.Q_unit 
     359        if data.dqy_data is not None and not all(data.dqy_data == [None]): 
     360            qy_entry.attrs['resolutions'] = 'dQy' 
     361            dqy_entry = data_entry.create_dataset('dQy', data=data.dqy_data) 
     362            dqy_entry.attrs['units'] = data.Q_unit 
Note: See TracChangeset for help on using the changeset viewer.