Changes in / [7c64911:759a8ab] in sasview


Ignore:
Files:
7 added
5 deleted
28 edited

Legend:

Unmodified
Added
Removed
  • installers/setup_exe.py

    red03b99 red03b99  
    345345 
    346346# Exclude packages that are not needed but are often found on build systems 
    347 excludes = ['Tkinter', 'PyQt4', '_tkagg', 'sip', 'pytz', 'sympy'] 
    348  
    349  
     347excludes = [ 
     348    'Tkinter', 'PyQt4', '_tkagg', 'sip', 'pytz', 'sympy', 
    350349    # Various matplotlib backends we are not using 
    351350    'libgdk_pixbuf-2.0-0.dll', 'libgobject-2.0-0.dll', 'libgdk-win32-2.0-0.dll', 
  • setup.py

    red03b99 red03b99  
    224224package_dir["sas.sascalc.dataloader"] = os.path.join( 
    225225    "src", "sas", "sascalc", "dataloader") 
    226 package_data["sas.sascalc.dataloader.readers"] = [ 
    227     'defaults.json', 'schema/*.xsd'] 
     226package_data["sas.sascalc.dataloader.readers"] = ['schema/*.xsd'] 
    228227packages.extend(["sas.sascalc.dataloader", "sas.sascalc.dataloader.readers", 
    229228                 "sas.sascalc.dataloader.readers.schema"]) 
  • src/sas/sascalc/data_util/registry.py

    ra1b8fee r3ece5dd  
    1 # This program is public domain 
    21""" 
    32File extension registry. 
     
    87from __future__ import print_function 
    98 
    10 import os.path 
     9from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException 
     10 
    1111 
    1212class ExtensionRegistry(object): 
     
    2222        # Add an association by setting an element 
    2323        registry['.zip'] = unzip 
    24          
     24 
    2525        # Multiple extensions for one loader 
    2626        registry['.tgz'] = untar 
    2727        registry['.tar.gz'] = untar 
    2828 
    29         # Generic extensions to use after trying more specific extensions;  
     29        # Generic extensions to use after trying more specific extensions; 
    3030        # these will be checked after the more specific extensions fail. 
    3131        registry['.gz'] = gunzip 
     
    3838        # Show registered extensions 
    3939        print registry.extensions() 
    40          
     40 
    4141        # Can also register a format name for explicit control from caller 
    4242        registry['cx3'] = cx3 
     
    6262    def __init__(self, **kw): 
    6363        self.loaders = {} 
     64 
    6465    def __setitem__(self, ext, loader): 
    6566        if ext not in self.loaders: 
    6667            self.loaders[ext] = [] 
    6768        self.loaders[ext].insert(0,loader) 
     69 
    6870    def __getitem__(self, ext): 
    6971        return self.loaders[ext] 
     72 
    7073    def __contains__(self, ext): 
    7174        return ext in self.loaders 
     75 
    7276    def formats(self): 
    7377        """ 
     
    7781        names.sort() 
    7882        return names 
     83 
    7984    def extensions(self): 
    8085        """ 
     
    8489        exts.sort() 
    8590        return exts 
     91 
    8692    def lookup(self, path): 
    8793        """ 
    8894        Return the loader associated with the file type of path. 
    89          
    90         Raises ValueError if file type is not known. 
    91         """         
     95 
     96        :param path: Data file path 
     97        :raises ValueError: When no loaders are found for the file. 
     98        :return: List of available readers for the file extension 
     99        """ 
    92100        # Find matching extensions 
    93101        extlist = [ext for ext in self.extensions() if path.endswith(ext)] 
     
    106114        # Raise an error if there are no matching extensions 
    107115        if len(loaders) == 0: 
    108             raise ValueError, "Unknown file type for "+path 
    109         # All done 
     116            raise ValueError("Unknown file type for "+path) 
    110117        return loaders 
     118 
    111119    def load(self, path, format=None): 
    112120        """ 
    113121        Call the loader for the file type of path. 
    114122 
    115         Raises ValueError if no loader is available. 
    116         Raises KeyError if format is not available. 
    117         May raise a loader-defined exception if loader fails.         
     123        :raise ValueError: if no loader is available. 
     124        :raise KeyError: if format is not available. 
     125        May raise a loader-defined exception if loader fails. 
    118126        """ 
     127        loaders = [] 
    119128        if format is None: 
    120             loaders = self.lookup(path) 
     129            try: 
     130                loaders = self.lookup(path) 
     131            except ValueError as e: 
     132                pass 
    121133        else: 
    122             loaders = self.loaders[format] 
     134            try: 
     135                loaders = self.loaders[format] 
     136            except KeyError as e: 
     137                pass 
     138        last_exc = None 
    123139        for fn in loaders: 
    124140            try: 
    125141                return fn(path) 
    126             except: 
    127                 pass # give other loaders a chance to succeed 
     142            except Exception as e: 
     143                last_exc = e 
     144                pass  # give other loaders a chance to succeed 
    128145        # If we get here it is because all loaders failed 
    129         raise # reraises last exception 
    130  
    131 def test(): 
    132     reg = ExtensionRegistry() 
    133     class CxError(Exception): pass 
    134     def cx(file): return 'cx' 
    135     def new_cx(file): return 'new_cx' 
    136     def fail_cx(file): raise CxError 
    137     def cat(file): return 'cat' 
    138     def gunzip(file): return 'gunzip' 
    139     reg['.cx'] = cx 
    140     reg['.cx1'] = cx 
    141     reg['.cx'] = new_cx 
    142     reg['.gz'] = gunzip 
    143     reg['.cx.gz'] = new_cx 
    144     reg['.cx1.gz'] = fail_cx 
    145     reg['.cx1'] = fail_cx 
    146     reg['.cx2'] = fail_cx 
    147     reg['new_cx'] = new_cx 
    148  
    149     # Two loaders associated with .cx 
    150     assert reg.lookup('hello.cx') == [new_cx,cx] 
    151     # Make sure the last loader applies first 
    152     assert reg.load('hello.cx') == 'new_cx' 
    153     # Make sure the next loader applies if the first fails 
    154     assert reg.load('hello.cx1') == 'cx' 
    155     # Make sure the format override works 
    156     assert reg.load('hello.cx1',format='.cx.gz') == 'new_cx' 
    157     # Make sure the format override works 
    158     assert reg.load('hello.cx1',format='new_cx') == 'new_cx' 
    159     # Make sure the case of all loaders failing is correct 
    160     try:  reg.load('hello.cx2') 
    161     except CxError: pass # correct failure 
    162     else: raise AssertError,"Incorrect error on load failure" 
    163     # Make sure the case of no loaders fails correctly 
    164     try: reg.load('hello.missing') 
    165     except ValueError,msg: 
    166         assert str(msg)=="Unknown file type for hello.missing",'Message: <%s>'%(msg) 
    167     else: raise AssertError,"No error raised for missing extension" 
    168     assert reg.formats() == ['new_cx'] 
    169     assert reg.extensions() == ['.cx','.cx.gz','.cx1','.cx1.gz','.cx2','.gz'] 
    170     # make sure that it supports multiple '.' in filename 
    171     assert reg.load('hello.extra.cx1') == 'cx' 
    172     assert reg.load('hello.gz') == 'gunzip' 
    173     assert reg.load('hello.cx1.gz') == 'gunzip' # Since .cx1.gz fails 
    174  
    175 if __name__ == "__main__": test() 
     146        if last_exc is not None and len(loaders) != 0: 
     147            # If file has associated loader(s) and they;ve failed 
     148            raise last_exc 
     149        raise NoKnownLoaderException(e.message)  # raise generic exception 
  • src/sas/sascalc/dataloader/data_info.py

    ra1b8fee ra1b8fee  
    11811181        return return_string 
    11821182 
    1183     final_dataset.xmax = data.xmax 
    1184     final_dataset.ymax = data.ymax 
    1185     final_dataset.xmin = data.xmin 
    1186     final_dataset.ymin = data.ymin 
     1183    if hasattr(data, "xmax"): 
     1184        final_dataset.xmax = data.xmax 
     1185    if hasattr(data, "ymax"): 
     1186        final_dataset.ymax = data.ymax 
     1187    if hasattr(data, "xmin"): 
     1188        final_dataset.xmin = data.xmin 
     1189    if hasattr(data, "ymin"): 
     1190        final_dataset.ymin = data.ymin 
    11871191    final_dataset.isSesans = datainfo.isSesans 
    11881192    final_dataset.title = datainfo.title 
  • src/sas/sascalc/dataloader/loader.py

    r463e7ffc rdcb91cf  
    11""" 
    22    File handler to support different file extensions. 
    3     Uses reflectometry's registry utility. 
     3    Uses reflectometer registry utility. 
    44 
    55    The default readers are found in the 'readers' sub-module 
     
    1414""" 
    1515##################################################################### 
    16 #This software was developed by the University of Tennessee as part of the 
    17 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    18 #project funded by the US National Science Foundation. 
    19 #See the license text in license.txt 
    20 #copyright 2008, University of Tennessee 
     16# This software was developed by the University of Tennessee as part of the 
     17# Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
     18# project funded by the US National Science Foundation. 
     19# See the license text in license.txt 
     20# copyright 2008, University of Tennessee 
    2121###################################################################### 
    2222 
     
    2929# Default readers are defined in the readers sub-module 
    3030import readers 
     31from loader_exceptions import NoKnownLoaderException, FileContentsException,\ 
     32    DefaultReaderException 
    3133from readers import ascii_reader 
    3234from readers import cansas_reader 
     35from readers import cansas_reader_HDF5 
    3336 
    3437logger = logging.getLogger(__name__) 
     38 
    3539 
    3640class Registry(ExtensionRegistry): 
     
    3943    Readers and writers are supported. 
    4044    """ 
    41  
    4245    def __init__(self): 
    4346        super(Registry, self).__init__() 
    4447 
    45         ## Writers 
     48        # Writers 
    4649        self.writers = {} 
    4750 
    48         ## List of wildcards 
     51        # List of wildcards 
    4952        self.wildcards = ['All (*.*)|*.*'] 
    5053 
    51         ## Creation time, for testing 
     54        # Creation time, for testing 
    5255        self._created = time.time() 
    5356 
     
    6366            of a particular reader 
    6467 
    65         Defaults to the ascii (multi-column) reader 
    66         if no reader was registered for the file's 
    67         extension. 
    68         """ 
     68        Defaults to the ascii (multi-column), cansas XML, and cansas NeXuS 
     69        readers if no reader was registered for the file's extension. 
     70        """ 
     71        # Gets set to a string if the file has an associated reader that fails 
     72        msg_from_reader = None 
    6973        try: 
    7074            return super(Registry, self).load(path, format=format) 
    71         except: 
    72             try: 
    73                 # No reader was found. Default to the ascii reader. 
    74                 ascii_loader = ascii_reader.Reader() 
    75                 return ascii_loader.read(path) 
    76             except: 
    77                 cansas_loader = cansas_reader.Reader() 
    78                 return cansas_loader.read(path) 
     75        except NoKnownLoaderException as nkl_e: 
     76            pass  # Try the ASCII reader 
     77        except FileContentsException as fc_exc: 
     78            # File has an associated reader but it failed. 
     79            # Save the error message to display later, but try the 3 default loaders 
     80            msg_from_reader = fc_exc.message 
     81        except Exception: 
     82            pass 
     83 
     84        # File has no associated reader, or the associated reader failed. 
     85        # Try the ASCII reader 
     86        try: 
     87            ascii_loader = ascii_reader.Reader() 
     88            return ascii_loader.read(path) 
     89        except DefaultReaderException: 
     90            pass  # Loader specific error to try the cansas XML reader 
     91        except FileContentsException as e: 
     92            if msg_from_reader is None: 
     93                raise RuntimeError(e.message) 
     94 
     95        # ASCII reader failed - try CanSAS xML reader 
     96        try: 
     97            cansas_loader = cansas_reader.Reader() 
     98            return cansas_loader.read(path) 
     99        except DefaultReaderException: 
     100            pass  # Loader specific error to try the NXcanSAS reader 
     101        except FileContentsException as e: 
     102            if msg_from_reader is None: 
     103                raise RuntimeError(e.message) 
     104        except Exception: 
     105            pass 
     106 
     107        # CanSAS XML reader failed - try NXcanSAS reader 
     108        try: 
     109            cansas_nexus_loader = cansas_reader_HDF5.Reader() 
     110            return cansas_nexus_loader.read(path) 
     111        except DefaultReaderException as e: 
     112            logging.error("No default loader can load the data") 
     113            # No known reader available. Give up and throw an error 
     114            if msg_from_reader is None: 
     115                msg = "\nUnknown data format: {}.\nThe file is not a ".format(path) 
     116                msg += "known format that can be loaded by SasView.\n" 
     117                raise NoKnownLoaderException(msg) 
     118            else: 
     119                # Associated reader and default readers all failed. 
     120                # Show error message from associated reader 
     121                raise RuntimeError(msg_from_reader) 
     122        except FileContentsException as e: 
     123            err_msg = msg_from_reader if msg_from_reader is not None else e.message 
     124            raise RuntimeError(err_msg) 
    79125 
    80126    def find_plugins(self, dir): 
  • src/sas/sascalc/dataloader/readers/__init__.py

    r959eb01 r7a5d066  
    1 # Backward compatibility with the previous implementation of the default readers 
    2 from associations import register_readers 
     1# Method to associate extensions to default readers 
     2from associations import read_associations 
    33 
    4 # Method to associate extensions to default readers  
    5 from associations import read_associations 
    64 
    75# Method to return the location of the XML settings file 
  • src/sas/sascalc/dataloader/readers/abs_reader.py

    r959eb01 rad92c5a  
    11""" 
     2    IGOR 1D data reader 
    23""" 
    34##################################################################### 
    4 #This software was developed by the University of Tennessee as part of the 
    5 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    6 #project funded by the US National Science Foundation. 
    7 #See the license text in license.txt 
    8 #copyright 2008, University of Tennessee 
     5# This software was developed by the University of Tennessee as part of the 
     6# Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
     7# project funded by the US National Science Foundation. 
     8# See the license text in license.txt 
     9# copyright 2008, University of Tennessee 
    910###################################################################### 
    1011 
     12import logging 
    1113import numpy as np 
    12 import os 
    13 from sas.sascalc.dataloader.data_info import Data1D 
    14 from sas.sascalc.dataloader.data_info import Detector 
    15  
    16 has_converter = True 
    17 try: 
    18     from sas.sascalc.data_util.nxsunit import Converter 
    19 except: 
    20     has_converter = False 
    21      
    22      
    23 class Reader: 
     14from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     15from sas.sascalc.dataloader.data_info import DataInfo, plottable_1D, Data1D,\ 
     16    Detector 
     17from sas.sascalc.dataloader.loader_exceptions import FileContentsException,\ 
     18    DefaultReaderException 
     19 
     20logger = logging.getLogger(__name__) 
     21 
     22 
     23class Reader(FileReader): 
    2424    """ 
    2525    Class to load IGOR reduced .ABS files 
    2626    """ 
    27     ## File type 
     27    # File type 
    2828    type_name = "IGOR 1D" 
    29     ## Wildcards 
     29    # Wildcards 
    3030    type = ["IGOR 1D files (*.abs)|*.abs"] 
    31     ## List of allowed extensions 
    32     ext = ['.abs', '.ABS'] 
     31    # List of allowed extensions 
     32    ext = ['.abs'] 
    3333     
    34     def read(self, path): 
     34    def get_file_contents(self): 
    3535        """  
    36         Load data file. 
    37          
    38         :param path: file path 
    39          
    40         :return: Data1D object, or None 
     36        Get the contents of the file 
    4137         
    4238        :raise RuntimeError: when the file can't be opened 
    4339        :raise ValueError: when the length of the data vectors are inconsistent 
    4440        """ 
    45         if os.path.isfile(path): 
    46             basename = os.path.basename(path) 
    47             root, extension = os.path.splitext(basename) 
    48             if extension.lower() in self.ext: 
    49                 try: 
    50                     input_f = open(path,'r') 
     41        buff = self.f_open.read() 
     42        filepath = self.f_open.name 
     43        lines = buff.splitlines() 
     44        self.has_converter = True 
     45        try: 
     46            from sas.sascalc.data_util.nxsunit import Converter 
     47        except: 
     48            self.has_converter = False 
     49        self.output = [] 
     50        self.current_datainfo = DataInfo() 
     51        self.current_datainfo.filename = filepath 
     52        self.reset_data_list(len(lines)) 
     53        detector = Detector() 
     54        data_line = 0 
     55        self.reset_data_list(len(lines)) 
     56        self.current_datainfo.detector.append(detector) 
     57        self.current_datainfo.filename = filepath 
     58 
     59        is_info = False 
     60        is_center = False 
     61        is_data_started = False 
     62 
     63        base_q_unit = '1/A' 
     64        base_i_unit = '1/cm' 
     65        data_conv_q = Converter(base_q_unit) 
     66        data_conv_i = Converter(base_i_unit) 
     67 
     68        for line in lines: 
     69            # Information line 1 
     70            if is_info: 
     71                is_info = False 
     72                line_toks = line.split() 
     73 
     74                # Wavelength in Angstrom 
     75                try: 
     76                    value = float(line_toks[1]) 
     77                    if self.has_converter and \ 
     78                            self.current_datainfo.source.wavelength_unit != 'A': 
     79                        conv = Converter('A') 
     80                        self.current_datainfo.source.wavelength = conv(value, 
     81                            units=self.current_datainfo.source.wavelength_unit) 
     82                    else: 
     83                        self.current_datainfo.source.wavelength = value 
     84                except KeyError: 
     85                    msg = "ABSReader cannot read wavelength from %s" % filepath 
     86                    self.current_datainfo.errors.append(msg) 
     87 
     88                # Detector distance in meters 
     89                try: 
     90                    value = float(line_toks[3]) 
     91                    if self.has_converter and detector.distance_unit != 'm': 
     92                        conv = Converter('m') 
     93                        detector.distance = conv(value, 
     94                                        units=detector.distance_unit) 
     95                    else: 
     96                        detector.distance = value 
    5197                except: 
    52                     raise  RuntimeError, "abs_reader: cannot open %s" % path 
    53                 buff = input_f.read() 
    54                 lines = buff.split('\n') 
    55                 x  = np.zeros(0) 
    56                 y  = np.zeros(0) 
    57                 dy = np.zeros(0) 
    58                 dx = np.zeros(0) 
    59                 output = Data1D(x, y, dy=dy, dx=dx) 
    60                 detector = Detector() 
    61                 output.detector.append(detector) 
    62                 output.filename = basename 
    63                  
    64                 is_info = False 
     98                    msg = "ABSReader cannot read SDD from %s" % filepath 
     99                    self.current_datainfo.errors.append(msg) 
     100 
     101                # Transmission 
     102                try: 
     103                    self.current_datainfo.sample.transmission = \ 
     104                        float(line_toks[4]) 
     105                except ValueError: 
     106                    # Transmission isn't always in the header 
     107                    pass 
     108 
     109                # Sample thickness in mm 
     110                try: 
     111                    value = float(line_toks[5]) 
     112                    if self.has_converter and \ 
     113                            self.current_datainfo.sample.thickness_unit != 'cm': 
     114                        conv = Converter('cm') 
     115                        self.current_datainfo.sample.thickness = conv(value, 
     116                            units=self.current_datainfo.sample.thickness_unit) 
     117                    else: 
     118                        self.current_datainfo.sample.thickness = value 
     119                except ValueError: 
     120                    # Thickness is not a mandatory entry 
     121                    pass 
     122 
     123            # MON CNT  LAMBDA  DET ANG  DET DIST  TRANS  THICK  AVE   STEP 
     124            if line.count("LAMBDA") > 0: 
     125                is_info = True 
     126 
     127            # Find center info line 
     128            if is_center: 
    65129                is_center = False 
    66                 is_data_started = False 
    67                  
    68                 data_conv_q = None 
    69                 data_conv_i = None 
    70                  
    71                 if has_converter == True and output.x_unit != '1/A': 
    72                     data_conv_q = Converter('1/A') 
    73                     # Test it 
    74                     data_conv_q(1.0, output.x_unit) 
    75                      
    76                 if has_converter == True and output.y_unit != '1/cm': 
    77                     data_conv_i = Converter('1/cm') 
    78                     # Test it 
    79                     data_conv_i(1.0, output.y_unit) 
    80                  
    81                 for line in lines: 
    82                      
    83                     # Information line 1 
    84                     if is_info == True: 
    85                         is_info = False 
    86                         line_toks = line.split() 
    87                          
    88                         # Wavelength in Angstrom 
    89                         try: 
    90                             value = float(line_toks[1]) 
    91                             if has_converter == True and \ 
    92                                 output.source.wavelength_unit != 'A': 
    93                                 conv = Converter('A') 
    94                                 output.source.wavelength = conv(value, 
    95                                         units=output.source.wavelength_unit) 
    96                             else: 
    97                                 output.source.wavelength = value 
    98                         except: 
    99                             #goes to ASC reader 
    100                             msg = "abs_reader: cannot open %s" % path 
    101                             raise  RuntimeError, msg 
    102                          
    103                         # Distance in meters 
    104                         try: 
    105                             value = float(line_toks[3]) 
    106                             if has_converter == True and \ 
    107                                 detector.distance_unit != 'm': 
    108                                 conv = Converter('m') 
    109                                 detector.distance = conv(value, 
    110                                                 units=detector.distance_unit) 
    111                             else: 
    112                                 detector.distance = value 
    113                         except: 
    114                             #goes to ASC reader 
    115                             msg = "abs_reader: cannot open %s" % path 
    116                             raise  RuntimeError, msg 
    117                         # Transmission 
    118                         try: 
    119                             output.sample.transmission = float(line_toks[4]) 
    120                         except: 
    121                             # Transmission is not a mandatory entry 
    122                             pass 
    123                      
    124                         # Thickness in mm 
    125                         try: 
    126                             value = float(line_toks[5]) 
    127                             if has_converter == True and \ 
    128                                 output.sample.thickness_unit != 'cm': 
    129                                 conv = Converter('cm') 
    130                                 output.sample.thickness = conv(value, 
    131                                             units=output.sample.thickness_unit) 
    132                             else: 
    133                                 output.sample.thickness = value 
    134                         except: 
    135                             # Thickness is not a mandatory entry 
    136                             pass 
    137                      
    138                     #MON CNT   LAMBDA   DET ANG   DET DIST   TRANS   THICK  
    139                     #  AVE   STEP 
    140                     if line.count("LAMBDA") > 0: 
    141                         is_info = True 
    142                          
    143                     # Find center info line 
    144                     if is_center == True: 
    145                         is_center = False 
    146                         line_toks = line.split() 
    147                         # Center in bin number 
    148                         center_x = float(line_toks[0]) 
    149                         center_y = float(line_toks[1]) 
    150                          
    151                         # Bin size 
    152                         if has_converter == True and \ 
    153                             detector.pixel_size_unit != 'mm': 
    154                             conv = Converter('mm') 
    155                             detector.pixel_size.x = conv(5.0, 
    156                                                 units=detector.pixel_size_unit) 
    157                             detector.pixel_size.y = conv(5.0, 
    158                                                 units=detector.pixel_size_unit) 
    159                         else: 
    160                             detector.pixel_size.x = 5.0 
    161                             detector.pixel_size.y = 5.0 
    162                          
    163                         # Store beam center in distance units 
    164                         # Det 640 x 640 mm 
    165                         if has_converter == True and \ 
    166                             detector.beam_center_unit != 'mm': 
    167                             conv = Converter('mm') 
    168                             detector.beam_center.x = conv(center_x * 5.0, 
    169                                              units=detector.beam_center_unit) 
    170                             detector.beam_center.y = conv(center_y * 5.0, 
    171                                             units=detector.beam_center_unit) 
    172                         else: 
    173                             detector.beam_center.x = center_x * 5.0 
    174                             detector.beam_center.y = center_y * 5.0 
    175                          
    176                         # Detector type 
    177                         try: 
    178                             detector.name = line_toks[7] 
    179                         except: 
    180                             # Detector name is not a mandatory entry 
    181                             pass 
    182                      
    183                     #BCENT(X,Y)   A1(mm)   A2(mm)   A1A2DIST(m)   DL/L 
    184                     #  BSTOP(mm)   DET_TYP 
    185                     if line.count("BCENT") > 0: 
    186                         is_center = True 
    187                          
    188                     # Parse the data 
    189                     if is_data_started == True: 
    190                         toks = line.split() 
    191  
    192                         try: 
    193                             _x  = float(toks[0]) 
    194                             _y  = float(toks[1]) 
    195                             _dy = float(toks[2]) 
    196                             _dx = float(toks[3]) 
    197                              
    198                             if data_conv_q is not None: 
    199                                 _x = data_conv_q(_x, units=output.x_unit) 
    200                                 _dx = data_conv_i(_dx, units=output.x_unit) 
    201                                  
    202                             if data_conv_i is not None: 
    203                                 _y = data_conv_i(_y, units=output.y_unit) 
    204                                 _dy = data_conv_i(_dy, units=output.y_unit) 
    205                             
    206                             x = np.append(x, _x) 
    207                             y = np.append(y, _y) 
    208                             dy = np.append(dy, _dy) 
    209                             dx = np.append(dx, _dx) 
    210                              
    211                         except: 
    212                             # Could not read this data line. If we are here 
    213                             # it is because we are in the data section. Just 
    214                             # skip it. 
    215                             pass 
    216                              
    217                     #The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev. 
    218                     # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor| 
    219                     if line.count("The 6 columns") > 0: 
    220                         is_data_started = True 
    221              
    222                 # Sanity check 
    223                 if not len(y) == len(dy): 
    224                     msg = "abs_reader: y and dy have different length" 
    225                     raise ValueError, msg 
    226                 # If the data length is zero, consider this as 
    227                 # though we were not able to read the file. 
    228                 if len(x) == 0: 
    229                     raise ValueError, "ascii_reader: could not load file" 
    230                  
    231                 output.x = x[x != 0] 
    232                 output.y = y[x != 0] 
    233                 output.dy = dy[x != 0] 
    234                 output.dx = dx[x != 0] 
    235                 if data_conv_q is not None: 
    236                     output.xaxis("\\rm{Q}", output.x_unit) 
     130                line_toks = line.split() 
     131                # Center in bin number 
     132                center_x = float(line_toks[0]) 
     133                center_y = float(line_toks[1]) 
     134 
     135                # Bin size 
     136                if self.has_converter and detector.pixel_size_unit != 'mm': 
     137                    conv = Converter('mm') 
     138                    detector.pixel_size.x = conv(5.08, 
     139                                        units=detector.pixel_size_unit) 
     140                    detector.pixel_size.y = conv(5.08, 
     141                                        units=detector.pixel_size_unit) 
    237142                else: 
    238                     output.xaxis("\\rm{Q}", 'A^{-1}') 
    239                 if data_conv_i is not None: 
    240                     output.yaxis("\\rm{Intensity}", output.y_unit) 
     143                    detector.pixel_size.x = 5.08 
     144                    detector.pixel_size.y = 5.08 
     145 
     146                # Store beam center in distance units 
     147                # Det 640 x 640 mm 
     148                if self.has_converter and detector.beam_center_unit != 'mm': 
     149                    conv = Converter('mm') 
     150                    detector.beam_center.x = conv(center_x * 5.08, 
     151                                     units=detector.beam_center_unit) 
     152                    detector.beam_center.y = conv(center_y * 5.08, 
     153                                    units=detector.beam_center_unit) 
    241154                else: 
    242                     output.yaxis("\\rm{Intensity}", "cm^{-1}") 
    243                      
    244                 # Store loading process information 
    245                 output.meta_data['loader'] = self.type_name 
    246                 return output 
     155                    detector.beam_center.x = center_x * 5.08 
     156                    detector.beam_center.y = center_y * 5.08 
     157 
     158                # Detector type 
     159                try: 
     160                    detector.name = line_toks[7] 
     161                except: 
     162                    # Detector name is not a mandatory entry 
     163                    pass 
     164 
     165            # BCENT(X,Y)  A1(mm)  A2(mm)  A1A2DIST(m)  DL/L  BSTOP(mm)  DET_TYP 
     166            if line.count("BCENT") > 0: 
     167                is_center = True 
     168 
     169            # Parse the data 
     170            if is_data_started: 
     171                toks = line.split() 
     172 
     173                try: 
     174                    _x = float(toks[0]) 
     175                    _y = float(toks[1]) 
     176                    _dy = float(toks[2]) 
     177                    _dx = float(toks[3]) 
     178 
     179                    if data_conv_q is not None: 
     180                        _x = data_conv_q(_x, units=base_q_unit) 
     181                        _dx = data_conv_q(_dx, units=base_q_unit) 
     182 
     183                    if data_conv_i is not None: 
     184                        _y = data_conv_i(_y, units=base_i_unit) 
     185                        _dy = data_conv_i(_dy, units=base_i_unit) 
     186 
     187                    self.current_dataset.x[data_line] = _x 
     188                    self.current_dataset.y[data_line] = _y 
     189                    self.current_dataset.dy[data_line] = _dy 
     190                    self.current_dataset.dx[data_line] = _dx 
     191                    data_line += 1 
     192 
     193                except ValueError: 
     194                    # Could not read this data line. If we are here 
     195                    # it is because we are in the data section. Just 
     196                    # skip it. 
     197                    pass 
     198 
     199            # The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev. 
     200            # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor| 
     201            if line.count("The 6 columns") > 0: 
     202                is_data_started = True 
     203 
     204        self.remove_empty_q_values(True, True) 
     205 
     206        # Sanity check 
     207        if not len(self.current_dataset.y) == len(self.current_dataset.dy): 
     208            self.set_all_to_none() 
     209            msg = "abs_reader: y and dy have different length" 
     210            raise ValueError(msg) 
     211        # If the data length is zero, consider this as 
     212        # though we were not able to read the file. 
     213        if len(self.current_dataset.x) == 0: 
     214            self.set_all_to_none() 
     215            raise ValueError("ascii_reader: could not load file") 
     216 
     217        if data_conv_q is not None: 
     218            self.current_dataset.xaxis("\\rm{Q}", base_q_unit) 
    247219        else: 
    248             raise RuntimeError, "%s is not a file" % path 
    249         return None 
     220            self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 
     221        if data_conv_i is not None: 
     222            self.current_dataset.yaxis("\\rm{Intensity}", base_i_unit) 
     223        else: 
     224            self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 
     225 
     226        # Store loading process information 
     227        self.current_datainfo.meta_data['loader'] = self.type_name 
     228        self.send_to_output() 
  • src/sas/sascalc/dataloader/readers/anton_paar_saxs_reader.py

    ra235f715 rfafe52a  
    99 
    1010from sas.sascalc.dataloader.readers.xml_reader import XMLreader 
    11 from sas.sascalc.dataloader.data_info import plottable_1D, Data1D, Sample, Source 
     11from sas.sascalc.dataloader.data_info import plottable_1D, Data1D, DataInfo, Sample, Source 
    1212from sas.sascalc.dataloader.data_info import Process, Aperture, Collimation, TransmissionSpectrum, Detector 
    13  
     13from sas.sascalc.dataloader.loader_exceptions import FileContentsException, DataReaderException 
    1414 
    1515class Reader(XMLreader): 
    1616    """ 
    17     A class for reading in CanSAS v2.0 data files. The existing iteration opens Mantid generated HDF5 formatted files 
    18     with file extension .h5/.H5. Any number of data sets may be present within the file and any dimensionality of data 
    19     may be used. Currently 1D and 2D SAS data sets are supported, but future implementations will include 1D and 2D 
    20     SESANS data. This class assumes a single data set for each sasentry. 
    21  
    22     :Dependencies: 
    23         The CanSAS HDF5 reader requires h5py v2.5.0 or later. 
     17    A class for reading in Anton Paar .pdh files 
    2418    """ 
    2519 
     
    3024    ## Raw file contents to be processed 
    3125    raw_data = None 
    32     ## Data set being modified 
    33     current_dataset = None 
    3426    ## For recursion and saving purposes, remember parent objects 
    3527    parent_list = None 
     
    4234    ## Flag to bypass extension check 
    4335    allow_all = False 
    44     ## List of files to return 
    45     output = None 
    4636 
    4737    def reset_state(self): 
    48         self.current_dataset = Data1D(np.empty(0), np.empty(0), 
    49                                             np.empty(0), np.empty(0)) 
     38        self.current_dataset = plottable_1D(np.empty(0), np.empty(0), np.empty(0), np.empty(0)) 
     39        self.current_datainfo = DataInfo() 
    5040        self.datasets = [] 
    5141        self.raw_data = None 
     
    6353        self.lower = 5 
    6454 
    65     def read(self, filename): 
     55    def get_file_contents(self): 
    6656        """ 
    6757            This is the general read method that all SasView data_loaders must have. 
     
    7363        ## Reinitialize the class when loading a new data file to reset all class variables 
    7464        self.reset_state() 
    75         ## Check that the file exists 
    76         if os.path.isfile(filename): 
    77             basename = os.path.basename(filename) 
    78             _, extension = os.path.splitext(basename) 
    79             # If the file type is not allowed, return empty list 
    80             if extension in self.ext or self.allow_all: 
    81                 ## Load the data file 
    82                 input_f = open(filename, 'r') 
    83                 buff = input_f.read() 
    84                 self.raw_data = buff.splitlines() 
    85                 self.read_data() 
    86         return self.output 
     65        buff = self.f_open.read() 
     66        self.raw_data = buff.splitlines() 
     67        self.read_data() 
    8768 
    8869    def read_data(self): 
     70        correctly_loaded = True 
     71        error_message = "" 
     72 
    8973        q_unit = "1/nm" 
    9074        i_unit = "1/um^2" 
    91         self.current_dataset.title = self.raw_data[0] 
    92         self.current_dataset.meta_data["Keywords"] = self.raw_data[1] 
    93         line3 = self.raw_data[2].split() 
    94         line4 = self.raw_data[3].split() 
    95         line5 = self.raw_data[4].split() 
    96         self.data_points = int(line3[0]) 
    97         self.lower = 5 
    98         self.upper = self.lower + self.data_points 
    99         self.source.radiation = 'x-ray' 
    100         normal = float(line4[3]) 
    101         self.current_dataset.source.radiation = "x-ray" 
    102         self.current_dataset.source.name = "Anton Paar SAXSess Instrument" 
    103         self.current_dataset.source.wavelength = float(line4[4]) 
    104         xvals = [] 
    105         yvals = [] 
    106         dyvals = [] 
    107         for i in range(self.lower, self.upper): 
    108             index = i - self.lower 
    109             data = self.raw_data[i].split() 
    110             xvals.insert(index, normal * float(data[0])) 
    111             yvals.insert(index, normal * float(data[1])) 
    112             dyvals.insert(index, normal * float(data[2])) 
     75        try: 
     76            self.current_datainfo.title = self.raw_data[0] 
     77            self.current_datainfo.meta_data["Keywords"] = self.raw_data[1] 
     78            line3 = self.raw_data[2].split() 
     79            line4 = self.raw_data[3].split() 
     80            line5 = self.raw_data[4].split() 
     81            self.data_points = int(line3[0]) 
     82            self.lower = 5 
     83            self.upper = self.lower + self.data_points 
     84            self.source.radiation = 'x-ray' 
     85            normal = float(line4[3]) 
     86            self.current_datainfo.source.radiation = "x-ray" 
     87            self.current_datainfo.source.name = "Anton Paar SAXSess Instrument" 
     88            self.current_datainfo.source.wavelength = float(line4[4]) 
     89            xvals = [] 
     90            yvals = [] 
     91            dyvals = [] 
     92            for i in range(self.lower, self.upper): 
     93                index = i - self.lower 
     94                data = self.raw_data[i].split() 
     95                xvals.insert(index, normal * float(data[0])) 
     96                yvals.insert(index, normal * float(data[1])) 
     97                dyvals.insert(index, normal * float(data[2])) 
     98        except Exception as e: 
     99            error_message = "Couldn't load {}.\n".format(self.f_open.name) 
     100            error_message += e.message 
     101            raise FileContentsException(error_message) 
    113102        self.current_dataset.x = np.append(self.current_dataset.x, xvals) 
    114103        self.current_dataset.y = np.append(self.current_dataset.y, yvals) 
    115104        self.current_dataset.dy = np.append(self.current_dataset.dy, dyvals) 
    116105        if self.data_points != self.current_dataset.x.size: 
    117             self.errors.add("Not all data was loaded properly.") 
    118         if self.current_dataset.dx.size != self.current_dataset.x.size: 
    119             dxvals = np.zeros(self.current_dataset.x.size) 
    120             self.current_dataset.dx = dxvals 
     106            error_message += "Not all data points could be loaded.\n" 
     107            correctly_loaded = False 
    121108        if self.current_dataset.x.size != self.current_dataset.y.size: 
    122             self.errors.add("The x and y data sets are not the same size.") 
     109            error_message += "The x and y data sets are not the same size.\n" 
     110            correctly_loaded = False 
    123111        if self.current_dataset.y.size != self.current_dataset.dy.size: 
    124             self.errors.add("The y and dy datasets are not the same size.") 
    125         self.current_dataset.errors = self.errors 
     112            error_message += "The y and dy datasets are not the same size.\n" 
     113            correctly_loaded = False 
     114 
    126115        self.current_dataset.xaxis("Q", q_unit) 
    127116        self.current_dataset.yaxis("Intensity", i_unit) 
    128117        xml_intermediate = self.raw_data[self.upper:] 
    129118        xml = ''.join(xml_intermediate) 
    130         self.set_xml_string(xml) 
    131         dom = self.xmlroot.xpath('/fileinfo') 
    132         self._parse_child(dom) 
    133         self.output.append(self.current_dataset) 
     119        try: 
     120            self.set_xml_string(xml) 
     121            dom = self.xmlroot.xpath('/fileinfo') 
     122            self._parse_child(dom) 
     123        except Exception as e: 
     124            # Data loaded but XML metadata has an error 
     125            error_message += "Data points have been loaded but there was an " 
     126            error_message += "error reading XML metadata: " + e.message 
     127            correctly_loaded = False 
     128        self.send_to_output() 
     129        if not correctly_loaded: 
     130            raise DataReaderException(error_message) 
    134131 
    135132    def _parse_child(self, dom, parent=''): 
     
    146143                self._parse_child(node, key) 
    147144                if key == "SampleDetector": 
    148                     self.current_dataset.detector.append(self.detector) 
     145                    self.current_datainfo.detector.append(self.detector) 
    149146                    self.detector = Detector() 
    150147            else: 
    151148                if key == "value": 
    152149                    if parent == "Wavelength": 
    153                         self.current_dataset.source.wavelength = value 
     150                        self.current_datainfo.source.wavelength = value 
    154151                    elif parent == "SampleDetector": 
    155152                        self.detector.distance = value 
    156153                    elif parent == "Temperature": 
    157                         self.current_dataset.sample.temperature = value 
     154                        self.current_datainfo.sample.temperature = value 
    158155                    elif parent == "CounterSlitLength": 
    159156                        self.detector.slit_length = value 
     
    161158                    value = value.replace("_", "") 
    162159                    if parent == "Wavelength": 
    163                         self.current_dataset.source.wavelength_unit = value 
     160                        self.current_datainfo.source.wavelength_unit = value 
    164161                    elif parent == "SampleDetector": 
    165162                        self.detector.distance_unit = value 
     
    169166                        self.current_dataset.yaxis(self.current_dataset._yaxis, value) 
    170167                    elif parent == "Temperature": 
    171                         self.current_dataset.sample.temperature_unit = value 
     168                        self.current_datainfo.sample.temperature_unit = value 
    172169                    elif parent == "CounterSlitLength": 
    173170                        self.detector.slit_length_unit = value 
  • src/sas/sascalc/dataloader/readers/ascii_reader.py

    r235f514 rf994e8b1  
    11""" 
    2     ASCII reader 
     2    Generic multi-column ASCII data reader 
    33""" 
    44############################################################################ 
    5 #This software was developed by the University of Tennessee as part of the 
    6 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    7 #project funded by the US National Science Foundation.  
    8 #If you use DANSE applications to do scientific research that leads to 
    9 #publication, we ask that you acknowledge the use of the software with the 
    10 #following sentence: 
    11 #This work benefited from DANSE software developed under NSF award DMR-0520547. 
    12 #copyright 2008, University of Tennessee 
     5# This software was developed by the University of Tennessee as part of the 
     6# Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
     7# project funded by the US National Science Foundation. 
     8# If you use DANSE applications to do scientific research that leads to 
     9# publication, we ask that you acknowledge the use of the software with the 
     10# following sentence: 
     11# This work benefited from DANSE software developed under NSF award DMR-0520547. 
     12# copyright 2008, University of Tennessee 
    1313############################################################################# 
    1414 
     15import logging 
     16from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     17from sas.sascalc.dataloader.data_info import DataInfo, plottable_1D 
     18from sas.sascalc.dataloader.loader_exceptions import FileContentsException,\ 
     19    DefaultReaderException 
    1520 
    16 import numpy as np 
    17 import os 
    18 from sas.sascalc.dataloader.data_info import Data1D 
    19  
    20 # Check whether we have a converter available 
    21 has_converter = True 
    22 try: 
    23     from sas.sascalc.data_util.nxsunit import Converter 
    24 except: 
    25     has_converter = False 
    26 _ZERO = 1e-16 
     21logger = logging.getLogger(__name__) 
    2722 
    2823 
    29 class Reader: 
     24class Reader(FileReader): 
    3025    """ 
    3126    Class to load ascii files (2, 3 or 4 columns). 
    3227    """ 
    33     ## File type 
     28    # File type 
    3429    type_name = "ASCII" 
    35  
    36     ## Wildcards 
     30    # Wildcards 
    3731    type = ["ASCII files (*.txt)|*.txt", 
    3832            "ASCII files (*.dat)|*.dat", 
    3933            "ASCII files (*.abs)|*.abs", 
    4034            "CSV files (*.csv)|*.csv"] 
    41     ## List of allowed extensions 
    42     ext = ['.txt', '.TXT', '.dat', '.DAT', '.abs', '.ABS', 'csv', 'CSV'] 
     35    # List of allowed extensions 
     36    ext = ['.txt', '.dat', '.abs', '.csv'] 
     37    # Flag to bypass extension check 
     38    allow_all = True 
     39    # data unless that is the only data 
     40    min_data_pts = 5 
    4341 
    44     ## Flag to bypass extension check 
    45     allow_all = True 
     42    def get_file_contents(self): 
     43        """ 
     44        Get the contents of the file 
     45        """ 
    4646 
    47     def read(self, path): 
    48         """ 
    49         Load data file 
     47        buff = self.f_open.read() 
     48        filepath = self.f_open.name 
     49        lines = buff.splitlines() 
     50        self.output = [] 
     51        self.current_datainfo = DataInfo() 
     52        self.current_datainfo.filename = filepath 
     53        self.reset_data_list(len(lines)) 
    5054 
    51         :param path: file path 
    52         :return: Data1D object, or None 
     55        # The first good line of data will define whether 
     56        # we have 2-column or 3-column ascii 
     57        has_error_dx = None 
     58        has_error_dy = None 
    5359 
    54         :raise RuntimeError: when the file can't be opened 
    55         :raise ValueError: when the length of the data vectors are inconsistent 
    56         """ 
    57         if os.path.isfile(path): 
    58             basename = os.path.basename(path) 
    59             _, extension = os.path.splitext(basename) 
    60             if self.allow_all or extension.lower() in self.ext: 
    61                 try: 
    62                     # Read in binary mode since GRASP frequently has no-ascii 
    63                     # characters that breaks the open operation 
    64                     input_f = open(path,'rb') 
    65                 except: 
    66                     raise  RuntimeError, "ascii_reader: cannot open %s" % path 
    67                 buff = input_f.read() 
    68                 lines = buff.splitlines() 
     60        # Initialize counters for data lines and header lines. 
     61        is_data = False 
     62        # More than "5" lines of data is considered as actual 
     63        # To count # of current data candidate lines 
     64        candidate_lines = 0 
     65        # To count total # of previous data candidate lines 
     66        candidate_lines_previous = 0 
     67        # Current line number 
     68        line_no = 0 
     69        # minimum required number of columns of data 
     70        lentoks = 2 
     71        for line in lines: 
     72            toks = self.splitline(line.strip()) 
     73            # To remember the number of columns in the current line of data 
     74            new_lentoks = len(toks) 
     75            try: 
     76                if new_lentoks == 0: 
     77                    # If the line is blank, skip and continue on 
     78                    # In case of breaks within data sets. 
     79                    continue 
     80                elif new_lentoks != lentoks and is_data: 
     81                    # If a footer is found, break the loop and save the data 
     82                    break 
     83                elif new_lentoks != lentoks and not is_data: 
     84                    # If header lines are numerical 
     85                    candidate_lines = 0 
     86                    self.reset_data_list(len(lines) - line_no) 
    6987 
    70                 # Arrays for data storage 
    71                 tx = np.zeros(0) 
    72                 ty = np.zeros(0) 
    73                 tdy = np.zeros(0) 
    74                 tdx = np.zeros(0) 
     88                self.current_dataset.x[candidate_lines] = float(toks[0]) 
    7589 
    76                 # The first good line of data will define whether 
    77                 # we have 2-column or 3-column ascii 
     90                if new_lentoks > 1: 
     91                    self.current_dataset.y[candidate_lines] = float(toks[1]) 
     92 
     93                # If a 3rd row is present, consider it dy 
     94                if new_lentoks > 2: 
     95                    self.current_dataset.dy[candidate_lines] = \ 
     96                        float(toks[2]) 
     97                    has_error_dy = True 
     98 
     99                # If a 4th row is present, consider it dx 
     100                if new_lentoks > 3: 
     101                    self.current_dataset.dx[candidate_lines] = \ 
     102                        float(toks[3]) 
     103                    has_error_dx = True 
     104 
     105                candidate_lines += 1 
     106                # If 5 or more lines, this is considering the set data 
     107                if candidate_lines >= self.min_data_pts: 
     108                    is_data = True 
     109 
     110                if is_data and new_lentoks >= 8: 
     111                    msg = "This data looks like 2D ASCII data. Use the file " 
     112                    msg += "converter tool to convert it to NXcanSAS." 
     113                    raise FileContentsException(msg) 
     114 
     115                # To remember the # of columns on the current line 
     116                # for the next line of data 
     117                lentoks = new_lentoks 
     118                line_no += 1 
     119            except ValueError: 
     120                # ValueError is raised when non numeric strings conv. to float 
     121                # It is data and meet non - number, then stop reading 
     122                if is_data: 
     123                    break 
     124                # Delete the previously stored lines of data candidates if 
     125                # the list is not data 
     126                self.reset_data_list(len(lines) - line_no) 
     127                lentoks = 2 
    78128                has_error_dx = None 
    79129                has_error_dy = None 
     130                # Reset # of lines of data candidates 
     131                candidate_lines = 0 
     132         
     133        if not is_data: 
     134            self.set_all_to_none() 
     135            if self.extension in self.ext: 
     136                msg = "ASCII Reader error: Fewer than five Q data points found " 
     137                msg += "in {}.".format(filepath) 
     138                raise FileContentsException(msg) 
     139            else: 
     140                msg = "ASCII Reader could not load the file {}".format(filepath) 
     141                raise DefaultReaderException(msg) 
     142        # Sanity check 
     143        if has_error_dy and not len(self.current_dataset.y) == \ 
     144                len(self.current_dataset.dy): 
     145            msg = "ASCII Reader error: Number of I and dI data points are" 
     146            msg += " different in {}.".format(filepath) 
     147            # TODO: Add error to self.current_datainfo.errors instead? 
     148            self.set_all_to_none() 
     149            raise FileContentsException(msg) 
     150        if has_error_dx and not len(self.current_dataset.x) == \ 
     151                len(self.current_dataset.dx): 
     152            msg = "ASCII Reader error: Number of Q and dQ data points are" 
     153            msg += " different in {}.".format(filepath) 
     154            # TODO: Add error to self.current_datainfo.errors instead? 
     155            self.set_all_to_none() 
     156            raise FileContentsException(msg) 
    80157 
    81                 #Initialize counters for data lines and header lines. 
    82                 is_data = False 
    83                 # More than "5" lines of data is considered as actual 
    84                 # data unless that is the only data 
    85                 min_data_pts = 5 
    86                 # To count # of current data candidate lines 
    87                 candidate_lines = 0 
    88                 # To count total # of previous data candidate lines 
    89                 candidate_lines_previous = 0 
    90                 #minimum required number of columns of data 
    91                 lentoks = 2 
    92                 for line in lines: 
    93                     toks = self.splitline(line) 
    94                     # To remember the # of columns in the current line of data 
    95                     new_lentoks = len(toks) 
    96                     try: 
    97                         if new_lentoks == 1 and not is_data: 
    98                             ## If only one item in list, no longer data 
    99                             raise ValueError 
    100                         elif new_lentoks == 0: 
    101                             ## If the line is blank, skip and continue on 
    102                             ## In case of breaks within data sets. 
    103                             continue 
    104                         elif new_lentoks != lentoks and is_data: 
    105                             ## If a footer is found, break the loop and save the data 
    106                             break 
    107                         elif new_lentoks != lentoks and not is_data: 
    108                             ## If header lines are numerical 
    109                             candidate_lines = 0 
    110                             candidate_lines_previous = 0 
     158        self.remove_empty_q_values(has_error_dx, has_error_dy) 
     159        self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 
     160        self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 
    111161 
    112                         #Make sure that all columns are numbers. 
    113                         for colnum in range(len(toks)): 
    114                             # Any non-floating point values throw ValueError 
    115                             float(toks[colnum]) 
    116  
    117                         candidate_lines += 1 
    118                         _x = float(toks[0]) 
    119                         _y = float(toks[1]) 
    120                         _dx = None 
    121                         _dy = None 
    122  
    123                         #If 5 or more lines, this is considering the set data 
    124                         if candidate_lines >= min_data_pts: 
    125                             is_data = True 
    126  
    127                         # If a 3rd row is present, consider it dy 
    128                         if new_lentoks > 2: 
    129                             _dy = float(toks[2]) 
    130                         has_error_dy = False if _dy is None else True 
    131  
    132                         # If a 4th row is present, consider it dx 
    133                         if new_lentoks > 3: 
    134                             _dx = float(toks[3]) 
    135                         has_error_dx = False if _dx is None else True 
    136  
    137                         # Delete the previously stored lines of data candidates if 
    138                         # the list is not data 
    139                         if candidate_lines == 1 and -1 < candidate_lines_previous < min_data_pts and \ 
    140                             is_data == False: 
    141                             try: 
    142                                 tx = np.zeros(0) 
    143                                 ty = np.zeros(0) 
    144                                 tdy = np.zeros(0) 
    145                                 tdx = np.zeros(0) 
    146                             except: 
    147                                 pass 
    148  
    149                         if has_error_dy == True: 
    150                             tdy = np.append(tdy, _dy) 
    151                         if has_error_dx == True: 
    152                             tdx = np.append(tdx, _dx) 
    153                         tx = np.append(tx, _x) 
    154                         ty = np.append(ty, _y) 
    155  
    156                         #To remember the # of columns on the current line 
    157                         # for the next line of data 
    158                         lentoks = new_lentoks 
    159                         candidate_lines_previous = candidate_lines 
    160                     except ValueError: 
    161                         # It is data and meet non - number, then stop reading 
    162                         if is_data == True: 
    163                             break 
    164                         lentoks = 2 
    165                         has_error_dx = None 
    166                         has_error_dy = None 
    167                         #Reset # of lines of data candidates 
    168                         candidate_lines = 0 
    169                     except: 
    170                         pass 
    171  
    172                 input_f.close() 
    173                 if not is_data: 
    174                     msg = "ascii_reader: x has no data" 
    175                     raise RuntimeError, msg 
    176                 # Sanity check 
    177                 if has_error_dy == True and not len(ty) == len(tdy): 
    178                     msg = "ascii_reader: y and dy have different length" 
    179                     raise RuntimeError, msg 
    180                 if has_error_dx == True and not len(tx) == len(tdx): 
    181                     msg = "ascii_reader: y and dy have different length" 
    182                     raise RuntimeError, msg 
    183                 # If the data length is zero, consider this as 
    184                 # though we were not able to read the file. 
    185                 if len(tx) == 0: 
    186                     raise RuntimeError, "ascii_reader: could not load file" 
    187  
    188                 #Let's re-order the data to make cal. 
    189                 # curve look better some cases 
    190                 ind = np.lexsort((ty, tx)) 
    191                 x = np.zeros(len(tx)) 
    192                 y = np.zeros(len(ty)) 
    193                 dy = np.zeros(len(tdy)) 
    194                 dx = np.zeros(len(tdx)) 
    195                 output = Data1D(x, y, dy=dy, dx=dx) 
    196                 self.filename = output.filename = basename 
    197  
    198                 for i in ind: 
    199                     x[i] = tx[ind[i]] 
    200                     y[i] = ty[ind[i]] 
    201                     if has_error_dy == True: 
    202                         dy[i] = tdy[ind[i]] 
    203                     if has_error_dx == True: 
    204                         dx[i] = tdx[ind[i]] 
    205                 # Zeros in dx, dy 
    206                 if has_error_dx: 
    207                     dx[dx == 0] = _ZERO 
    208                 if has_error_dy: 
    209                     dy[dy == 0] = _ZERO 
    210                 #Data 
    211                 output.x = x[x != 0] 
    212                 output.y = y[x != 0] 
    213                 output.dy = dy[x != 0] if has_error_dy == True\ 
    214                     else np.zeros(len(output.y)) 
    215                 output.dx = dx[x != 0] if has_error_dx == True\ 
    216                     else np.zeros(len(output.x)) 
    217  
    218                 output.xaxis("\\rm{Q}", 'A^{-1}') 
    219                 output.yaxis("\\rm{Intensity}", "cm^{-1}") 
    220  
    221                 # Store loading process information 
    222                 output.meta_data['loader'] = self.type_name 
    223                 if len(output.x) < 1: 
    224                     raise RuntimeError, "%s is empty" % path 
    225                 return output 
    226  
    227         else: 
    228             raise RuntimeError, "%s is not a file" % path 
    229         return None 
    230  
    231     def splitline(self, line): 
    232         """ 
    233         Splits a line into pieces based on common delimeters 
    234         :param line: A single line of text 
    235         :return: list of values 
    236         """ 
    237         # Initial try for CSV (split on ,) 
    238         toks = line.split(',') 
    239         # Now try SCSV (split on ;) 
    240         if len(toks) < 2: 
    241             toks = line.split(';') 
    242         # Now go for whitespace 
    243         if len(toks) < 2: 
    244             toks = line.split() 
    245         return toks 
     162        # Store loading process information 
     163        self.current_datainfo.meta_data['loader'] = self.type_name 
     164        self.send_to_output() 
  • src/sas/sascalc/dataloader/readers/associations.py

    ra1b8fee rce8c7bd  
    1414#copyright 2009, University of Tennessee 
    1515############################################################################# 
    16 from __future__ import print_function 
    17  
    18 import os 
    1916import sys 
    2017import logging 
    21 import json 
    2218 
    2319logger = logging.getLogger(__name__) 
    2420 
    25 FILE_NAME = 'defaults.json' 
     21FILE_ASSOCIATIONS = { 
     22    ".xml": "cansas_reader", 
     23    ".ses": "sesans_reader", 
     24    ".h5": "cansas_reader_HDF5", 
     25    ".txt": "ascii_reader", 
     26    ".dat": "red2d_reader", 
     27    ".abs": "abs_reader", 
     28    ".sans": "danse_reader", 
     29    ".pdh": "anton_paar_saxs_reader" 
     30} 
    2631 
    27 def read_associations(loader, settings=FILE_NAME): 
     32 
     33def read_associations(loader, settings=FILE_ASSOCIATIONS): 
    2834    """ 
    2935    Read the specified settings file to associate 
    3036    default readers to file extension. 
    31      
     37 
    3238    :param loader: Loader object 
    3339    :param settings: path to the json settings file [string] 
    3440    """ 
    35     reader_dir = os.path.dirname(__file__) 
    36     path = os.path.join(reader_dir, settings) 
    37      
    38     # If we can't find the file in the installation 
    39     # directory, look into the execution directory. 
    40     if not os.path.isfile(path): 
    41         path = os.path.join(os.getcwd(), settings) 
    42     if not os.path.isfile(path): 
    43         path = os.path.join(sys.path[0], settings) 
    44     if not os.path.isfile(path): 
    45         path = settings 
    46     if not os.path.isfile(path): 
    47         path = "./%s" % settings 
    48     if os.path.isfile(path): 
    49         with open(path) as fh: 
    50             json_tree = json.load(fh) 
    51          
    52         # Read in the file extension associations 
    53         entry_list = json_tree['SasLoader']['FileType'] 
    54  
    55         # For each FileType entry, get the associated reader and extension 
    56         for entry in entry_list: 
    57             reader = entry['-reader'] 
    58             ext = entry['-extension'] 
    59              
    60             if reader is not None and ext is not None: 
    61                 # Associate the extension with a particular reader 
    62                 # TODO: Modify the Register code to be case-insensitive 
    63                 # and remove the extra line below. 
    64                 try: 
    65                     exec "import %s" % reader 
    66                     exec "loader.associate_file_type('%s', %s)" % (ext.lower(), 
    67                                                                     reader) 
    68                     exec "loader.associate_file_type('%s', %s)" % (ext.upper(), 
    69                                                                     reader) 
    70                 except: 
    71                     msg = "read_associations: skipping association" 
    72                     msg += " for %s\n  %s" % (ext.lower(), sys.exc_value) 
    73                     logger.error(msg) 
    74     else: 
    75         print("Could not find reader association settings\n  %s [%s]" % (__file__, os.getcwd())) 
    76           
    77           
    78 def register_readers(registry_function): 
    79     """ 
    80     Function called by the registry/loader object to register 
    81     all default readers using a call back function. 
    82      
    83     :WARNING: this method is now obsolete 
    84  
    85     :param registry_function: function to be called to register each reader 
    86     """ 
    87     logger.info("register_readers is now obsolete: use read_associations()") 
    88     import abs_reader 
    89     import ascii_reader 
    90     import cansas_reader 
    91     import danse_reader 
    92     import hfir1d_reader 
    93     import IgorReader 
    94     import red2d_reader 
    95     #import tiff_reader 
    96     import nexus_reader 
    97     import sesans_reader 
    98     import cansas_reader_HDF5 
    99     import anton_paar_saxs_reader 
    100     registry_function(sesans_reader) 
    101     registry_function(abs_reader) 
    102     registry_function(ascii_reader) 
    103     registry_function(cansas_reader) 
    104     registry_function(danse_reader) 
    105     registry_function(hfir1d_reader) 
    106     registry_function(IgorReader) 
    107     registry_function(red2d_reader) 
    108     #registry_function(tiff_reader) 
    109     registry_function(nexus_reader) 
    110     registry_function(cansas_reader_HDF5) 
    111     registry_function(anton_paar_saxs_reader) 
    112     return True 
     41    # For each FileType entry, get the associated reader and extension 
     42    for ext, reader in settings.iteritems(): 
     43        if reader is not None and ext is not None: 
     44            # Associate the extension with a particular reader 
     45            # TODO: Modify the Register code to be case-insensitive 
     46            # FIXME: Remove exec statements 
     47            # and remove the extra line below. 
     48            try: 
     49                exec "import %s" % reader 
     50                exec "loader.associate_file_type('%s', %s)" % (ext.lower(), 
     51                                                                reader) 
     52                exec "loader.associate_file_type('%s', %s)" % (ext.upper(), 
     53                                                                reader) 
     54            except: 
     55                msg = "read_associations: skipping association" 
     56                msg += " for %s\n  %s" % (ext.lower(), sys.exc_value) 
     57                logger.error(msg) 
  • src/sas/sascalc/dataloader/readers/cansas_reader.py

    r7432acb rdcb91cf  
    1 """ 
    2     CanSAS data reader - new recursive cansas_version. 
    3 """ 
    4 ############################################################################ 
    5 #This software was developed by the University of Tennessee as part of the 
    6 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    7 #project funded by the US National Science Foundation. 
    8 #If you use DANSE applications to do scientific research that leads to 
    9 #publication, we ask that you acknowledge the use of the software with the 
    10 #following sentence: 
    11 #This work benefited from DANSE software developed under NSF award DMR-0520547. 
    12 #copyright 2008,2009 University of Tennessee 
    13 ############################################################################# 
    14  
    151import logging 
    162import numpy as np 
     
    2915from sas.sascalc.dataloader.readers.xml_reader import XMLreader 
    3016from sas.sascalc.dataloader.readers.cansas_constants import CansasConstants, CurrentLevel 
     17from sas.sascalc.dataloader.loader_exceptions import FileContentsException, \ 
     18    DefaultReaderException, DataReaderException 
    3119 
    3220# The following 2 imports *ARE* used. Do not remove either. 
    3321import xml.dom.minidom 
    3422from xml.dom.minidom import parseString 
     23 
     24from lxml import etree 
    3525 
    3626logger = logging.getLogger(__name__) 
     
    5545 
    5646class Reader(XMLreader): 
    57     """ 
    58     Class to load cansas 1D XML files 
    59  
    60     :Dependencies: 
    61         The CanSAS reader requires PyXML 0.8.4 or later. 
    62     """ 
    63     # CanSAS version - defaults to version 1.0 
    6447    cansas_version = "1.0" 
    6548    base_ns = "{cansas1d/1.0}" 
     
    7558    ns_list = None 
    7659    # Temporary storage location for loading multiple data sets in a single file 
    77     current_datainfo = None 
    78     current_dataset = None 
    7960    current_data1d = None 
    8061    data = None 
    81     # List of data1D objects to be sent back to SasView 
    82     output = None 
    8362    # Wildcards 
    8463    type = ["XML files (*.xml)|*.xml", "SasView Save Files (*.svs)|*.svs"] 
     
    11089 
    11190    def read(self, xml_file, schema_path="", invalid=True): 
    112         """ 
    113         Validate and read in an xml_file file in the canSAS format. 
    114  
    115         :param xml_file: A canSAS file path in proper XML format 
    116         :param schema_path: A file path to an XML schema to validate the xml_file against 
    117         """ 
    118         # For every file loaded, reset everything to a base state 
     91        if schema_path != "" or invalid != True: 
     92            # read has been called from self.get_file_contents because xml file doens't conform to schema 
     93            _, self.extension = os.path.splitext(os.path.basename(xml_file)) 
     94            return self.get_file_contents(xml_file=xml_file, schema_path=schema_path, invalid=invalid) 
     95 
     96        # Otherwise, read has been called by the data loader - file_reader_base_class handles this 
     97        return super(XMLreader, self).read(xml_file) 
     98 
     99    def get_file_contents(self, xml_file=None, schema_path="", invalid=True): 
     100        # Reset everything since we're loading a new file 
    119101        self.reset_state() 
    120102        self.invalid = invalid 
    121         # Check that the file exists 
    122         if os.path.isfile(xml_file): 
    123             basename, extension = os.path.splitext(os.path.basename(xml_file)) 
    124             # If the file type is not allowed, return nothing 
    125             if extension in self.ext or self.allow_all: 
    126                 # Get the file location of 
    127                 self.load_file_and_schema(xml_file, schema_path) 
    128                 self.add_data_set() 
    129                 # Try to load the file, but raise an error if unable to. 
    130                 # Check the file matches the XML schema 
     103        if xml_file is None: 
     104            xml_file = self.f_open.name 
     105        # We don't sure f_open since lxml handles opnening/closing files 
     106        if not self.f_open.closed: 
     107            self.f_open.close() 
     108 
     109        basename, _ = os.path.splitext(os.path.basename(xml_file)) 
     110 
     111        try: 
     112            # Raises FileContentsException 
     113            self.load_file_and_schema(xml_file, schema_path) 
     114            self.current_datainfo = DataInfo() 
     115            # Raises FileContentsException if file doesn't meet CanSAS schema 
     116            self.is_cansas(self.extension) 
     117            self.invalid = False # If we reach this point then file must be valid CanSAS 
     118 
     119            # Parse each SASentry 
     120            entry_list = self.xmlroot.xpath('/ns:SASroot/ns:SASentry', namespaces={ 
     121                'ns': self.cansas_defaults.get("ns") 
     122            }) 
     123            # Look for a SASentry 
     124            self.names.append("SASentry") 
     125            self.set_processing_instructions() 
     126 
     127            for entry in entry_list: 
     128                self.current_datainfo.filename = basename + self.extension 
     129                self.current_datainfo.meta_data["loader"] = "CanSAS XML 1D" 
     130                self.current_datainfo.meta_data[PREPROCESS] = self.processing_instructions 
     131                self._parse_entry(entry) 
     132                has_error_dx = self.current_dataset.dx is not None 
     133                has_error_dy = self.current_dataset.dy is not None 
     134                self.remove_empty_q_values(has_error_dx=has_error_dx, 
     135                    has_error_dy=has_error_dy) 
     136                self.send_to_output() # Combine datasets with DataInfo 
     137                self.current_datainfo = DataInfo() # Reset DataInfo 
     138        except FileContentsException as fc_exc: 
     139            # File doesn't meet schema - try loading with a less strict schema 
     140            base_name = xml_reader.__file__ 
     141            base_name = base_name.replace("\\", "/") 
     142            base = base_name.split("/sas/")[0] 
     143            if self.cansas_version == "1.1": 
     144                invalid_schema = INVALID_SCHEMA_PATH_1_1.format(base, self.cansas_defaults.get("schema")) 
     145            else: 
     146                invalid_schema = INVALID_SCHEMA_PATH_1_0.format(base, self.cansas_defaults.get("schema")) 
     147            self.set_schema(invalid_schema) 
     148            if self.invalid: 
    131149                try: 
    132                     self.is_cansas(extension) 
    133                     self.invalid = False 
    134                     # Get each SASentry from XML file and add it to a list. 
    135                     entry_list = self.xmlroot.xpath( 
    136                             '/ns:SASroot/ns:SASentry', 
    137                             namespaces={'ns': self.cansas_defaults.get("ns")}) 
    138                     self.names.append("SASentry") 
    139  
    140                     # Get all preprocessing events and encoding 
    141                     self.set_processing_instructions() 
    142  
    143                     # Parse each <SASentry> item 
    144                     for entry in entry_list: 
    145                         # Create a new DataInfo object for every <SASentry> 
    146  
    147                         # Set the file name and then parse the entry. 
    148                         self.current_datainfo.filename = basename + extension 
    149                         self.current_datainfo.meta_data["loader"] = "CanSAS XML 1D" 
    150                         self.current_datainfo.meta_data[PREPROCESS] = \ 
    151                             self.processing_instructions 
    152  
    153                         # Parse the XML SASentry 
    154                         self._parse_entry(entry) 
    155                         # Combine datasets with datainfo 
    156                         self.add_data_set() 
    157                 except RuntimeError: 
    158                     # If the file does not match the schema, raise this error 
     150                    # Load data with less strict schema 
     151                    self.read(xml_file, invalid_schema, False) 
     152 
     153                    # File can still be read but doesn't match schema, so raise exception 
     154                    self.load_file_and_schema(xml_file) # Reload strict schema so we can find where error are in file 
    159155                    invalid_xml = self.find_invalid_xml() 
    160                     invalid_xml = INVALID_XML.format(basename + extension) + invalid_xml 
    161                     self.errors.add(invalid_xml) 
    162                     # Try again with an invalid CanSAS schema, that requires only a data set in each 
    163                     base_name = xml_reader.__file__ 
    164                     base_name = base_name.replace("\\", "/") 
    165                     base = base_name.split("/sas/")[0] 
    166                     if self.cansas_version == "1.1": 
    167                         invalid_schema = INVALID_SCHEMA_PATH_1_1.format(base, self.cansas_defaults.get("schema")) 
    168                     else: 
    169                         invalid_schema = INVALID_SCHEMA_PATH_1_0.format(base, self.cansas_defaults.get("schema")) 
    170                     self.set_schema(invalid_schema) 
    171                     try: 
    172                         if self.invalid: 
    173                             if self.is_cansas(): 
    174                                 self.output = self.read(xml_file, invalid_schema, False) 
    175                             else: 
    176                                 raise RuntimeError 
    177                         else: 
    178                             raise RuntimeError 
    179                     except RuntimeError: 
    180                         x = np.zeros(1) 
    181                         y = np.zeros(1) 
    182                         self.current_data1d = Data1D(x,y) 
    183                         self.current_data1d.errors = self.errors 
    184                         return [self.current_data1d] 
    185         else: 
    186             self.output.append("Not a valid file path.") 
    187         # Return a list of parsed entries that dataloader can manage 
    188         return self.output 
     156                    invalid_xml = INVALID_XML.format(basename + self.extension) + invalid_xml 
     157                    raise DataReaderException(invalid_xml) # Handled by base class 
     158                except FileContentsException as fc_exc: 
     159                    msg = "CanSAS Reader could not load the file {}".format(xml_file) 
     160                    if fc_exc.message is not None: # Propagate error messages from earlier 
     161                        msg = fc_exc.message 
     162                    if not self.extension in self.ext: # If the file has no associated loader 
     163                        raise DefaultReaderException(msg) 
     164                    raise FileContentsException(msg) 
     165                    pass 
     166            else: 
     167                raise fc_exc 
     168        except Exception as e: # Convert all other exceptions to FileContentsExceptions 
     169            raise FileContentsException(e.message) 
     170 
     171 
     172    def load_file_and_schema(self, xml_file, schema_path=""): 
     173        base_name = xml_reader.__file__ 
     174        base_name = base_name.replace("\\", "/") 
     175        base = base_name.split("/sas/")[0] 
     176 
     177        # Try and parse the XML file 
     178        try: 
     179            self.set_xml_file(xml_file) 
     180        except etree.XMLSyntaxError: # File isn't valid XML so can't be loaded 
     181            msg = "SasView cannot load {}.\nInvalid XML syntax".format(xml_file) 
     182            raise FileContentsException(msg) 
     183 
     184        self.cansas_version = self.xmlroot.get("version", "1.0") 
     185        self.cansas_defaults = CANSAS_NS.get(self.cansas_version, "1.0") 
     186 
     187        if schema_path == "": 
     188            schema_path = "{}/sas/sascalc/dataloader/readers/schema/{}".format( 
     189                base, self.cansas_defaults.get("schema").replace("\\", "/") 
     190            ) 
     191        self.set_schema(schema_path) 
     192 
     193    def is_cansas(self, ext="xml"): 
     194        """ 
     195        Checks to see if the XML file is a CanSAS file 
     196 
     197        :param ext: The file extension of the data file 
     198        :raises FileContentsException: Raised if XML file isn't valid CanSAS 
     199        """ 
     200        if self.validate_xml(): # Check file is valid XML 
     201            name = "{http://www.w3.org/2001/XMLSchema-instance}schemaLocation" 
     202            value = self.xmlroot.get(name) 
     203            # Check schema CanSAS version matches file CanSAS version 
     204            if CANSAS_NS.get(self.cansas_version).get("ns") == value.rsplit(" ")[0]: 
     205                return True 
     206        if ext == "svs": 
     207            return True # Why is this required? 
     208        # If we get to this point then file isn't valid CanSAS 
     209        logger.warning("File doesn't meet CanSAS schema. Trying to load anyway.") 
     210        raise FileContentsException("The file is not valid CanSAS") 
    189211 
    190212    def _parse_entry(self, dom, recurse=False): 
    191         """ 
    192         Parse a SASEntry - new recursive method for parsing the dom of 
    193             the CanSAS data format. This will allow multiple data files 
    194             and extra nodes to be read in simultaneously. 
    195  
    196         :param dom: dom object with a namespace base of names 
    197         """ 
    198  
    199213        if not self._is_call_local() and not recurse: 
    200214            self.reset_state() 
    201             self.add_data_set() 
     215            self.data = [] 
     216            self.current_datainfo = DataInfo() 
    202217            self.names.append("SASentry") 
    203218            self.parent_class = "SASentry" 
    204         self._check_for_empty_data() 
    205         self.base_ns = "{0}{1}{2}".format("{", \ 
    206                             CANSAS_NS.get(self.cansas_version).get("ns"), "}") 
    207  
    208         # Go through each child in the parent element 
     219        # Create an empty dataset if no data has been passed to the reader 
     220        if self.current_dataset is None: 
     221            self.current_dataset = plottable_1D(np.empty(0), np.empty(0), 
     222                np.empty(0), np.empty(0)) 
     223        self.base_ns = "{" + CANSAS_NS.get(self.cansas_version).get("ns") + "}" 
     224 
     225        # Loop through each child in the parent element 
    209226        for node in dom: 
    210227            attr = node.attrib 
     
    217234            if tagname == "fitting_plug_in" or tagname == "pr_inversion" or tagname == "invariant": 
    218235                continue 
    219  
    220236            # Get where to store content 
    221237            self.names.append(tagname_original) 
     
    233249                        else: 
    234250                            self.current_dataset.shape = () 
    235                 # Recursion step to access data within the group 
    236                 self._parse_entry(node, True) 
     251                # Recurse to access data within the group 
     252                self._parse_entry(node, recurse=True) 
    237253                if tagname == "SASsample": 
    238254                    self.current_datainfo.sample.name = name 
     
    244260                    self.aperture.name = name 
    245261                    self.aperture.type = type 
    246                 self.add_intermediate() 
     262                self._add_intermediate() 
    247263            else: 
    248264                if isinstance(self.current_dataset, plottable_2D): 
     
    261277                    self.current_datainfo.notes.append(data_point) 
    262278 
    263                 # I and Q - 1D data 
     279                # I and Q points 
    264280                elif tagname == 'I' and isinstance(self.current_dataset, plottable_1D): 
    265281                    unit_list = unit.split("|") 
     
    283299                    self.current_dataset.dx = np.append(self.current_dataset.dx, data_point) 
    284300                elif tagname == 'dQw': 
     301                    if self.current_dataset.dqw is None: self.current_dataset.dqw = np.empty(0) 
    285302                    self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point) 
    286303                elif tagname == 'dQl': 
     304                    if self.current_dataset.dxl is None: self.current_dataset.dxl = np.empty(0) 
    287305                    self.current_dataset.dxl = np.append(self.current_dataset.dxl, data_point) 
    288306                elif tagname == 'Qmean': 
     
    356374                elif tagname == 'name' and self.parent_class == 'SASinstrument': 
    357375                    self.current_datainfo.instrument = data_point 
     376 
    358377                # Detector Information 
    359378                elif tagname == 'name' and self.parent_class == 'SASdetector': 
     
    401420                    self.detector.orientation.z = data_point 
    402421                    self.detector.orientation_unit = unit 
     422 
    403423                # Collimation and Aperture 
    404424                elif tagname == 'length' and self.parent_class == 'SAScollimation': 
     
    434454                elif tagname == 'term' and self.parent_class == 'SASprocess': 
    435455                    unit = attr.get("unit", "") 
    436                     dic = {} 
    437                     dic["name"] = name 
    438                     dic["value"] = data_point 
    439                     dic["unit"] = unit 
     456                    dic = { "name": name, "value": data_point, "unit": unit } 
    440457                    self.process.term.append(dic) 
    441458 
     
    490507        if not self._is_call_local() and not recurse: 
    491508            self.frm = "" 
    492             self.add_data_set() 
     509            self.current_datainfo.errors = set() 
     510            for error in self.errors: 
     511                self.current_datainfo.errors.add(error) 
     512            self.errors.clear() 
     513            self.send_to_output() 
    493514            empty = None 
    494515            return self.output[0], empty 
    495516 
    496  
    497517    def _is_call_local(self): 
    498         """ 
    499  
    500         """ 
    501518        if self.frm == "": 
    502519            inter = inspect.stack() 
     
    510527        return True 
    511528 
    512     def is_cansas(self, ext="xml"): 
    513         """ 
    514         Checks to see if the xml file is a CanSAS file 
    515  
    516         :param ext: The file extension of the data file 
    517         """ 
    518         if self.validate_xml(): 
    519             name = "{http://www.w3.org/2001/XMLSchema-instance}schemaLocation" 
    520             value = self.xmlroot.get(name) 
    521             if CANSAS_NS.get(self.cansas_version).get("ns") == \ 
    522                     value.rsplit(" ")[0]: 
    523                 return True 
    524         if ext == "svs": 
    525             return True 
    526         raise RuntimeError 
    527  
    528     def load_file_and_schema(self, xml_file, schema_path=""): 
    529         """ 
    530         Loads the file and associates a schema, if a schema is passed in or if one already exists 
    531  
    532         :param xml_file: The xml file path sent to Reader.read 
    533         :param schema_path: The path to a schema associated with the xml_file, or find one based on the file 
    534         """ 
    535         base_name = xml_reader.__file__ 
    536         base_name = base_name.replace("\\", "/") 
    537         base = base_name.split("/sas/")[0] 
    538  
    539         # Load in xml file and get the cansas version from the header 
    540         self.set_xml_file(xml_file) 
    541         self.cansas_version = self.xmlroot.get("version", "1.0") 
    542  
    543         # Generic values for the cansas file based on the version 
    544         self.cansas_defaults = CANSAS_NS.get(self.cansas_version, "1.0") 
    545         if schema_path == "": 
    546             schema_path = "{0}/sas/sascalc/dataloader/readers/schema/{1}".format \ 
    547                 (base, self.cansas_defaults.get("schema")).replace("\\", "/") 
    548  
    549         # Link a schema to the XML file. 
    550         self.set_schema(schema_path) 
    551  
    552     def add_data_set(self): 
    553         """ 
    554         Adds the current_dataset to the list of outputs after preforming final processing on the data and then calls a 
    555         private method to generate a new data set. 
    556  
    557         :param key: NeXus group name for current tree level 
    558         """ 
    559  
    560         if self.current_datainfo and self.current_dataset: 
    561             self._final_cleanup() 
    562         self.data = [] 
    563         self.current_datainfo = DataInfo() 
    564  
    565     def _initialize_new_data_set(self, node=None): 
    566         """ 
    567         A private class method to generate a new 1D data object. 
    568         Outside methods should call add_data_set() to be sure any existing data is stored properly. 
    569  
    570         :param node: XML node to determine if 1D or 2D data 
    571         """ 
    572         x = np.array(0) 
    573         y = np.array(0) 
    574         for child in node: 
    575             if child.tag.replace(self.base_ns, "") == "Idata": 
    576                 for i_child in child: 
    577                     if i_child.tag.replace(self.base_ns, "") == "Qx": 
    578                         self.current_dataset = plottable_2D() 
    579                         return 
    580         self.current_dataset = plottable_1D(x, y) 
    581  
    582     def add_intermediate(self): 
     529    def _add_intermediate(self): 
    583530        """ 
    584531        This method stores any intermediate objects within the final data set after fully reading the set. 
    585  
    586         :param parent: The NXclass name for the h5py Group object that just finished being processed 
    587         """ 
    588  
     532        """ 
    589533        if self.parent_class == 'SASprocess': 
    590534            self.current_datainfo.process.append(self.process) 
     
    605549            self._check_for_empty_resolution() 
    606550            self.data.append(self.current_dataset) 
    607  
    608     def _final_cleanup(self): 
    609         """ 
    610         Final cleanup of the Data1D object to be sure it has all the 
    611         appropriate information needed for perspectives 
    612         """ 
    613  
    614         # Append errors to dataset and reset class errors 
    615         self.current_datainfo.errors = set() 
    616         for error in self.errors: 
    617             self.current_datainfo.errors.add(error) 
    618         self.errors.clear() 
    619  
    620         # Combine all plottables with datainfo and append each to output 
    621         # Type cast data arrays to float64 and find min/max as appropriate 
    622         for dataset in self.data: 
    623             if isinstance(dataset, plottable_1D): 
    624                 if dataset.x is not None: 
    625                     dataset.x = np.delete(dataset.x, [0]) 
    626                     dataset.x = dataset.x.astype(np.float64) 
    627                     dataset.xmin = np.min(dataset.x) 
    628                     dataset.xmax = np.max(dataset.x) 
    629                 if dataset.y is not None: 
    630                     dataset.y = np.delete(dataset.y, [0]) 
    631                     dataset.y = dataset.y.astype(np.float64) 
    632                     dataset.ymin = np.min(dataset.y) 
    633                     dataset.ymax = np.max(dataset.y) 
    634                 if dataset.dx is not None: 
    635                     dataset.dx = np.delete(dataset.dx, [0]) 
    636                     dataset.dx = dataset.dx.astype(np.float64) 
    637                 if dataset.dxl is not None: 
    638                     dataset.dxl = np.delete(dataset.dxl, [0]) 
    639                     dataset.dxl = dataset.dxl.astype(np.float64) 
    640                 if dataset.dxw is not None: 
    641                     dataset.dxw = np.delete(dataset.dxw, [0]) 
    642                     dataset.dxw = dataset.dxw.astype(np.float64) 
    643                 if dataset.dy is not None: 
    644                     dataset.dy = np.delete(dataset.dy, [0]) 
    645                     dataset.dy = dataset.dy.astype(np.float64) 
    646                 np.trim_zeros(dataset.x) 
    647                 np.trim_zeros(dataset.y) 
    648                 np.trim_zeros(dataset.dy) 
    649             elif isinstance(dataset, plottable_2D): 
    650                 dataset.data = dataset.data.astype(np.float64) 
    651                 dataset.qx_data = dataset.qx_data.astype(np.float64) 
    652                 dataset.xmin = np.min(dataset.qx_data) 
    653                 dataset.xmax = np.max(dataset.qx_data) 
    654                 dataset.qy_data = dataset.qy_data.astype(np.float64) 
    655                 dataset.ymin = np.min(dataset.qy_data) 
    656                 dataset.ymax = np.max(dataset.qy_data) 
    657                 dataset.q_data = np.sqrt(dataset.qx_data * dataset.qx_data 
    658                                          + dataset.qy_data * dataset.qy_data) 
    659                 if dataset.err_data is not None: 
    660                     dataset.err_data = dataset.err_data.astype(np.float64) 
    661                 if dataset.dqx_data is not None: 
    662                     dataset.dqx_data = dataset.dqx_data.astype(np.float64) 
    663                 if dataset.dqy_data is not None: 
    664                     dataset.dqy_data = dataset.dqy_data.astype(np.float64) 
    665                 if dataset.mask is not None: 
    666                     dataset.mask = dataset.mask.astype(dtype=bool) 
    667  
    668                 if len(dataset.shape) == 2: 
    669                     n_rows, n_cols = dataset.shape 
    670                     dataset.y_bins = dataset.qy_data[0::int(n_cols)] 
    671                     dataset.x_bins = dataset.qx_data[:int(n_cols)] 
    672                     dataset.data = dataset.data.flatten() 
    673                 else: 
    674                     dataset.y_bins = [] 
    675                     dataset.x_bins = [] 
    676                     dataset.data = dataset.data.flatten() 
    677  
    678             final_dataset = combine_data(dataset, self.current_datainfo) 
    679             self.output.append(final_dataset) 
    680  
    681     def _create_unique_key(self, dictionary, name, numb=0): 
    682         """ 
    683         Create a unique key value for any dictionary to prevent overwriting 
    684         Recurse until a unique key value is found. 
    685  
    686         :param dictionary: A dictionary with any number of entries 
    687         :param name: The index of the item to be added to dictionary 
    688         :param numb: The number to be appended to the name, starts at 0 
    689         """ 
    690         if dictionary.get(name) is not None: 
    691             numb += 1 
    692             name = name.split("_")[0] 
    693             name += "_{0}".format(numb) 
    694             name = self._create_unique_key(dictionary, name, numb) 
    695         return name 
    696551 
    697552    def _get_node_value(self, node, tagname): 
     
    801656        return node_value, value_unit 
    802657 
    803     def _check_for_empty_data(self): 
    804         """ 
    805         Creates an empty data set if no data is passed to the reader 
    806  
    807         :param data1d: presumably a Data1D object 
    808         """ 
    809         if self.current_dataset is None: 
    810             x_vals = np.empty(0) 
    811             y_vals = np.empty(0) 
    812             dx_vals = np.empty(0) 
    813             dy_vals = np.empty(0) 
    814             dxl = np.empty(0) 
    815             dxw = np.empty(0) 
    816             self.current_dataset = plottable_1D(x_vals, y_vals, dx_vals, dy_vals) 
    817             self.current_dataset.dxl = dxl 
    818             self.current_dataset.dxw = dxw 
    819  
    820658    def _check_for_empty_resolution(self): 
    821659        """ 
    822         A method to check all resolution data sets are the same size as I and Q 
    823         """ 
    824         if isinstance(self.current_dataset, plottable_1D): 
    825             dql_exists = False 
    826             dqw_exists = False 
    827             dq_exists = False 
    828             di_exists = False 
    829             if self.current_dataset.dxl is not None: 
    830                 dql_exists = True 
    831             if self.current_dataset.dxw is not None: 
    832                 dqw_exists = True 
    833             if self.current_dataset.dx is not None: 
    834                 dq_exists = True 
    835             if self.current_dataset.dy is not None: 
    836                 di_exists = True 
    837             if dqw_exists and not dql_exists: 
    838                 array_size = self.current_dataset.dxw.size - 1 
    839                 self.current_dataset.dxl = np.append(self.current_dataset.dxl, 
    840                                                      np.zeros([array_size])) 
    841             elif dql_exists and not dqw_exists: 
    842                 array_size = self.current_dataset.dxl.size - 1 
    843                 self.current_dataset.dxw = np.append(self.current_dataset.dxw, 
    844                                                      np.zeros([array_size])) 
    845             elif not dql_exists and not dqw_exists and not dq_exists: 
    846                 array_size = self.current_dataset.x.size - 1 
    847                 self.current_dataset.dx = np.append(self.current_dataset.dx, 
    848                                                     np.zeros([array_size])) 
    849             if not di_exists: 
    850                 array_size = self.current_dataset.y.size - 1 
    851                 self.current_dataset.dy = np.append(self.current_dataset.dy, 
    852                                                     np.zeros([array_size])) 
    853         elif isinstance(self.current_dataset, plottable_2D): 
    854             dqx_exists = False 
    855             dqy_exists = False 
    856             di_exists = False 
    857             mask_exists = False 
    858             if self.current_dataset.dqx_data is not None: 
    859                 dqx_exists = True 
    860             if self.current_dataset.dqy_data is not None: 
    861                 dqy_exists = True 
    862             if self.current_dataset.err_data is not None: 
    863                 di_exists = True 
    864             if self.current_dataset.mask is not None: 
    865                 mask_exists = True 
    866             if not dqy_exists: 
    867                 array_size = self.current_dataset.qy_data.size - 1 
    868                 self.current_dataset.dqy_data = np.append( 
    869                     self.current_dataset.dqy_data, np.zeros([array_size])) 
    870             if not dqx_exists: 
    871                 array_size = self.current_dataset.qx_data.size - 1 
    872                 self.current_dataset.dqx_data = np.append( 
    873                     self.current_dataset.dqx_data, np.zeros([array_size])) 
    874             if not di_exists: 
    875                 array_size = self.current_dataset.data.size - 1 
    876                 self.current_dataset.err_data = np.append( 
    877                     self.current_dataset.err_data, np.zeros([array_size])) 
    878             if not mask_exists: 
    879                 array_size = self.current_dataset.data.size - 1 
    880                 self.current_dataset.mask = np.append( 
    881                     self.current_dataset.mask, 
    882                     np.ones([array_size] ,dtype=bool)) 
    883  
    884     ####### All methods below are for writing CanSAS XML files ####### 
    885  
     660        a method to check all resolution data sets are the same size as I and q 
     661        """ 
     662        dql_exists = False 
     663        dqw_exists = False 
     664        dq_exists = False 
     665        di_exists = False 
     666        if self.current_dataset.dxl is not None: 
     667            dql_exists = True 
     668        if self.current_dataset.dxw is not None: 
     669            dqw_exists = True 
     670        if self.current_dataset.dx is not None: 
     671            dq_exists = True 
     672        if self.current_dataset.dy is not None: 
     673            di_exists = True 
     674        if dqw_exists and not dql_exists: 
     675            array_size = self.current_dataset.dxw.size - 1 
     676            self.current_dataset.dxl = np.append(self.current_dataset.dxl, 
     677                                                 np.zeros([array_size])) 
     678        elif dql_exists and not dqw_exists: 
     679            array_size = self.current_dataset.dxl.size - 1 
     680            self.current_dataset.dxw = np.append(self.current_dataset.dxw, 
     681                                                 np.zeros([array_size])) 
     682        elif not dql_exists and not dqw_exists and not dq_exists: 
     683            array_size = self.current_dataset.x.size - 1 
     684            self.current_dataset.dx = np.append(self.current_dataset.dx, 
     685                                                np.zeros([array_size])) 
     686        if not di_exists: 
     687            array_size = self.current_dataset.y.size - 1 
     688            self.current_dataset.dy = np.append(self.current_dataset.dy, 
     689                                                np.zeros([array_size])) 
     690 
     691    def _initialize_new_data_set(self, node=None): 
     692        if node is not None: 
     693            for child in node: 
     694                if child.tag.replace(self.base_ns, "") == "Idata": 
     695                    for i_child in child: 
     696                        if i_child.tag.replace(self.base_ns, "") == "Qx": 
     697                            self.current_dataset = plottable_2D() 
     698                            return 
     699        self.current_dataset = plottable_1D(np.array(0), np.array(0)) 
     700 
     701    ## Writing Methods 
    886702    def write(self, filename, datainfo): 
    887703        """ 
     
    15141330            exec "storage.%s = entry.text.strip()" % variable 
    15151331 
    1516  
    15171332# DO NOT REMOVE Called by outside packages: 
    15181333#    sas.sasgui.perspectives.invariant.invariant_state 
  • src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py

    rc94280c rdcb91cf  
    1313    TransmissionSpectrum, Detector 
    1414from sas.sascalc.dataloader.data_info import combine_data_info_with_plottable 
    15  
    16  
    17 class Reader(): 
     15from sas.sascalc.dataloader.loader_exceptions import FileContentsException, DefaultReaderException 
     16from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     17 
     18 
     19class Reader(FileReader): 
    1820    """ 
    1921    A class for reading in CanSAS v2.0 data files. The existing iteration opens 
     
    4042    # Raw file contents to be processed 
    4143    raw_data = None 
    42     # Data info currently being read in 
    43     current_datainfo = None 
    44     # SASdata set currently being read in 
    45     current_dataset = None 
    4644    # List of plottable1D objects that should be linked to the current_datainfo 
    4745    data1d = None 
     
    5654    # Flag to bypass extension check 
    5755    allow_all = True 
    58     # List of files to return 
    59     output = None 
    60  
    61     def read(self, filename): 
     56 
     57    def get_file_contents(self): 
    6258        """ 
    6359        This is the general read method that all SasView data_loaders must have. 
     
    6864        # Reinitialize when loading a new data file to reset all class variables 
    6965        self.reset_class_variables() 
     66 
     67        filename = self.f_open.name 
     68        self.f_open.close() # IO handled by h5py 
     69 
    7070        # Check that the file exists 
    7171        if os.path.isfile(filename): 
     
    7575            if extension in self.ext or self.allow_all: 
    7676                # Load the data file 
    77                 self.raw_data = h5py.File(filename, 'r') 
    78                 # Read in all child elements of top level SASroot 
    79                 self.read_children(self.raw_data, []) 
    80                 # Add the last data set to the list of outputs 
    81                 self.add_data_set() 
    82                 # Close the data file 
    83                 self.raw_data.close() 
    84         # Return data set(s) 
    85         return self.output 
     77                try: 
     78                    self.raw_data = h5py.File(filename, 'r') 
     79                except Exception as e: 
     80                    if extension not in self.ext: 
     81                        msg = "CanSAS2.0 HDF5 Reader could not load file {}".format(basename + extension) 
     82                        raise DefaultReaderException(msg) 
     83                    raise FileContentsException(e.message) 
     84                try: 
     85                    # Read in all child elements of top level SASroot 
     86                    self.read_children(self.raw_data, []) 
     87                    # Add the last data set to the list of outputs 
     88                    self.add_data_set() 
     89                except Exception as exc: 
     90                    raise FileContentsException(exc.message) 
     91                finally: 
     92                    # Close the data file 
     93                    self.raw_data.close() 
     94 
     95                for dataset in self.output: 
     96                    if isinstance(dataset, Data1D): 
     97                        if dataset.x.size < 5: 
     98                            self.output = [] 
     99                            raise FileContentsException("Fewer than 5 data points found.") 
    86100 
    87101    def reset_class_variables(self): 
     
    427441        Data1D and Data2D objects 
    428442        """ 
    429  
    430443        # Type cast data arrays to float64 
    431444        if len(self.current_datainfo.trans_spectrum) > 0: 
     
    451464        # Type cast data arrays to float64 and find min/max as appropriate 
    452465        for dataset in self.data2d: 
    453             dataset.data = dataset.data.astype(np.float64) 
    454             dataset.err_data = dataset.err_data.astype(np.float64) 
    455             if dataset.qx_data is not None: 
    456                 dataset.xmin = np.min(dataset.qx_data) 
    457                 dataset.xmax = np.max(dataset.qx_data) 
    458                 dataset.qx_data = dataset.qx_data.astype(np.float64) 
    459             if dataset.dqx_data is not None: 
    460                 dataset.dqx_data = dataset.dqx_data.astype(np.float64) 
    461             if dataset.qy_data is not None: 
    462                 dataset.ymin = np.min(dataset.qy_data) 
    463                 dataset.ymax = np.max(dataset.qy_data) 
    464                 dataset.qy_data = dataset.qy_data.astype(np.float64) 
    465             if dataset.dqy_data is not None: 
    466                 dataset.dqy_data = dataset.dqy_data.astype(np.float64) 
    467             if dataset.q_data is not None: 
    468                 dataset.q_data = dataset.q_data.astype(np.float64) 
    469466            zeros = np.ones(dataset.data.size, dtype=bool) 
    470467            try: 
     
    489486                dataset.x_bins = dataset.qx_data[:n_cols] 
    490487                dataset.data = dataset.data.flatten() 
    491  
    492             final_dataset = combine_data_info_with_plottable( 
    493                 dataset, self.current_datainfo) 
    494             self.output.append(final_dataset) 
     488            self.current_dataset = dataset 
     489            self.send_to_output() 
    495490 
    496491        for dataset in self.data1d: 
    497             if dataset.x is not None: 
    498                 dataset.x = dataset.x.astype(np.float64) 
    499                 dataset.xmin = np.min(dataset.x) 
    500                 dataset.xmax = np.max(dataset.x) 
    501             if dataset.y is not None: 
    502                 dataset.y = dataset.y.astype(np.float64) 
    503                 dataset.ymin = np.min(dataset.y) 
    504                 dataset.ymax = np.max(dataset.y) 
    505             if dataset.dx is not None: 
    506                 dataset.dx = dataset.dx.astype(np.float64) 
    507             if dataset.dxl is not None: 
    508                 dataset.dxl = dataset.dxl.astype(np.float64) 
    509             if dataset.dxw is not None: 
    510                 dataset.dxw = dataset.dxw.astype(np.float64) 
    511             if dataset.dy is not None: 
    512                 dataset.dy = dataset.dy.astype(np.float64) 
    513             final_dataset = combine_data_info_with_plottable( 
    514                 dataset, self.current_datainfo) 
    515             self.output.append(final_dataset) 
     492            self.current_dataset = dataset 
     493            self.send_to_output() 
    516494 
    517495    def add_data_set(self, key=""): 
  • src/sas/sascalc/dataloader/readers/danse_reader.py

    r235f514 r713a047  
    55#This software was developed by the University of Tennessee as part of the 
    66#Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    7 #project funded by the US National Science Foundation.  
     7#project funded by the US National Science Foundation. 
    88#If you use DANSE applications to do scientific research that leads to 
    99#publication, we ask that you acknowledge the use of the software with the 
     
    1414import math 
    1515import os 
    16 import sys 
    1716import numpy as np 
    1817import logging 
    19 from sas.sascalc.dataloader.data_info import Data2D, Detector 
     18from sas.sascalc.dataloader.data_info import plottable_2D, DataInfo, Detector 
    2019from sas.sascalc.dataloader.manipulations import reader2D_converter 
     20from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     21from sas.sascalc.dataloader.loader_exceptions import FileContentsException, DataReaderException 
    2122 
    2223logger = logging.getLogger(__name__) 
     
    3031 
    3132 
    32 class Reader: 
     33class Reader(FileReader): 
    3334    """ 
    3435    Example data manipulation 
     
    4041    ## Extension 
    4142    ext  = ['.sans', '.SANS'] 
    42          
    43     def read(self, filename=None): 
    44         """ 
    45         Open and read the data in a file 
    46         @param file: path of the file 
    47         """ 
    48          
    49         read_it = False 
    50         for item in self.ext: 
    51             if filename.lower().find(item) >= 0: 
    52                 read_it = True 
    53                  
    54         if read_it: 
     43 
     44    def get_file_contents(self): 
     45        self.current_datainfo = DataInfo() 
     46        self.current_dataset = plottable_2D() 
     47        self.output = [] 
     48 
     49        loaded_correctly = True 
     50        error_message = "" 
     51 
     52        # defaults 
     53        # wavelength in Angstrom 
     54        wavelength = 10.0 
     55        # Distance in meter 
     56        distance   = 11.0 
     57        # Pixel number of center in x 
     58        center_x   = 65 
     59        # Pixel number of center in y 
     60        center_y   = 65 
     61        # Pixel size [mm] 
     62        pixel      = 5.0 
     63        # Size in x, in pixels 
     64        size_x     = 128 
     65        # Size in y, in pixels 
     66        size_y     = 128 
     67        # Format version 
     68        fversion   = 1.0 
     69 
     70        self.current_datainfo.filename = os.path.basename(self.f_open.name) 
     71        detector = Detector() 
     72        self.current_datainfo.detector.append(detector) 
     73 
     74        self.current_dataset.data = np.zeros([size_x, size_y]) 
     75        self.current_dataset.err_data = np.zeros([size_x, size_y]) 
     76 
     77        read_on = True 
     78        data_start_line = 1 
     79        while read_on: 
     80            line = self.f_open.readline() 
     81            data_start_line += 1 
     82            if line.find("DATA:") >= 0: 
     83                read_on = False 
     84                break 
     85            toks = line.split(':') 
    5586            try: 
    56                 datafile = open(filename, 'r') 
    57             except: 
    58                 raise  RuntimeError,"danse_reader cannot open %s" % (filename) 
    59          
    60             # defaults 
    61             # wavelength in Angstrom 
    62             wavelength = 10.0 
    63             # Distance in meter 
    64             distance   = 11.0 
    65             # Pixel number of center in x 
    66             center_x   = 65 
    67             # Pixel number of center in y 
    68             center_y   = 65 
    69             # Pixel size [mm] 
    70             pixel      = 5.0 
    71             # Size in x, in pixels 
    72             size_x     = 128 
    73             # Size in y, in pixels 
    74             size_y     = 128 
    75             # Format version 
    76             fversion   = 1.0 
    77              
    78             output = Data2D() 
    79             output.filename = os.path.basename(filename) 
    80             detector = Detector() 
    81             output.detector.append(detector) 
    82              
    83             output.data = np.zeros([size_x,size_y]) 
    84             output.err_data = np.zeros([size_x, size_y]) 
    85              
    86             data_conv_q = None 
    87             data_conv_i = None 
    88              
    89             if has_converter == True and output.Q_unit != '1/A': 
    90                 data_conv_q = Converter('1/A') 
    91                 # Test it 
    92                 data_conv_q(1.0, output.Q_unit) 
    93                  
    94             if has_converter == True and output.I_unit != '1/cm': 
    95                 data_conv_i = Converter('1/cm') 
    96                 # Test it 
    97                 data_conv_i(1.0, output.I_unit) 
    98          
    99             read_on = True 
    100             while read_on: 
    101                 line = datafile.readline() 
    102                 if line.find("DATA:") >= 0: 
    103                     read_on = False 
    104                     break 
    105                 toks = line.split(':') 
    10687                if toks[0] == "FORMATVERSION": 
    10788                    fversion = float(toks[1]) 
    108                 if toks[0] == "WAVELENGTH": 
     89                elif toks[0] == "WAVELENGTH": 
    10990                    wavelength = float(toks[1]) 
    11091                elif toks[0] == "DISTANCE": 
     
    120101                elif toks[0] == "SIZE_Y": 
    121102                    size_y = int(toks[1]) 
    122              
    123             # Read the data 
    124             data = [] 
    125             error = [] 
    126             if fversion == 1.0: 
    127                 data_str = datafile.readline() 
    128                 data = data_str.split(' ') 
    129             else: 
    130                 read_on = True 
    131                 while read_on: 
    132                     data_str = datafile.readline() 
    133                     if len(data_str) == 0: 
    134                         read_on = False 
    135                     else: 
    136                         toks = data_str.split() 
    137                         try: 
    138                             val = float(toks[0]) 
    139                             err = float(toks[1]) 
    140                             if data_conv_i is not None: 
    141                                 val = data_conv_i(val, units=output._yunit) 
    142                                 err = data_conv_i(err, units=output._yunit) 
    143                             data.append(val) 
    144                             error.append(err) 
    145                         except: 
    146                             logger.info("Skipping line:%s,%s" %(data_str, 
    147                                                                 sys.exc_value)) 
    148              
    149             # Initialize 
    150             x_vals = [] 
    151             y_vals = [] 
    152             ymin = None 
    153             ymax = None 
    154             xmin = None 
    155             xmax = None 
    156              
    157             # Qx and Qy vectors 
    158             theta = pixel / distance / 100.0 
    159             stepq = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) 
    160             for i_x in range(size_x): 
    161                 theta = (i_x - center_x + 1) * pixel / distance / 100.0 
    162                 qx = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) 
    163                  
    164                 if has_converter == True and output.Q_unit != '1/A': 
    165                     qx = data_conv_q(qx, units=output.Q_unit) 
    166                  
    167                 x_vals.append(qx) 
    168                 if xmin is None or qx < xmin: 
    169                     xmin = qx 
    170                 if xmax is None or qx > xmax: 
    171                     xmax = qx 
    172              
    173             ymin = None 
    174             ymax = None 
    175             for i_y in range(size_y): 
    176                 theta = (i_y - center_y + 1) * pixel / distance / 100.0 
    177                 qy = 4.0 * math.pi / wavelength * math.sin(theta/2.0) 
    178                  
    179                 if has_converter == True and output.Q_unit != '1/A': 
    180                     qy = data_conv_q(qy, units=output.Q_unit) 
    181                  
    182                 y_vals.append(qy) 
    183                 if ymin is None or qy < ymin: 
    184                     ymin = qy 
    185                 if ymax is None or qy > ymax: 
    186                     ymax = qy 
    187              
    188             # Store the data in the 2D array 
    189             i_x = 0 
    190             i_y = -1 
    191              
    192             for i_pt in range(len(data)): 
    193                 try: 
    194                     value = float(data[i_pt]) 
    195                 except: 
    196                     # For version 1.0, the data were still 
    197                     # stored as strings at this point. 
    198                     msg = "Skipping entry (v1.0):%s,%s" % (str(data[i_pt]), 
    199                                                            sys.exc_value) 
    200                     logger.info(msg) 
    201                  
    202                 # Get bin number 
    203                 if math.fmod(i_pt, size_x) == 0: 
    204                     i_x = 0 
    205                     i_y += 1 
    206                 else: 
    207                     i_x += 1 
    208                      
    209                 output.data[i_y][i_x] = value 
    210                 if fversion>1.0: 
    211                     output.err_data[i_y][i_x] = error[i_pt] 
    212                  
    213             # Store all data 
    214             # Store wavelength 
    215             if has_converter == True and output.source.wavelength_unit != 'A': 
    216                 conv = Converter('A') 
    217                 wavelength = conv(wavelength, 
    218                                   units=output.source.wavelength_unit) 
    219             output.source.wavelength = wavelength 
    220                  
    221             # Store distance 
    222             if has_converter == True and detector.distance_unit != 'm': 
    223                 conv = Converter('m') 
    224                 distance = conv(distance, units=detector.distance_unit) 
    225             detector.distance = distance 
    226              
    227             # Store pixel size 
    228             if has_converter == True and detector.pixel_size_unit != 'mm': 
    229                 conv = Converter('mm') 
    230                 pixel = conv(pixel, units=detector.pixel_size_unit) 
    231             detector.pixel_size.x = pixel 
    232             detector.pixel_size.y = pixel 
    233  
    234             # Store beam center in distance units 
    235             detector.beam_center.x = center_x * pixel 
    236             detector.beam_center.y = center_y * pixel 
    237              
    238             # Store limits of the image (2D array) 
    239             xmin = xmin - stepq / 2.0 
    240             xmax = xmax + stepq / 2.0 
    241             ymin = ymin - stepq /2.0 
    242             ymax = ymax + stepq / 2.0 
    243              
    244             if has_converter == True and output.Q_unit != '1/A': 
    245                 xmin = data_conv_q(xmin, units=output.Q_unit) 
    246                 xmax = data_conv_q(xmax, units=output.Q_unit) 
    247                 ymin = data_conv_q(ymin, units=output.Q_unit) 
    248                 ymax = data_conv_q(ymax, units=output.Q_unit) 
    249             output.xmin = xmin 
    250             output.xmax = xmax 
    251             output.ymin = ymin 
    252             output.ymax = ymax 
    253              
    254             # Store x and y axis bin centers 
    255             output.x_bins = x_vals 
    256             output.y_bins = y_vals 
    257             
    258             # Units 
    259             if data_conv_q is not None: 
    260                 output.xaxis("\\rm{Q_{x}}", output.Q_unit) 
    261                 output.yaxis("\\rm{Q_{y}}", output.Q_unit) 
    262             else: 
    263                 output.xaxis("\\rm{Q_{x}}", 'A^{-1}') 
    264                 output.yaxis("\\rm{Q_{y}}", 'A^{-1}') 
    265                  
    266             if data_conv_i is not None: 
    267                 output.zaxis("\\rm{Intensity}", output.I_unit) 
    268             else: 
    269                 output.zaxis("\\rm{Intensity}", "cm^{-1}") 
    270             
    271             if not fversion >= 1.0: 
    272                 msg = "Danse_reader can't read this file %s" % filename 
    273                 raise ValueError, msg 
    274             else: 
    275                 logger.info("Danse_reader Reading %s \n" % filename) 
    276              
    277             # Store loading process information 
    278             output.meta_data['loader'] = self.type_name 
    279             output = reader2D_converter(output) 
    280             return output 
    281          
    282         return None 
     103            except ValueError as e: 
     104                error_message += "Unable to parse {}. Default value used.\n".format(toks[0]) 
     105                loaded_correctly = False 
     106 
     107        # Read the data 
     108        data = [] 
     109        error = [] 
     110        if not fversion >= 1.0: 
     111            msg = "danse_reader can't read this file {}".format(self.f_open.name) 
     112            raise FileContentsException(msg) 
     113 
     114        for line_num, data_str in enumerate(self.f_open.readlines()): 
     115            toks = data_str.split() 
     116            try: 
     117                val = float(toks[0]) 
     118                err = float(toks[1]) 
     119                data.append(val) 
     120                error.append(err) 
     121            except ValueError as exc: 
     122                msg = "Unable to parse line {}: {}".format(line_num + data_start_line, data_str.strip()) 
     123                raise FileContentsException(msg) 
     124 
     125        num_pts = size_x * size_y 
     126        if len(data) < num_pts: 
     127            msg = "Not enough data points provided. Expected {} but got {}".format( 
     128                size_x * size_y, len(data)) 
     129            raise FileContentsException(msg) 
     130        elif len(data) > num_pts: 
     131            error_message += ("Too many data points provided. Expected {0} but" 
     132                " got {1}. Only the first {0} will be used.\n").format(num_pts, len(data)) 
     133            loaded_correctly = False 
     134            data = data[:num_pts] 
     135            error = error[:num_pts] 
     136 
     137        # Qx and Qy vectors 
     138        theta = pixel / distance / 100.0 
     139        i_x = np.arange(size_x) 
     140        theta = (i_x - center_x + 1) * pixel / distance / 100.0 
     141        x_vals = 4.0 * np.pi / wavelength * np.sin(theta / 2.0) 
     142        xmin = x_vals.min() 
     143        xmax = x_vals.max() 
     144 
     145        i_y = np.arange(size_y) 
     146        theta = (i_y - center_y + 1) * pixel / distance / 100.0 
     147        y_vals = 4.0 * np.pi / wavelength * np.sin(theta / 2.0) 
     148        ymin = y_vals.min() 
     149        ymax = y_vals.max() 
     150 
     151        self.current_dataset.data = np.array(data, dtype=np.float64).reshape((size_y, size_x)) 
     152        if fversion > 1.0: 
     153            self.current_dataset.err_data = np.array(error, dtype=np.float64).reshape((size_y, size_x)) 
     154 
     155        # Store all data 
     156        # Store wavelength 
     157        if has_converter == True and self.current_datainfo.source.wavelength_unit != 'A': 
     158            conv = Converter('A') 
     159            wavelength = conv(wavelength, 
     160                              units=self.current_datainfo.source.wavelength_unit) 
     161        self.current_datainfo.source.wavelength = wavelength 
     162 
     163        # Store distance 
     164        if has_converter == True and detector.distance_unit != 'm': 
     165            conv = Converter('m') 
     166            distance = conv(distance, units=detector.distance_unit) 
     167        detector.distance = distance 
     168 
     169        # Store pixel size 
     170        if has_converter == True and detector.pixel_size_unit != 'mm': 
     171            conv = Converter('mm') 
     172            pixel = conv(pixel, units=detector.pixel_size_unit) 
     173        detector.pixel_size.x = pixel 
     174        detector.pixel_size.y = pixel 
     175 
     176        # Store beam center in distance units 
     177        detector.beam_center.x = center_x * pixel 
     178        detector.beam_center.y = center_y * pixel 
     179 
     180 
     181        self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}') 
     182        self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}') 
     183        self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}") 
     184 
     185        self.current_dataset.x_bins = x_vals 
     186        self.current_dataset.y_bins = y_vals 
     187 
     188        # Reshape data 
     189        x_vals = np.tile(x_vals, (size_y, 1)).flatten() 
     190        y_vals = np.tile(y_vals, (size_x, 1)).T.flatten() 
     191        if self.current_dataset.err_data == np.all(np.array(None)) or np.any(self.current_dataset.err_data <= 0): 
     192            new_err_data = np.sqrt(np.abs(self.current_dataset.data)) 
     193        else: 
     194            new_err_data = self.current_dataset.err_data.flatten() 
     195 
     196        self.current_dataset.err_data = new_err_data 
     197        self.current_dataset.qx_data = x_vals 
     198        self.current_dataset.qy_data = y_vals 
     199        self.current_dataset.q_data = np.sqrt(x_vals**2 + y_vals**2) 
     200        self.current_dataset.mask = np.ones(len(x_vals), dtype=bool) 
     201 
     202        # Store loading process information 
     203        self.current_datainfo.meta_data['loader'] = self.type_name 
     204 
     205        self.send_to_output() 
     206 
     207        if not loaded_correctly: 
     208            raise DataReaderException(error_message) 
  • src/sas/sascalc/dataloader/readers/red2d_reader.py

    ra1b8fee r2f85af7  
    55#This software was developed by the University of Tennessee as part of the 
    66#Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    7 #project funded by the US National Science Foundation.  
     7#project funded by the US National Science Foundation. 
    88#See the license text in license.txt 
    99#copyright 2008, University of Tennessee 
    1010###################################################################### 
    11 from __future__ import print_function 
    12  
    1311import os 
    1412import numpy as np 
    1513import math 
    16 from sas.sascalc.dataloader.data_info import Data2D, Detector 
     14from sas.sascalc.dataloader.data_info import plottable_2D, DataInfo, Detector 
     15from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     16from sas.sascalc.dataloader.loader_exceptions import FileContentsException 
    1717 
    1818# Look for unit converter 
     
    2222except: 
    2323    has_converter = False 
    24      
    25      
     24 
     25 
    2626def check_point(x_point): 
    2727    """ 
     
    3333    except: 
    3434        return 0 
    35        
    36          
    37 class Reader: 
     35 
     36 
     37class Reader(FileReader): 
    3838    """ Simple data reader for Igor data files """ 
    3939    ## File type 
     
    4343    ## Extension 
    4444    ext = ['.DAT', '.dat'] 
    45      
     45 
    4646    def write(self, filename, data): 
    4747        """ 
    4848        Write to .dat 
    49          
     49 
    5050        :param filename: file name to write 
    5151        :param data: data2D 
     
    5353        import time 
    5454        # Write the file 
    55         fd = open(filename, 'w') 
    56         t = time.localtime() 
    57         time_str = time.strftime("%H:%M on %b %d %y", t) 
    58          
    59         header_str = "Data columns are Qx - Qy - I(Qx,Qy)\n\nASCII data" 
    60         header_str += " created at %s \n\n" % time_str 
    61         # simple 2D header 
    62         fd.write(header_str) 
    63         # write qx qy I values 
    64         for i in range(len(data.data)): 
    65             fd.write("%g  %g  %g\n" % (data.qx_data[i], 
    66                                         data.qy_data[i], 
    67                                        data.data[i])) 
    68         # close 
    69         fd.close() 
    70  
    71     def read(self, filename=None): 
    72         """ Read file """ 
    73         if not os.path.isfile(filename): 
    74             raise ValueError, \ 
    75             "Specified file %s is not a regular file" % filename 
    76  
     55        try: 
     56            fd = open(filename, 'w') 
     57            t = time.localtime() 
     58            time_str = time.strftime("%H:%M on %b %d %y", t) 
     59 
     60            header_str = "Data columns are Qx - Qy - I(Qx,Qy)\n\nASCII data" 
     61            header_str += " created at %s \n\n" % time_str 
     62            # simple 2D header 
     63            fd.write(header_str) 
     64            # write qx qy I values 
     65            for i in range(len(data.data)): 
     66                fd.write("%g  %g  %g\n" % (data.qx_data[i], 
     67                                            data.qy_data[i], 
     68                                           data.data[i])) 
     69        finally: 
     70            fd.close() 
     71 
     72    def get_file_contents(self): 
    7773        # Read file 
    78         f = open(filename, 'r') 
    79         buf = f.read() 
    80         f.close() 
     74        buf = self.f_open.read() 
     75        self.f_open.close() 
    8176        # Instantiate data object 
    82         output = Data2D() 
    83         output.filename = os.path.basename(filename) 
    84         detector = Detector() 
    85         if len(output.detector) > 0: 
    86             print(str(output.detector[0])) 
    87         output.detector.append(detector) 
    88                  
     77        self.current_dataset = plottable_2D() 
     78        self.current_datainfo = DataInfo() 
     79        self.current_datainfo.filename = os.path.basename(self.f_open.name) 
     80        self.current_datainfo.detector.append(Detector()) 
     81 
    8982        # Get content 
    90         dataStarted = False 
    91          
     83        data_started = False 
     84 
    9285        ## Defaults 
    9386        lines = buf.split('\n') 
    9487        x = [] 
    9588        y = [] 
    96          
     89 
    9790        wavelength = None 
    9891        distance = None 
    9992        transmission = None 
    100          
     93 
    10194        pixel_x = None 
    10295        pixel_y = None 
    103          
    104         isInfo = False 
    105         isCenter = False 
    106  
    107         data_conv_q = None 
    108         data_conv_i = None 
    109          
    110         # Set units: This is the unit assumed for Q and I in the data file. 
    111         if has_converter == True and output.Q_unit != '1/A': 
    112             data_conv_q = Converter('1/A') 
    113             # Test it 
    114             data_conv_q(1.0, output.Q_unit) 
    115              
    116         if has_converter == True and output.I_unit != '1/cm': 
    117             data_conv_i = Converter('1/cm') 
    118             # Test it 
    119             data_conv_i(1.0, output.I_unit) 
    120          
    121                
     96 
     97        is_info = False 
     98        is_center = False 
     99 
    122100        # Remove the last lines before the for loop if the lines are empty 
    123101        # to calculate the exact number of data points 
     
    135113            ## Reading the header applies only to IGOR/NIST 2D q_map data files 
    136114            # Find setup info line 
    137             if isInfo: 
    138                 isInfo = False 
     115            if is_info: 
     116                is_info = False 
    139117                line_toks = line.split() 
    140118                # Wavelength in Angstrom 
     
    143121                    # Units 
    144122                    if has_converter == True and \ 
    145                     output.source.wavelength_unit != 'A': 
     123                    self.current_datainfo.source.wavelength_unit != 'A': 
    146124                        conv = Converter('A') 
    147125                        wavelength = conv(wavelength, 
    148                                           units=output.source.wavelength_unit) 
     126                                          units=self.current_datainfo.source.wavelength_unit) 
    149127                except: 
    150128                    #Not required 
     
    154132                    distance = float(line_toks[3]) 
    155133                    # Units 
    156                     if has_converter == True and detector.distance_unit != 'm': 
     134                    if has_converter == True and self.current_datainfo.detector[0].distance_unit != 'm': 
    157135                        conv = Converter('m') 
    158                         distance = conv(distance, units=detector.distance_unit) 
     136                        distance = conv(distance, 
     137                            units=self.current_datainfo.detector[0].distance_unit) 
    159138                except: 
    160139                    #Not required 
    161140                    pass 
    162                  
     141 
    163142                # Distance in meters 
    164143                try: 
     
    167146                    #Not required 
    168147                    pass 
    169                                              
     148 
    170149            if line.count("LAMBDA") > 0: 
    171                 isInfo = True 
    172                  
     150                is_info = True 
     151 
    173152            # Find center info line 
    174             if isCenter: 
    175                 isCenter = False 
     153            if is_center: 
     154                is_center = False 
    176155                line_toks = line.split() 
    177156                # Center in bin number 
     
    180159 
    181160            if line.count("BCENT") > 0: 
    182                 isCenter = True 
     161                is_center = True 
    183162            # Check version 
    184163            if line.count("Data columns") > 0: 
     
    187166            # Find data start 
    188167            if line.count("ASCII data") > 0: 
    189                 dataStarted = True 
     168                data_started = True 
    190169                continue 
    191170 
    192171            ## Read and get data. 
    193             if dataStarted == True: 
     172            if data_started == True: 
    194173                line_toks = line.split() 
    195174                if len(line_toks) == 0: 
    196175                    #empty line 
    197176                    continue 
    198                 # the number of columns must be stayed same  
     177                # the number of columns must be stayed same 
    199178                col_num = len(line_toks) 
    200179                break 
     
    204183        # index for lines_array 
    205184        lines_index = np.arange(len(lines)) 
    206          
     185 
    207186        # get the data lines 
    208187        data_lines = lines_array[lines_index >= (line_num - 1)] 
     
    213192        # split all data to one big list w/" "separator 
    214193        data_list = data_list.split() 
    215   
     194 
    216195        # Check if the size is consistent with data, otherwise 
    217196        #try the tab(\t) separator 
     
    233212            data_point = data_array.reshape(row_num, col_num).transpose() 
    234213        except: 
    235             msg = "red2d_reader: Can't read this file: Not a proper file format" 
    236             raise ValueError, msg 
     214            msg = "red2d_reader can't read this file: Incorrect number of data points provided." 
     215            raise FileContentsException(msg) 
    237216        ## Get the all data: Let's HARDcoding; Todo find better way 
    238217        # Defaults 
     
    257236        #if col_num > (6 + ver): mask[data_point[(6 + ver)] < 1] = False 
    258237        q_data = np.sqrt(qx_data*qx_data+qy_data*qy_data+qz_data*qz_data) 
    259             
    260         # Extra protection(it is needed for some data files):  
     238 
     239        # Extra protection(it is needed for some data files): 
    261240        # If all mask elements are False, put all True 
    262241        if not mask.any(): 
    263242            mask[mask == False] = True 
    264    
     243 
    265244        # Store limits of the image in q space 
    266245        xmin = np.min(qx_data) 
     
    269248        ymax = np.max(qy_data) 
    270249 
    271         # units 
    272         if has_converter == True and output.Q_unit != '1/A': 
    273             xmin = data_conv_q(xmin, units=output.Q_unit) 
    274             xmax = data_conv_q(xmax, units=output.Q_unit) 
    275             ymin = data_conv_q(ymin, units=output.Q_unit) 
    276             ymax = data_conv_q(ymax, units=output.Q_unit) 
    277              
    278250        ## calculate the range of the qx and qy_data 
    279251        x_size = math.fabs(xmax - xmin) 
    280252        y_size = math.fabs(ymax - ymin) 
    281          
     253 
    282254        # calculate the number of pixels in the each axes 
    283255        npix_y = math.floor(math.sqrt(len(data))) 
    284256        npix_x = math.floor(len(data) / npix_y) 
    285          
     257 
    286258        # calculate the size of bins 
    287259        xstep = x_size / (npix_x - 1) 
    288260        ystep = y_size / (npix_y - 1) 
    289          
     261 
    290262        # store x and y axis bin centers in q space 
    291263        x_bins = np.arange(xmin, xmax + xstep, xstep) 
    292264        y_bins = np.arange(ymin, ymax + ystep, ystep) 
    293         
     265 
    294266        # get the limits of q values 
    295267        xmin = xmin - xstep / 2 
     
    297269        ymin = ymin - ystep / 2 
    298270        ymax = ymax + ystep / 2 
    299          
     271 
    300272        #Store data in outputs 
    301273        #TODO: Check the lengths 
    302         output.data = data 
     274        self.current_dataset.data = data 
    303275        if (err_data == 1).all(): 
    304             output.err_data = np.sqrt(np.abs(data)) 
    305             output.err_data[output.err_data == 0.0] = 1.0 
     276            self.current_dataset.err_data = np.sqrt(np.abs(data)) 
     277            self.current_dataset.err_data[self.current_dataset.err_data == 0.0] = 1.0 
    306278        else: 
    307             output.err_data = err_data 
    308              
    309         output.qx_data = qx_data 
    310         output.qy_data = qy_data 
    311         output.q_data = q_data 
    312         output.mask = mask 
    313          
    314         output.x_bins = x_bins 
    315         output.y_bins = y_bins 
    316                 
    317         output.xmin = xmin 
    318         output.xmax = xmax 
    319         output.ymin = ymin 
    320         output.ymax = ymax 
    321          
    322         output.source.wavelength = wavelength 
    323          
     279            self.current_dataset.err_data = err_data 
     280 
     281        self.current_dataset.qx_data = qx_data 
     282        self.current_dataset.qy_data = qy_data 
     283        self.current_dataset.q_data = q_data 
     284        self.current_dataset.mask = mask 
     285 
     286        self.current_dataset.x_bins = x_bins 
     287        self.current_dataset.y_bins = y_bins 
     288 
     289        self.current_dataset.xmin = xmin 
     290        self.current_dataset.xmax = xmax 
     291        self.current_dataset.ymin = ymin 
     292        self.current_dataset.ymax = ymax 
     293 
     294        self.current_datainfo.source.wavelength = wavelength 
     295 
    324296        # Store pixel size in mm 
    325         detector.pixel_size.x = pixel_x 
    326         detector.pixel_size.y = pixel_y 
    327          
     297        self.current_datainfo.detector[0].pixel_size.x = pixel_x 
     298        self.current_datainfo.detector[0].pixel_size.y = pixel_y 
     299 
    328300        # Store the sample to detector distance 
    329         detector.distance = distance 
    330          
     301        self.current_datainfo.detector[0].distance = distance 
     302 
    331303        # optional data: if all of dq data == 0, do not pass to output 
    332304        if len(dqx_data) == len(qx_data) and dqx_data.any() != 0: 
     
    340312                    cos_th = qx_data / diag 
    341313                    sin_th = qy_data / diag 
    342                     output.dqx_data = np.sqrt((dqx_data * cos_th) * \ 
     314                    self.current_dataset.dqx_data = np.sqrt((dqx_data * cos_th) * \ 
    343315                                                 (dqx_data * cos_th) \ 
    344316                                                 + (dqy_data * sin_th) * \ 
    345317                                                  (dqy_data * sin_th)) 
    346                     output.dqy_data = np.sqrt((dqx_data * sin_th) * \ 
     318                    self.current_dataset.dqy_data = np.sqrt((dqx_data * sin_th) * \ 
    347319                                                 (dqx_data * sin_th) \ 
    348320                                                 + (dqy_data * cos_th) * \ 
    349321                                                  (dqy_data * cos_th)) 
    350322                else: 
    351                     output.dqx_data = dqx_data 
    352                     output.dqy_data = dqy_data 
     323                    self.current_dataset.dqx_data = dqx_data 
     324                    self.current_dataset.dqy_data = dqy_data 
    353325 
    354326        # Units of axes 
    355         if data_conv_q is not None: 
    356             output.xaxis("\\rm{Q_{x}}", output.Q_unit) 
    357             output.yaxis("\\rm{Q_{y}}", output.Q_unit) 
    358         else: 
    359             output.xaxis("\\rm{Q_{x}}", 'A^{-1}') 
    360             output.yaxis("\\rm{Q_{y}}", 'A^{-1}') 
    361         if data_conv_i is not None: 
    362             output.zaxis("\\rm{Intensity}", output.I_unit) 
    363         else: 
    364             output.zaxis("\\rm{Intensity}", "cm^{-1}") 
    365      
     327        self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}') 
     328        self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}') 
     329        self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}") 
     330 
    366331        # Store loading process information 
    367         output.meta_data['loader'] = self.type_name 
    368  
    369         return output 
     332        self.current_datainfo.meta_data['loader'] = self.type_name 
     333 
     334        self.send_to_output() 
  • src/sas/sascalc/dataloader/readers/sesans_reader.py

    r149b8f6 rbe43448  
    88import numpy as np 
    99import os 
    10 from sas.sascalc.dataloader.data_info import Data1D 
     10from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     11from sas.sascalc.dataloader.data_info import plottable_1D, DataInfo 
     12from sas.sascalc.dataloader.loader_exceptions import FileContentsException, DataReaderException 
    1113 
    1214# Check whether we have a converter available 
     
    1820_ZERO = 1e-16 
    1921 
    20  
    21 class Reader: 
     22class Reader(FileReader): 
    2223    """ 
    2324    Class to load sesans files (6 columns). 
     
    2627    type_name = "SESANS" 
    2728 
    28     # Wildcards 
     29    ## Wildcards 
    2930    type = ["SESANS files (*.ses)|*.ses", 
    3031            "SESANS files (*..sesans)|*.sesans"] 
     
    3536    allow_all = True 
    3637 
    37     def read(self, path): 
    38         """ 
    39         Load data file 
     38    def get_file_contents(self): 
     39        self.current_datainfo = DataInfo() 
     40        self.current_dataset = plottable_1D(np.array([]), np.array([])) 
     41        self.current_datainfo.isSesans = True 
     42        self.output = [] 
    4043 
    41         :param path: file path 
     44        line = self.f_open.readline() 
     45        params = {} 
     46        while not line.startswith("BEGIN_DATA"): 
     47            terms = line.split() 
     48            if len(terms) >= 2: 
     49                params[terms[0]] = " ".join(terms[1:]) 
     50            line = self.f_open.readline() 
     51        self.params = params 
    4252 
    43         :return: SESANSData1D object, or None 
     53        if "FileFormatVersion" not in self.params: 
     54            raise FileContentsException("SES file missing FileFormatVersion") 
     55        if float(self.params["FileFormatVersion"]) >= 2.0: 
     56            raise FileContentsException("SASView only supports SES version 1") 
    4457 
    45         :raise RuntimeError: when the file can't be opened 
    46         :raise ValueError: when the length of the data vectors are inconsistent 
    47         """ 
    48         if os.path.isfile(path): 
    49             basename = os.path.basename(path) 
    50             _, extension = os.path.splitext(basename) 
    51             if not (self.allow_all or extension.lower() in self.ext): 
    52                 raise RuntimeError( 
    53                     "{} has an unrecognized file extension".format(path)) 
     58        if "SpinEchoLength_unit" not in self.params: 
     59            raise FileContentsException("SpinEchoLength has no units") 
     60        if "Wavelength_unit" not in self.params: 
     61            raise FileContentsException("Wavelength has no units") 
     62        if params["SpinEchoLength_unit"] != params["Wavelength_unit"]: 
     63            raise FileContentsException("The spin echo data has rudely used " 
     64                               "different units for the spin echo length " 
     65                               "and the wavelength.  While sasview could " 
     66                               "handle this instance, it is a violation " 
     67                               "of the file format and will not be " 
     68                               "handled by other software.") 
     69 
     70        headers = self.f_open.readline().split() 
     71 
     72        self._insist_header(headers, "SpinEchoLength") 
     73        self._insist_header(headers, "Depolarisation") 
     74        self._insist_header(headers, "Depolarisation_error") 
     75        self._insist_header(headers, "Wavelength") 
     76 
     77        data = np.loadtxt(self.f_open) 
     78 
     79        if data.shape[1] != len(headers): 
     80            raise FileContentsException( 
     81                "File has {} headers, but {} columns".format( 
     82                    len(headers), 
     83                    data.shape[1])) 
     84 
     85        if not data.size: 
     86            raise FileContentsException("{} is empty".format(path)) 
     87        x = data[:, headers.index("SpinEchoLength")] 
     88        if "SpinEchoLength_error" in headers: 
     89            dx = data[:, headers.index("SpinEchoLength_error")] 
    5490        else: 
    55             raise RuntimeError("{} is not a file".format(path)) 
    56         with open(path, 'r') as input_f: 
    57             line = input_f.readline() 
    58             params = {} 
    59             while not line.startswith("BEGIN_DATA"): 
    60                 terms = line.split() 
    61                 if len(terms) >= 2: 
    62                     params[terms[0]] = " ".join(terms[1:]) 
    63                 line = input_f.readline() 
    64             self.params = params 
     91            dx = x * 0.05 
     92        lam = data[:, headers.index("Wavelength")] 
     93        if "Wavelength_error" in headers: 
     94            dlam = data[:, headers.index("Wavelength_error")] 
     95        else: 
     96            dlam = lam * 0.05 
     97        y = data[:, headers.index("Depolarisation")] 
     98        dy = data[:, headers.index("Depolarisation_error")] 
    6599 
    66             if "FileFormatVersion" not in self.params: 
    67                 raise RuntimeError("SES file missing FileFormatVersion") 
    68             if float(self.params["FileFormatVersion"]) >= 2.0: 
    69                 raise RuntimeError("SASView only supports SES version 1") 
     100        lam_unit = self._unit_fetch("Wavelength") 
     101        x, x_unit = self._unit_conversion(x, "A", 
     102                                          self._unit_fetch( 
     103                                              "SpinEchoLength")) 
     104        dx, dx_unit = self._unit_conversion( 
     105            dx, lam_unit, 
     106            self._unit_fetch("SpinEchoLength")) 
     107        dlam, dlam_unit = self._unit_conversion( 
     108            dlam, lam_unit, 
     109            self._unit_fetch("Wavelength")) 
     110        y_unit = self._unit_fetch("Depolarisation") 
    70111 
    71             if "SpinEchoLength_unit" not in self.params: 
    72                 raise RuntimeError("SpinEchoLength has no units") 
    73             if "Wavelength_unit" not in self.params: 
    74                 raise RuntimeError("Wavelength has no units") 
    75             if params["SpinEchoLength_unit"] != params["Wavelength_unit"]: 
    76                 raise RuntimeError("The spin echo data has rudely used " 
    77                                    "different units for the spin echo length " 
    78                                    "and the wavelength.  While sasview could " 
    79                                    "handle this instance, it is a violation " 
    80                                    "of the file format and will not be " 
    81                                    "handled by other software.") 
     112        self.current_dataset.x = x 
     113        self.current_dataset.y = y 
     114        self.current_dataset.lam = lam 
     115        self.current_dataset.dy = dy 
     116        self.current_dataset.dx = dx 
     117        self.current_dataset.dlam = dlam 
     118        self.current_datainfo.isSesans = True 
    82119 
    83             headers = input_f.readline().split() 
     120        self.current_datainfo._yunit = y_unit 
     121        self.current_datainfo._xunit = x_unit 
     122        self.current_datainfo.source.wavelength_unit = lam_unit 
     123        self.current_datainfo.source.wavelength = lam 
     124        self.current_datainfo.filename = os.path.basename(self.f_open.name) 
     125        self.current_dataset.xaxis(r"\rm{z}", x_unit) 
     126        # Adjust label to ln P/(lam^2 t), remove lam column refs 
     127        self.current_dataset.yaxis(r"\rm{ln(P)/(t \lambda^2)}", y_unit) 
     128        # Store loading process information 
     129        self.current_datainfo.meta_data['loader'] = self.type_name 
     130        self.current_datainfo.sample.name = params["Sample"] 
     131        self.current_datainfo.sample.ID = params["DataFileTitle"] 
     132        self.current_datainfo.sample.thickness = self._unit_conversion( 
     133            float(params["Thickness"]), "cm", 
     134            self._unit_fetch("Thickness"))[0] 
    84135 
    85             self._insist_header(headers, "SpinEchoLength") 
    86             self._insist_header(headers, "Depolarisation") 
    87             self._insist_header(headers, "Depolarisation_error") 
    88             self._insist_header(headers, "Wavelength") 
     136        self.current_datainfo.sample.zacceptance = ( 
     137            float(params["Theta_zmax"]), 
     138            self._unit_fetch("Theta_zmax")) 
    89139 
    90             data = np.loadtxt(input_f) 
     140        self.current_datainfo.sample.yacceptance = ( 
     141            float(params["Theta_ymax"]), 
     142            self._unit_fetch("Theta_ymax")) 
    91143 
    92             if data.shape[1] != len(headers): 
    93                 raise RuntimeError( 
    94                     "File has {} headers, but {} columns".format( 
    95                         len(headers), 
    96                         data.shape[1])) 
    97  
    98             if not data.size: 
    99                 raise RuntimeError("{} is empty".format(path)) 
    100             x = data[:, headers.index("SpinEchoLength")] 
    101             if "SpinEchoLength_error" in headers: 
    102                 dx = data[:, headers.index("SpinEchoLength_error")] 
    103             else: 
    104                 dx = x * 0.05 
    105             lam = data[:, headers.index("Wavelength")] 
    106             if "Wavelength_error" in headers: 
    107                 dlam = data[:, headers.index("Wavelength_error")] 
    108             else: 
    109                 dlam = lam * 0.05 
    110             y = data[:, headers.index("Depolarisation")] 
    111             dy = data[:, headers.index("Depolarisation_error")] 
    112  
    113             lam_unit = self._unit_fetch("Wavelength") 
    114             x, x_unit = self._unit_conversion(x, "A", 
    115                                               self._unit_fetch( 
    116                                                   "SpinEchoLength")) 
    117             dx, dx_unit = self._unit_conversion( 
    118                 dx, lam_unit, 
    119                 self._unit_fetch("SpinEchoLength")) 
    120             dlam, dlam_unit = self._unit_conversion( 
    121                 dlam, lam_unit, 
    122                 self._unit_fetch("Wavelength")) 
    123             y_unit = self._unit_fetch("Depolarisation") 
    124  
    125             output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, 
    126                             isSesans=True) 
    127  
    128             output.y_unit = y_unit 
    129             output.x_unit = x_unit 
    130             output.source.wavelength_unit = lam_unit 
    131             output.source.wavelength = lam 
    132             self.filename = output.filename = basename 
    133             output.xaxis(r"\rm{z}", x_unit) 
    134             # Adjust label to ln P/(lam^2 t), remove lam column refs 
    135             output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", y_unit) 
    136             # Store loading process information 
    137             output.meta_data['loader'] = self.type_name 
    138             output.sample.name = params["Sample"] 
    139             output.sample.ID = params["DataFileTitle"] 
    140             output.sample.thickness = self._unit_conversion( 
    141                 float(params["Thickness"]), "cm", 
    142                 self._unit_fetch("Thickness"))[0] 
    143  
    144             output.sample.zacceptance = ( 
    145                 float(params["Theta_zmax"]), 
    146                 self._unit_fetch("Theta_zmax")) 
    147  
    148             output.sample.yacceptance = ( 
    149                 float(params["Theta_ymax"]), 
    150                 self._unit_fetch("Theta_ymax")) 
    151             return output 
     144        self.send_to_output() 
    152145 
    153146    @staticmethod 
    154147    def _insist_header(headers, name): 
    155148        if name not in headers: 
    156             raise RuntimeError( 
     149            raise FileContentsException( 
    157150                "Missing {} column in spin echo data".format(name)) 
    158151 
  • src/sas/sascalc/dataloader/readers/xml_reader.py

    r235f514 rfafe52a  
    1818from lxml import etree 
    1919from lxml.builder import E 
     20from sas.sascalc.dataloader.file_reader_base_class import FileReader 
    2021 
    2122logger = logging.getLogger(__name__) 
     
    2324PARSER = etree.ETCompatXMLParser(remove_comments=True, remove_pis=False) 
    2425 
    25 class XMLreader(): 
     26class XMLreader(FileReader): 
    2627    """ 
    2728    Generic XML read and write class. Mostly helper functions. 
     
    7475        except etree.XMLSyntaxError as xml_error: 
    7576            logger.info(xml_error) 
     77            raise xml_error 
    7678        except Exception: 
    7779            self.xml = None 
     
    9193        except etree.XMLSyntaxError as xml_error: 
    9294            logger.info(xml_error) 
    93         except Exception: 
     95            raise xml_error 
     96        except Exception as exc: 
    9497            self.xml = None 
    9598            self.xmldoc = None 
    9699            self.xmlroot = None 
     100            raise exc 
    97101 
    98102    def set_schema(self, schema): 
     
    206210        Create a unique key value for any dictionary to prevent overwriting 
    207211        Recurses until a unique key value is found. 
    208          
     212 
    209213        :param dictionary: A dictionary with any number of entries 
    210214        :param name: The index of the item to be added to dictionary 
     
    222226        Create an element tree for processing from an etree element 
    223227 
    224         :param root: etree Element(s)  
     228        :param root: etree Element(s) 
    225229        """ 
    226230        return etree.ElementTree(root) 
  • src/sas/sasgui/guiframe/local_perspectives/data_loader/data_loader.py

    r235f514 rdcb91cf  
    1111 
    1212from sas.sascalc.dataloader.loader import Loader 
     13from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException 
    1314 
    1415from sas.sasgui import get_local_config 
     
    2627APPLICATION_WLIST = config.APPLICATION_WLIST 
    2728 
     29 
    2830class Plugin(PluginBase): 
    2931 
     
    4143        """ 
    4244        # menu for data files 
    43         menu_list = [] 
    4445        data_file_hint = "load one or more data in the application" 
    4546        menu_list = [('&Load Data File(s)', data_file_hint, self.load_data)] 
    4647        gui_style = self.parent.get_style() 
    4748        style = gui_style & GUIFRAME.MULTIPLE_APPLICATIONS 
    48         style1 = gui_style & GUIFRAME.DATALOADER_ON 
    4949        if style == GUIFRAME.MULTIPLE_APPLICATIONS: 
    5050            # menu for data from folder 
     
    8787        self.get_data(file_list) 
    8888 
    89  
    9089    def can_load_data(self): 
    9190        """ 
     
    9392        """ 
    9493        return True 
    95  
    9694 
    9795    def _load_folder(self, event): 
     
    125123        """ 
    126124        if error is not None or str(error).strip() != "": 
    127             dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File', 
     125            dial = wx.MessageDialog(self.parent, str(error), 
     126                                    'Error Loading File', 
    128127                                    wx.OK | wx.ICON_EXCLAMATION) 
    129128            dial.ShowModal() 
     
    134133        """ 
    135134        if os.path.isdir(path): 
    136             return [os.path.join(os.path.abspath(path), filename) for filename in os.listdir(path)] 
     135            return [os.path.join(os.path.abspath(path), filename) for filename 
     136                    in os.listdir(path)] 
    137137 
    138138    def _process_data_and_errors(self, item, p_file, output, message): 
     
    163163        for p_file in path: 
    164164            basename = os.path.basename(p_file) 
     165            # Skip files that start with a period 
     166            if basename.startswith("."): 
     167                msg = "The folder included a potential hidden file - %s." \ 
     168                      % basename 
     169                msg += " Do you wish to load this file as data?" 
     170                msg_box = wx.MessageDialog(None, msg, 'Warning', 
     171                                           wx.OK | wx.CANCEL) 
     172                if msg_box.ShowModal() == wx.ID_CANCEL: 
     173                    continue 
    165174            _, extension = os.path.splitext(basename) 
    166175            if extension.lower() in EXTENSIONS: 
     
    198207                info="info") 
    199208 
    200             except: 
    201                 logger.error(sys.exc_value) 
    202  
    203                 error_message = "The Data file you selected could not be loaded.\n" 
    204                 error_message += "Make sure the content of your file" 
    205                 error_message += " is properly formatted.\n" 
    206                 error_message += "When contacting the SasView team, mention the" 
    207                 error_message += " following:\n" 
    208                 error_message += "Error: " + str(sys.exc_info()[1]) 
    209                 file_errors[basename] = [error_message] 
    210                 self.load_update(output=output, message=error_message, info="warning") 
     209            except NoKnownLoaderException as e: 
     210                exception_occurred = True 
     211                logger.error(e.message) 
     212 
     213                error_message = "Loading data failed!\n" + e.message 
     214                self.load_update(output=None, message=e.message, info="warning") 
     215 
     216            except Exception as e: 
     217                exception_occurred = True 
     218                logger.error(e.message) 
     219 
     220                file_err = "The Data file you selected could not be " 
     221                file_err += "loaded.\nMake sure the content of your file" 
     222                file_err += " is properly formatted.\n" 
     223                file_err += "When contacting the SasView team, mention the" 
     224                file_err += " following:\n" 
     225                file_err += e.message 
     226                file_errors[basename] = [file_err] 
    211227 
    212228        if len(file_errors) > 0: 
     
    218234                    error_message += message + "\n" 
    219235                error_message += "\n" 
    220             self.load_update(output=output, message=error_message, info="error") 
    221  
    222         self.load_complete(output=output, message="Loading data complete!", 
    223             info="info") 
     236            if not exception_occurred: # Some data loaded but with errors 
     237                self.load_update(output=output, message=error_message, info="error") 
     238 
     239        if not exception_occurred: # Everything loaded as expected 
     240            self.load_complete(output=output, message="Loading data complete!", 
     241                               info="info") 
     242        else: 
     243            self.load_complete(output=None, message=error_message, info="error") 
     244 
    224245 
    225246    def load_update(self, output=None, message="", info="warning"): 
     
    230251            wx.PostEvent(self.parent, StatusEvent(status=message, info=info, 
    231252                                                  type="progress")) 
    232     def load_complete(self, output, message="", error_message="", path=None, 
    233                       info="warning"): 
    234         """ 
    235          post message to  status bar and return list of data 
    236         """ 
    237         wx.PostEvent(self.parent, StatusEvent(status=message, 
    238                                               info=info, 
     253 
     254    def load_complete(self, output, message="", info="warning"): 
     255        """ 
     256         post message to status bar and return list of data 
     257        """ 
     258        wx.PostEvent(self.parent, StatusEvent(status=message, info=info, 
    239259                                              type="stop")) 
    240         # if error_message != "": 
    241         #    self.load_error(error_message) 
    242         self.parent.add_data(data_list=output) 
     260        if output is not None: 
     261            self.parent.add_data(data_list=output) 
  • src/sas/sasgui/perspectives/file_converter/converter_panel.py

    red9f872 r19296dc  
    2424from sas.sascalc.file_converter.otoko_loader import OTOKOLoader 
    2525from sas.sascalc.file_converter.bsl_loader import BSLLoader 
     26from sas.sascalc.file_converter.ascii2d_loader import ASCII2DLoader 
    2627from sas.sascalc.file_converter.nxcansas_writer import NXcanSASWriter 
    2728from sas.sascalc.dataloader.data_info import Detector 
     
    3536    _STATICBOX_WIDTH = 410 
    3637    _BOX_WIDTH = 200 
    37     PANEL_SIZE = 480 
     38    PANEL_SIZE = 520 
    3839    FONT_VARIANT = 0 
    3940else: 
     
    4142    _STATICBOX_WIDTH = 430 
    4243    _BOX_WIDTH = 200 
    43     PANEL_SIZE = 500 
     44    PANEL_SIZE = 540 
    4445    FONT_VARIANT = 1 
    4546 
     
    352353            w.write(frame_data, output_path) 
    353354 
     355    def convert_2d_data(self, dataset): 
     356        metadata = self.get_metadata() 
     357        for key, value in metadata.iteritems(): 
     358            setattr(dataset[0], key, value) 
     359 
     360        w = NXcanSASWriter() 
     361        w.write(dataset, self.output.GetPath()) 
     362 
    354363    def on_convert(self, event): 
    355364        """Called when the Convert button is clicked""" 
     
    367376                qdata, iqdata = self.extract_otoko_data(self.q_input.GetPath()) 
    368377                self.convert_1d_data(qdata, iqdata) 
     378            elif self.data_type == 'ascii2d': 
     379                loader = ASCII2DLoader(self.iq_input.GetPath()) 
     380                data = loader.load() 
     381                dataset = [data] # ASCII 2D only ever contains 1 frame 
     382                self.convert_2d_data(dataset) 
    369383            else: # self.data_type == 'bsl' 
    370384                dataset = self.extract_bsl_data(self.iq_input.GetPath()) 
     
    372386                    # Cancelled by user 
    373387                    return 
    374  
    375                 metadata = self.get_metadata() 
    376                 for key, value in metadata.iteritems(): 
    377                     setattr(dataset[0], key, value) 
    378  
    379                 w = NXcanSASWriter() 
    380                 w.write(dataset, self.output.GetPath()) 
     388                self.convert_2d_data(dataset) 
     389 
    381390        except Exception as ex: 
    382391            msg = str(ex) 
     
    399408    def validate_inputs(self): 
    400409        msg = "You must select a" 
    401         if self.q_input.GetPath() == '' and self.data_type != 'bsl': 
     410        if self.q_input.GetPath() == '' and self.data_type != 'bsl' \ 
     411            and self.data_type != 'ascii2d': 
    402412            msg += " Q Axis input file." 
    403413        elif self.iq_input.GetPath() == '': 
     
    472482        dtype = event.GetEventObject().GetName() 
    473483        self.data_type = dtype 
    474         if dtype == 'bsl': 
     484        if dtype == 'bsl' or dtype == 'ascii2d': 
    475485            self.q_input.SetPath("") 
    476486            self.q_input.Disable() 
     
    500510 
    501511        instructions = ( 
    502         "Select linked single column 1D ASCII files containing the Q-axis and " 
    503         "Intensity-axis data, or 1D BSL/OTOKO files, or a 2D BSL/OTOKO file, " 
    504         "then choose where to save the converted file, and click Convert.\n" 
    505         "1D ASCII and BSL/OTOKO files can be converted to CanSAS (XML) or " 
    506         "NXcanSAS (HDF5) formats. 2D BSL/OTOKO files can only be converted to " 
    507         "the NXcanSAS format.\n" 
    508         "Metadata can be optionally added for the CanSAS XML format." 
     512        "If converting a 1D dataset, select linked single-column ASCII files " 
     513        "containing the Q-axis and intensity-axis data, or a 1D BSL/OTOKO file." 
     514        " If converting 2D data, select an ASCII file in the ISIS 2D file " 
     515        "format, or a 2D BSL/OTOKO file. Choose where to save the converted " 
     516        "file and click convert.\n" 
     517        "One dimensional ASCII and BSL/OTOKO files can be converted to CanSAS " 
     518        "(XML) or NXcanSAS (HDF5) formats. Two dimensional datasets can only be" 
     519        " converted to the NXcanSAS format.\n" 
     520        "Metadata can also be optionally added to the output file." 
    509521        ) 
    510522 
     
    526538            wx.ALIGN_CENTER_VERTICAL, 5) 
    527539        radio_sizer = wx.BoxSizer(wx.HORIZONTAL) 
    528         ascii_btn = wx.RadioButton(self, -1, "ASCII", name="ascii", 
     540        ascii_btn = wx.RadioButton(self, -1, "ASCII 1D", name="ascii", 
    529541            style=wx.RB_GROUP) 
    530542        ascii_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
    531543        radio_sizer.Add(ascii_btn) 
     544        ascii2d_btn = wx.RadioButton(self, -1, "ASCII 2D", name="ascii2d") 
     545        ascii2d_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
     546        radio_sizer.Add(ascii2d_btn) 
    532547        otoko_btn = wx.RadioButton(self, -1, "BSL 1D", name="otoko") 
    533548        otoko_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
    534549        radio_sizer.Add(otoko_btn) 
    535         input_grid.Add(radio_sizer, (y,1), (1,1), wx.ALL, 5) 
    536550        bsl_btn = wx.RadioButton(self, -1, "BSL 2D", name="bsl") 
    537551        bsl_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
    538552        radio_sizer.Add(bsl_btn) 
     553        input_grid.Add(radio_sizer, (y,1), (1,1), wx.ALL, 5) 
    539554        y += 1 
    540555 
     
    549564        y += 1 
    550565 
    551         iq_label = wx.StaticText(self, -1, "Intensity-Axis Data: ") 
     566        iq_label = wx.StaticText(self, -1, "Intensity Data: ") 
    552567        input_grid.Add(iq_label, (y,0), (1,1), wx.ALIGN_CENTER_VERTICAL, 5) 
    553568 
     
    647662 
    648663    def __init__(self, parent=None, title='File Converter', base=None, 
    649         manager=None, size=(PANEL_SIZE * 1.05, PANEL_SIZE / 1.1), 
     664        manager=None, size=(PANEL_SIZE * 0.96, PANEL_SIZE * 0.9), 
    650665        *args, **kwargs): 
    651666        kwargs['title'] = title 
  • src/sas/sasgui/perspectives/file_converter/file_converter.py

    r463e7ffc r94e3572  
    2525        Returns a set of menu entries 
    2626        """ 
    27         help_txt = "Convert single column ASCII data to CanSAS format" 
     27        help_txt = "Convert ASCII or BSL/OTOKO data to CanSAS or NXcanSAS formats" 
    2828        return [("File Converter", help_txt, self.on_file_converter)] 
    2929 
  • src/sas/sasgui/perspectives/file_converter/media/file_converter_help.rst

    rd73998c r59decb81  
    1818*   Single-column ASCII data, with lines that end without any delimiter, 
    1919    or with a comma or semi-colon delimiter 
     20*   2D `ISIS ASCII formatted 
     21    <http://www.isis.stfc.ac.uk/instruments/loq/software/ 
     22    colette-ascii-file-format-descriptions9808.pdf>`_ data 
    2023*   `1D BSL/OTOKO format 
    2124    <http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/ 
     
    3639 
    37401) Select the files containing your Q-axis and Intensity-axis data 
    38 2) Choose whether the files are in ASCII, 1D BSL/OTOKO or 2D BSL/OTOKO format 
     412) Choose whether the files are in ASCII 1D, ASCII 2D, 1D BSL/OTOKO or 2D BSL/OTOKO format 
    39423) Choose where you would like to save the converted file 
    40434) Optionally, input some metadata such as sample size, detector name, etc 
     
    4750file, a dialog will appear asking which frames you would like converted. You 
    4851may enter a start frame, end frame & increment, and all frames in that subset 
    49 will be converted. For example, entering 0, 50 and 10 will convert frames 0,  
     52will be converted. For example, entering 0, 50 and 10 will convert frames 0, 
    505310, 20, 30, 40 & 50. 
    5154 
     
    5659single file, so there is an option in the *Select Frame* dialog to output each 
    5760frame to its own file. The single file option will produce one file with 
    58 multiple `<SASdata>` elements. The multiple file option will output a separate  
    59 file with one `<SASdata>` element for each frame. The frame number will also be  
     61multiple `<SASdata>` elements. The multiple file option will output a separate 
     62file with one `<SASdata>` element for each frame. The frame number will also be 
    6063appended to the file name. 
    6164 
    62 The multiple file option is not available when exporting to NXcanSAS because  
     65The multiple file option is not available when exporting to NXcanSAS because 
    6366the HDF5 format is more efficient at handling large amounts of data. 
    6467 
  • test/fileconverter/test/cansas1d.xml

    rc476457 rdcb91cf  
    2626                                <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
    2727                        </Idata> 
     28      <Idata> 
     29                                <Q unit="1/A">0.04</Q> 
     30                                <I unit="1/cm">1002</I> 
     31                                <Idev unit="1/cm">4</Idev> 
     32                                <Qdev unit="1/A">0.02</Qdev> 
     33                                <Qmean unit="1/A"><!-- Qmean is optional --></Qmean> 
     34                                <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
     35                        </Idata> 
     36      <Idata> 
     37                                <Q unit="1/A">0.05</Q> 
     38                                <I unit="1/cm">1003</I> 
     39                                <Idev unit="1/cm">4</Idev> 
     40                                <Qdev unit="1/A">0.02</Qdev> 
     41                                <Qmean unit="1/A"><!-- Qmean is optional --></Qmean> 
     42                                <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
     43                        </Idata> 
     44      <Idata> 
     45                                <Q unit="1/A">0.06</Q> 
     46                                <I unit="1/cm">1004</I> 
     47                                <Idev unit="1/cm">4</Idev> 
     48                                <Qdev unit="1/A">0.02</Qdev> 
     49                                <Qmean unit="1/A"><!-- Qmean is optional --></Qmean> 
     50                                <Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor> 
     51                        </Idata> 
    2852                </SASdata> 
    2953                <SASsample name='my sample'> 
     
    4771                                Some text here 
    4872                        </details> 
    49                          
     73 
    5074                </SASsample> 
    5175                <SASinstrument> 
  • test/fileconverter/test/utest_nxcansas_writer.py

    r17c9436 r248ff73  
    11from sas.sascalc.file_converter.nxcansas_writer import NXcanSASWriter 
    2 from sas.sascalc.dataloader.readers.cansas_reader import Reader as XMLReader 
    3 from sas.sascalc.dataloader.readers.red2d_reader import Reader as DATReader 
    4 from sas.sascalc.dataloader.readers.cansas_reader_HDF5 import Reader as HDF5Reader 
     2from sas.sascalc.dataloader.loader import Loader 
    53 
    64import os 
     
    1412 
    1513    def setUp(self): 
     14        self.loader = Loader() 
    1615        self.writer = NXcanSASWriter() 
    1716        self.read_file_1d = "cansas1d.xml" 
     
    1918        self.read_file_2d = "exp18_14_igor_2dqxqy.dat" 
    2019        self.write_file_2d = "export2d.h5" 
    21         self.hdf5_reader = HDF5Reader() 
    2220 
    23         xml_reader = XMLReader() 
    24         self.data_1d = xml_reader.read(self.read_file_1d)[0] 
     21        self.data_1d = self.loader.load(self.read_file_1d)[0] 
    2522 
    26         dat_reader = DATReader() 
    27         self.data_2d = dat_reader.read(self.read_file_2d) 
     23        self.data_2d = self.loader.load(self.read_file_2d)[0] 
    2824        self.data_2d.detector[0].name = '' 
    2925        self.data_2d.source.radiation = 'neutron' 
     
    3127    def test_write_1d(self): 
    3228        self.writer.write([self.data_1d], self.write_file_1d) 
    33         data = self.hdf5_reader.read(self.write_file_1d) 
     29        data = self.loader.load(self.write_file_1d) 
    3430        self.assertTrue(len(data) == 1) 
    3531        data = data[0] 
     
    4137    def test_write_2d(self): 
    4238        self.writer.write([self.data_2d], self.write_file_2d) 
    43         data = self.hdf5_reader.read(self.write_file_2d) 
     39        data = self.loader.load(self.write_file_2d) 
    4440        self.assertTrue(len(data) == 1) 
    4541        data = data[0] 
  • test/sascalculator/test/utest_slit_length_calculator.py

    r959eb01 rb09095a  
    55import unittest 
    66from sas.sascalc.dataloader.readers.ascii_reader import Reader 
    7 from  sas.sascalc.calculator.slit_length_calculator import SlitlengthCalculator as calculator 
     7from sas.sascalc.calculator.slit_length_calculator import SlitlengthCalculator \ 
     8    as calculator 
    89 
    9 import os.path 
    1010 
    11 class slit_calculator(unittest.TestCase): 
     11class SlitCalculator(unittest.TestCase): 
    1212     
    1313    def setUp(self): 
     
    1515        self.reader = Reader() 
    1616         
    17     def test_slitlength_calculation(self): 
     17    def test_slit_length_calculation(self): 
    1818        """ 
    1919            Test slit_length_calculator" 
    2020        """ 
    21         f = self.reader.read("beam profile.DAT") 
     21        list = self.reader.read("beam profile.DAT") 
     22        self.assertTrue(len(list) == 1) 
     23        f = list[0] 
    2224        cal = calculator() 
    2325        cal.set_data(f.x,f.y) 
    24         slitlength = cal.calculate_slit_length() 
     26        slit_length = cal.calculate_slit_length() 
    2527         
    2628        # The value "5.5858" was obtained by manual calculation. 
    2729        # It turns out our slit length is FWHM/2 
    28         self.assertAlmostEqual(slitlength,5.5858/2, 3) 
     30        self.assertAlmostEqual(slit_length, 5.5858/2, 3) 
    2931         
    3032         
  • test/sasdataloader/test/utest_abs_reader.py

    rc551bb3 rce8c7bd  
    55 
    66import unittest 
    7 import math 
    87import numpy as np 
    98from sas.sascalc.dataloader.loader import Loader 
    10 from sas.sascalc.dataloader.readers.IgorReader import Reader as IgorReader 
    119from sas.sascalc.dataloader.readers.abs_reader import Reader as AbsReader 
    12 from sas.sascalc.dataloader.readers.hfir1d_reader import Reader as HFIRReader 
    1310from sas.sascalc.dataloader.readers.danse_reader import Reader as DANSEReader 
    1411from sas.sascalc.dataloader.readers.cansas_reader import Reader as CANSASReader 
    1512 
    1613from sas.sascalc.dataloader.data_info import Data1D 
    17   
     14 
    1815import os.path 
    1916 
    2017 
    2118class abs_reader(unittest.TestCase): 
    22      
     19 
    2320    def setUp(self): 
    2421        reader = AbsReader() 
     
    2724    def test_abs_checkdata(self): 
    2825        """ 
    29             Check the data content to see whether  
     26            Check the data content to see whether 
    3027            it matches the specific file we loaded. 
    3128            Check the units too to see whether the 
     
    3532        self.assertEqual(self.data.filename, "jan08002.ABS") 
    3633        self.assertEqual(self.data.meta_data['loader'], "IGOR 1D") 
    37          
     34 
    3835        self.assertEqual(self.data.source.wavelength_unit, 'A') 
    3936        self.assertEqual(self.data.source.wavelength, 6.0) 
    40          
     37 
    4138        self.assertEqual(self.data.detector[0].distance_unit, 'mm') 
    4239        self.assertEqual(self.data.detector[0].distance, 1000.0) 
    43          
     40 
    4441        self.assertEqual(self.data.sample.transmission, 0.5667) 
    45          
     42 
    4643        self.assertEqual(self.data.detector[0].beam_center_unit, 'mm') 
    47         center_x = 114.58*5.0 
    48         center_y = 64.22*5.0 
     44        center_x = 114.58*5.08 
     45        center_y = 64.22*5.08 
    4946        self.assertEqual(self.data.detector[0].beam_center.x, center_x) 
    5047        self.assertEqual(self.data.detector[0].beam_center.y, center_y) 
    51          
     48 
    5249        self.assertEqual(self.data.y_unit, '1/cm') 
    5350        self.assertEqual(self.data.x[0], 0.002618) 
     
    5552        self.assertEqual(self.data.x[2], 0.01309) 
    5653        self.assertEqual(self.data.x[126], 0.5828) 
    57          
     54 
    5855        self.assertEqual(self.data.y[0], 0.02198) 
    5956        self.assertEqual(self.data.y[1], 0.02201) 
    6057        self.assertEqual(self.data.y[2], 0.02695) 
    6158        self.assertEqual(self.data.y[126], 0.2958) 
    62          
     59 
    6360        self.assertEqual(self.data.dy[0], 0.002704) 
    6461        self.assertEqual(self.data.dy[1], 0.001643) 
    6562        self.assertEqual(self.data.dy[2], 0.002452) 
    6663        self.assertEqual(self.data.dy[126], 1) 
    67          
     64 
    6865    def test_checkdata2(self): 
    6966        self.assertEqual(self.data.dy[126], 1) 
     
    7471        self.assertEqual(data.meta_data['loader'], "IGOR 1D") 
    7572 
    76  
    77 class hfir_reader(unittest.TestCase): 
     73class DanseReaderTests(unittest.TestCase): 
    7874 
    7975    def setUp(self): 
    80         reader = HFIRReader() 
    81         self.data = reader.read("S2-30dq.d1d") 
    82  
    83     def test_hfir_checkdata(self): 
    84         """ 
    85             Check the data content to see whether  
    86             it matches the specific file we loaded. 
    87         """ 
    88         self.assertEqual(self.data.filename, "S2-30dq.d1d") 
    89         # THIS FILE FORMAT IS CURRENTLY READ BY THE ASCII READER 
    90         self.assertEqual(self.data.meta_data['loader'], "HFIR 1D") 
    91         self.assertEqual(len(self.data.x), 134) 
    92         self.assertEqual(len(self.data.y), 134) 
    93         #          Q           I               dI          dQ   
    94         # Point 1: 0.003014    0.003010        0.000315    0.008249 
    95         self.assertEqual(self.data.x[1], 0.003014) 
    96         self.assertEqual(self.data.y[1], 0.003010) 
    97         self.assertEqual(self.data.dy[1], 0.000315) 
    98         self.assertEqual(self.data.dx[1], 0.008249) 
    99  
    100     def test_generic_loader(self): 
    101         # the generic loader should work as well 
    102         data = Loader().load("S2-30dq.d1d") 
    103         self.assertEqual(data.meta_data['loader'], "HFIR 1D") 
    104  
    105  
    106 class igor_reader(unittest.TestCase): 
    107      
    108     def setUp(self): 
    109         # the IgorReader should be able to read this filetype 
    110         # if it can't, stop here. 
    111         reader = IgorReader() 
    112         self.data = reader.read("MAR07232_rest.ASC") 
    113  
    114     def test_igor_checkdata(self): 
    115         """ 
    116             Check the data content to see whether  
     76        reader = DANSEReader() 
     77        self.data = reader.read("MP_New.sans") 
     78 
     79    def test_checkdata(self): 
     80        """ 
     81            Check the data content to see whether 
    11782            it matches the specific file we loaded. 
    11883            Check the units too to see whether the 
     
    12085            tests won't pass 
    12186        """ 
    122         self.assertEqual(self.data.filename, "MAR07232_rest.ASC") 
    123         self.assertEqual(self.data.meta_data['loader'], "IGOR 2D") 
    124          
    125         self.assertEqual(self.data.source.wavelength_unit, 'A') 
    126         self.assertEqual(self.data.source.wavelength, 8.4) 
    127          
    128         self.assertEqual(self.data.detector[0].distance_unit, 'mm') 
    129         self.assertEqual(self.data.detector[0].distance, 13705) 
    130          
    131         self.assertEqual(self.data.sample.transmission, 0.84357) 
    132          
    133         self.assertEqual(self.data.detector[0].beam_center_unit, 'mm') 
    134         center_x = (68.76 - 1)*5.0 
    135         center_y = (62.47 - 1)*5.0 
    136         self.assertEqual(self.data.detector[0].beam_center.x, center_x) 
    137         self.assertEqual(self.data.detector[0].beam_center.y, center_y) 
    138          
    139         self.assertEqual(self.data.I_unit, '1/cm') 
    140         # 3 points should be suffcient to check that the data is in column 
    141         # major order. 
    142         np.testing.assert_almost_equal(self.data.data[0:3], 
    143                                        [0.279783, 0.28951, 0.167634]) 
    144         np.testing.assert_almost_equal(self.data.qx_data[0:3], 
    145                                        [-0.01849072, -0.01821785, -0.01794498]) 
    146         np.testing.assert_almost_equal(self.data.qy_data[0:3], 
    147                                        [-0.01677435, -0.01677435, -0.01677435]) 
    148  
    149     def test_generic_loader(self): 
    150         # the generic loader should direct the file to IgorReader as well 
    151         data = Loader().load("MAR07232_rest.ASC") 
    152         self.assertEqual(data.meta_data['loader'], "IGOR 2D") 
    153  
    154  
    155 class danse_reader(unittest.TestCase): 
    156      
    157     def setUp(self): 
    158         reader = DANSEReader() 
    159         self.data = reader.read("MP_New.sans") 
    160  
    161     def test_checkdata(self): 
    162         """ 
    163             Check the data content to see whether  
    164             it matches the specific file we loaded. 
    165             Check the units too to see whether the 
    166             Data1D defaults changed. Otherwise the 
    167             tests won't pass 
    168         """ 
    16987        self.assertEqual(self.data.filename, "MP_New.sans") 
    17088        self.assertEqual(self.data.meta_data['loader'], "DANSE") 
    171          
     89 
    17290        self.assertEqual(self.data.source.wavelength_unit, 'A') 
    17391        self.assertEqual(self.data.source.wavelength, 7.5) 
    174          
     92 
    17593        self.assertEqual(self.data.detector[0].distance_unit, 'mm') 
    17694        self.assertAlmostEqual(self.data.detector[0].distance, 5414.99, 3) 
    177          
     95 
    17896        self.assertEqual(self.data.detector[0].beam_center_unit, 'mm') 
    17997        center_x = 68.74*5.0 
     
    18199        self.assertEqual(self.data.detector[0].beam_center.x, center_x) 
    182100        self.assertEqual(self.data.detector[0].beam_center.y, center_y) 
    183          
     101 
    184102        self.assertEqual(self.data.I_unit, '1/cm') 
    185103        self.assertEqual(self.data.data[0], 1.57831) 
     
    196114        self.assertEqual(data.meta_data['loader'], "DANSE") 
    197115 
    198   
     116 
    199117class cansas_reader(unittest.TestCase): 
    200      
     118 
    201119    def setUp(self): 
    202120        reader = CANSASReader() 
     
    212130        self.assertEqual(self.data.filename, "cansas1d.xml") 
    213131        self._checkdata() 
    214          
     132 
    215133    def _checkdata(self): 
    216134        """ 
    217             Check the data content to see whether  
     135            Check the data content to see whether 
    218136            it matches the specific file we loaded. 
    219137            Check the units too to see whether the 
     
    223141        self.assertEqual(self.data.run[0], "1234") 
    224142        self.assertEqual(self.data.meta_data['loader'], "CanSAS XML 1D") 
    225          
     143 
    226144        # Data 
    227145        self.assertEqual(len(self.data.x), 2) 
     
    238156        self.assertEqual(self.data.run_name['1234'], 'run name') 
    239157        self.assertEqual(self.data.title, "Test title") 
    240          
     158 
    241159        # Sample info 
    242160        self.assertEqual(self.data.sample.ID, "SI600-new-long") 
     
    244162        self.assertEqual(self.data.sample.thickness_unit, 'mm') 
    245163        self.assertAlmostEqual(self.data.sample.thickness, 1.03) 
    246          
     164 
    247165        self.assertAlmostEqual(self.data.sample.transmission, 0.327) 
    248          
     166 
    249167        self.assertEqual(self.data.sample.temperature_unit, 'C') 
    250168        self.assertEqual(self.data.sample.temperature, 0) 
     
    258176        self.assertAlmostEqual(self.data.sample.orientation.y, 0.02, 6) 
    259177 
    260         self.assertEqual(self.data.sample.details[0], "http://chemtools.chem.soton.ac.uk/projects/blog/blogs.php/bit_id/2720")  
    261         self.assertEqual(self.data.sample.details[1], "Some text here")  
    262          
     178        self.assertEqual(self.data.sample.details[0], "http://chemtools.chem.soton.ac.uk/projects/blog/blogs.php/bit_id/2720") 
     179        self.assertEqual(self.data.sample.details[1], "Some text here") 
     180 
    263181        # Instrument info 
    264182        self.assertEqual(self.data.instrument, "canSAS instrument") 
    265          
     183 
    266184        # Source 
    267185        self.assertEqual(self.data.source.radiation, "neutron") 
    268          
     186 
    269187        self.assertEqual(self.data.source.beam_size_unit, "mm") 
    270188        self.assertEqual(self.data.source.beam_size_name, "bm") 
    271189        self.assertEqual(self.data.source.beam_size.x, 12) 
    272190        self.assertEqual(self.data.source.beam_size.y, 13) 
    273          
     191 
    274192        self.assertEqual(self.data.source.beam_shape, "disc") 
    275          
     193 
    276194        self.assertEqual(self.data.source.wavelength_unit, "A") 
    277195        self.assertEqual(self.data.source.wavelength, 6) 
    278          
     196 
    279197        self.assertEqual(self.data.source.wavelength_max_unit, "nm") 
    280198        self.assertAlmostEqual(self.data.source.wavelength_max, 1.0) 
     
    283201        self.assertEqual(self.data.source.wavelength_spread_unit, "percent") 
    284202        self.assertEqual(self.data.source.wavelength_spread, 14.3) 
    285          
     203 
    286204        # Collimation 
    287205        _found1 = False 
     
    289207        self.assertEqual(self.data.collimation[0].length, 123.) 
    290208        self.assertEqual(self.data.collimation[0].name, 'test coll name') 
    291          
     209 
    292210        for item in self.data.collimation[0].aperture: 
    293211            self.assertEqual(item.size_unit,'mm') 
     
    303221                and item.type == 'radius': 
    304222                _found2 = True 
    305                  
     223 
    306224        if _found1 == False or _found2 == False: 
    307             raise RuntimeError, "Could not find all data %s %s" % (_found1, _found2)  
    308              
     225            raise RuntimeError, "Could not find all data %s %s" % (_found1, _found2) 
     226 
    309227        # Detector 
    310228        self.assertEqual(self.data.detector[0].name, "fictional hybrid") 
    311229        self.assertEqual(self.data.detector[0].distance_unit, "mm") 
    312230        self.assertEqual(self.data.detector[0].distance, 4150) 
    313          
     231 
    314232        self.assertEqual(self.data.detector[0].orientation_unit, "degree") 
    315233        self.assertAlmostEqual(self.data.detector[0].orientation.x, 1.0, 6) 
    316234        self.assertEqual(self.data.detector[0].orientation.y, 0.0) 
    317235        self.assertEqual(self.data.detector[0].orientation.z, 0.0) 
    318          
     236 
    319237        self.assertEqual(self.data.detector[0].offset_unit, "m") 
    320238        self.assertEqual(self.data.detector[0].offset.x, .001) 
    321239        self.assertEqual(self.data.detector[0].offset.y, .002) 
    322240        self.assertEqual(self.data.detector[0].offset.z, None) 
    323          
     241 
    324242        self.assertEqual(self.data.detector[0].beam_center_unit, "mm") 
    325243        self.assertEqual(self.data.detector[0].beam_center.x, 322.64) 
    326244        self.assertEqual(self.data.detector[0].beam_center.y, 327.68) 
    327245        self.assertEqual(self.data.detector[0].beam_center.z, None) 
    328          
     246 
    329247        self.assertEqual(self.data.detector[0].pixel_size_unit, "mm") 
    330248        self.assertEqual(self.data.detector[0].pixel_size.x, 5) 
    331249        self.assertEqual(self.data.detector[0].pixel_size.y, 5) 
    332250        self.assertEqual(self.data.detector[0].pixel_size.z, None) 
    333          
     251 
    334252        # Process 
    335253        _found_term1 = False 
     
    349267                      and float(t['value']) == 10.0): 
    350268                    _found_term1 = True 
    351                      
     269 
    352270        if _found_term1 == False or _found_term2 == False: 
    353271            raise RuntimeError, "Could not find all process terms %s %s" % (_found_term1, _found_term2) 
    354          
     272 
    355273    def test_writer(self): 
    356274        r = CANSASReader() 
     
    364282        if os.path.isfile(filename): 
    365283            os.remove(filename) 
    366          
     284 
    367285    def test_units(self): 
    368286        """ 
     
    375293        self.assertEqual(self.data.filename, filename) 
    376294        self._checkdata() 
    377          
     295 
    378296    def test_badunits(self): 
    379297        """ 
     
    389307        # This one should 
    390308        self.assertAlmostEqual(self.data.sample.transmission, 0.327) 
    391          
     309 
    392310        self.assertEqual(self.data.meta_data['loader'], "CanSAS XML 1D") 
    393311        print(self.data.errors) 
     
    403321        self.assertEqual(self.data.filename, filename) 
    404322        self.assertEqual(self.data.run[0], "1234") 
    405          
     323 
    406324        # Data 
    407325        self.assertEqual(len(self.data.x), 2) 
  • test/sasdataloader/test/utest_ascii.py

    r959eb01 rad92c5a  
    66 
    77import unittest 
    8 from sas.sascalc.dataloader.loader import  Loader 
    9   
    10 import os.path 
     8from sas.sascalc.dataloader.loader import Loader 
    119 
    12 class abs_reader(unittest.TestCase): 
     10 
     11class ABSReaderTests(unittest.TestCase): 
    1312     
    1413    def setUp(self): 
    1514        self.loader = Loader() 
    16          
     15        self.f1_list = self.loader.load("ascii_test_1.txt") 
     16        self.f1 = self.f1_list[0] 
     17        self.f2_list = self.loader.load("ascii_test_2.txt") 
     18        self.f2 = self.f2_list[0] 
     19        self.f3_list = self.loader.load("ascii_test_3.txt") 
     20        self.f3 = self.f3_list[0] 
     21        self.f4_list = self.loader.load("ascii_test_4.abs") 
     22        self.f4 = self.f4_list[0] 
     23        self.f5_list = self.loader.load("ascii_test_5.txt") 
     24        self.f5 = self.f5_list[0] 
     25 
    1726    def test_checkdata(self): 
    1827        """ 
    1928            Test .ABS file loaded as ascii 
    2029        """ 
    21         f = self.loader.load("ascii_test_1.txt") 
    2230        # The length of the data is 10 
    23         self.assertEqual(len(f.x), 10) 
    24         self.assertEqual(f.x[0],0.002618) 
    25         self.assertEqual(f.x[9],0.0497) 
    26         self.assertEqual(f.x_unit, '1/A') 
    27         self.assertEqual(f.y_unit, '1/cm') 
     31        self.assertEqual(len(self.f1.x), 10) 
     32        self.assertEqual(self.f1.x[0],0.002618) 
     33        self.assertEqual(self.f1.x[9],0.0497) 
     34        self.assertEqual(self.f1.x_unit, '1/A') 
     35        self.assertEqual(self.f1.y_unit, '1/cm') 
    2836         
    29         self.assertEqual(f.meta_data['loader'],"ASCII") 
    30          
     37        self.assertEqual(self.f1.meta_data['loader'],"ASCII") 
     38 
    3139    def test_truncated_1(self): 
    3240        """ 
     
    3846            as though it were the start of a footer). 
    3947        """ 
    40         # Test .ABS file loaded as ascii 
    41         f = self.loader.load("ascii_test_2.txt") 
    42         # The length of the data is 10 
    43         self.assertEqual(len(f.x), 5) 
    44         self.assertEqual(f.x[0],0.002618) 
    45         self.assertEqual(f.x[4],0.02356) 
    46          
     48        # The length of the data is 5 
     49        self.assertEqual(len(self.f2.x), 5) 
     50        self.assertEqual(self.f2.x[0],0.002618) 
     51        self.assertEqual(self.f2.x[4],0.02356) 
     52 
    4753    def test_truncated_2(self): 
    4854        """ 
     
    5258            reading at the first inconsitent line. 
    5359        """ 
    54         # Test .ABS file loaded as ascii 
    55         f = self.loader.load("ascii_test_3.txt") 
    5660        # The length of the data is 5 
    57         self.assertEqual(len(f.x), 5) 
    58         self.assertEqual(f.x[0],0.002618) 
    59         self.assertEqual(f.x[4],0.02356) 
    60          
     61        self.assertEqual(len(self.f3.x), 5) 
     62        self.assertEqual(self.f3.x[0],0.002618) 
     63        self.assertEqual(self.f3.x[4],0.02356) 
     64 
    6165    def test_truncated_3(self): 
    6266        """ 
     
    6670            reading at the last line of header. 
    6771        """ 
    68         # Test .ABS file loaded as ascii 
    69         f = self.loader.load("ascii_test_4.abs") 
    7072        # The length of the data is 5 
    71         self.assertEqual(len(f.x), 5) 
    72         self.assertEqual(f.x[0],0.012654) 
    73         self.assertEqual(f.x[4],0.02654) 
    74          
     73        self.assertEqual(len(self.f4.x), 5) 
     74        self.assertEqual(self.f4.x[0],0.012654) 
     75        self.assertEqual(self.f4.x[4],0.02654) 
     76 
    7577    def test_truncated_4(self): 
    7678        """ 
     
    7880            Only the last 5 2-col lines should be read. 
    7981        """ 
    80         # Test .ABS file loaded as ascii 
    81         f = self.loader.load("ascii_test_5.txt") 
    8282        # The length of the data is 5 
    83         self.assertEqual(len(f.x), 5) 
    84         self.assertEqual(f.x[0],0.02879) 
    85         self.assertEqual(f.x[4],0.0497) 
    86          
     83        self.assertEqual(len(self.f5.x), 5) 
     84        self.assertEqual(self.f5.x[0],0.02879) 
     85        self.assertEqual(self.f5.x[4],0.0497) 
     86 
    8787    def test_truncated_5(self): 
    8888        """ 
    89             Test a 6-col ascii file with complex header where one of them has a letter and  
    90             many lines with 2 or 2 columns in the middle of the data section. 
    91             Only last four lines should be read. 
     89            Test a 6-col ascii file with complex header where one of them has a 
     90            letter and many lines with 2 or 2 columns in the middle of the data 
     91            section. Will be rejected because fewer than 5 lines. 
    9292        """ 
    9393        # Test .ABS file loaded as ascii 
     
    9898        except: 
    9999            self.assertEqual(f, None) 
    100          
     100 
    101101if __name__ == '__main__': 
    102102    unittest.main() 
  • test/sasdataloader/test/utest_averaging.py

    re123eb9 r2a52b0e  
    4646        # respectively. 
    4747        self.qmin = get_q(1.0, 1.0, detector.distance, source.wavelength) 
    48  
    4948        self.qmax = get_q(49.5, 49.5, detector.distance, source.wavelength) 
    5049 
     
    104103    def setUp(self): 
    105104        filepath = os.path.join(os.path.dirname( 
    106             os.path.realpath(__file__)), 'MAR07232_rest.ASC') 
    107         self.data = Loader().load(filepath) 
     105            os.path.realpath(__file__)), 'MAR07232_rest.h5') 
     106        self.data = Loader().load(filepath)[0] 
    108107 
    109108    def test_ring(self): 
     
    120119        filepath = os.path.join(os.path.dirname( 
    121120            os.path.realpath(__file__)), 'ring_testdata.txt') 
    122         answer = Loader().load(filepath) 
     121        answer = Loader().load(filepath)[0] 
    123122 
    124123        for i in range(r.nbins_phi - 1): 
     
    140139        filepath = os.path.join(os.path.dirname( 
    141140            os.path.realpath(__file__)), 'avg_testdata.txt') 
    142         answer = Loader().load(filepath) 
     141        answer = Loader().load(filepath)[0] 
    143142        for i in range(r.nbins_phi): 
    144143            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     
    176175        filepath = os.path.join(os.path.dirname( 
    177176            os.path.realpath(__file__)), 'slabx_testdata.txt') 
    178         answer = Loader().load(filepath) 
     177        answer = Loader().load(filepath)[0] 
    179178        for i in range(len(o.x)): 
    180179            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     
    195194        filepath = os.path.join(os.path.dirname( 
    196195            os.path.realpath(__file__)), 'slaby_testdata.txt') 
    197         answer = Loader().load(filepath) 
     196        answer = Loader().load(filepath)[0] 
    198197        for i in range(len(o.x)): 
    199198            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     
    204203        """ 
    205204            Test sector averaging I(phi) 
    206             When considering the whole azimuthal range (2pi),  
     205            When considering the whole azimuthal range (2pi), 
    207206            the answer should be the same as ring averaging. 
    208207            The test data was not generated by IGOR. 
     
    222221        filepath = os.path.join(os.path.dirname( 
    223222            os.path.realpath(__file__)), 'ring_testdata.txt') 
    224         answer = Loader().load(filepath) 
     223        answer = Loader().load(filepath)[0] 
    225224        for i in range(len(o.x)): 
    226225            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     
    240239        filepath = os.path.join(os.path.dirname( 
    241240            os.path.realpath(__file__)), 'sectorphi_testdata.txt') 
    242         answer = Loader().load(filepath) 
     241        answer = Loader().load(filepath)[0] 
    243242        for i in range(len(o.x)): 
    244243            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     
    258257        filepath = os.path.join(os.path.dirname( 
    259258            os.path.realpath(__file__)), 'sectorq_testdata.txt') 
    260         answer = Loader().load(filepath) 
     259        answer = Loader().load(filepath)[0] 
    261260        for i in range(len(o.x)): 
    262261            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     
    277276        for i in range(len(o.x)): 
    278277            self.assertAlmostEqual(o.x[i], expected_binning[i], 3) 
    279          
     278 
    280279        # TODO: Test for Y values (o.y) 
    281280        # print len(self.data.x_bins) 
     
    288287        # xedges_width = (xedges[1] - xedges[0]) 
    289288        # xedges_center = xedges[1:] - xedges_width / 2 
    290          
     289 
    291290        # yedges_width = (yedges[1] - yedges[0]) 
    292291        # yedges_center = yedges[1:] - yedges_width / 2 
    293          
     292 
    294293        # print H.flatten().shape 
    295294        # print o.y.shape 
    296          
     295 
    297296 
    298297if __name__ == '__main__': 
  • test/sasdataloader/test/utest_red2d_reader.py

    r959eb01 r248ff73  
    77import unittest 
    88from sas.sascalc.dataloader.loader import  Loader 
    9   
     9 
    1010import os.path 
    1111 
    1212class abs_reader(unittest.TestCase): 
    13      
     13 
    1414    def setUp(self): 
    1515        self.loader = Loader() 
    16          
     16 
    1717    def test_checkdata(self): 
    1818        """ 
    1919            Test .DAT file loaded as IGOR/DAT 2D Q_map 
    2020        """ 
    21         f = self.loader.load("exp18_14_igor_2dqxqy.dat") 
     21        f = self.loader.load("exp18_14_igor_2dqxqy.dat")[0] 
    2222        # The length of the data is 10 
    2323        self.assertEqual(len(f.qx_data),  36864) 
     
    2626        self.assertEqual(f.Q_unit, '1/A') 
    2727        self.assertEqual(f.I_unit, '1/cm') 
    28          
     28 
    2929        self.assertEqual(f.meta_data['loader'],"IGOR/DAT 2D Q_map") 
    30          
    31          
     30 
     31 
    3232if __name__ == '__main__': 
    3333    unittest.main() 
    34     
  • test/sasinvariant/test/utest_use_cases.py

    r959eb01 rb09095a  
    66import unittest 
    77from sas.sascalc.dataloader.loader import  Loader 
    8  
    98from sas.sascalc.invariant import invariant 
     9 
    1010 
    1111class Data1D: 
    1212    pass 
    13      
     13 
     14 
    1415class TestLineFit(unittest.TestCase): 
    1516    """ 
     
    1718    """ 
    1819    def setUp(self): 
    19         self.data = Loader().load("linefittest.txt") 
    20          
     20        self.data_list = Loader().load("linefittest.txt") 
     21        self.data = self.data_list[0] 
     22 
    2123    def test_fit_line_data(self): 
    2224        """  
    2325            Fit_Test_1: test linear fit, ax +b, without fixed 
    2426        """ 
    25          
     27 
    2628        # Create invariant object. Background and scale left as defaults. 
    2729        fit = invariant.Extrapolator(data=self.data) 
    2830         
    29         ##Without holding 
     31        # Without holding 
    3032        p, dp = fit.fit(power=None) 
    3133 
     
    3335        self.assertAlmostEquals(p[0], 2.3983,3) 
    3436        self.assertAlmostEquals(p[1], 0.87833,3) 
    35  
    3637 
    3738    def test_fit_line_data_fixed(self): 
     
    3940            Fit_Test_2: test linear fit, ax +b, with 'a' fixed 
    4041        """ 
    41          
     42 
    4243        # Create invariant object. Background and scale left as defaults. 
    4344        fit = invariant.Extrapolator(data=self.data) 
    44          
    45         #With holding a = -power =4 
     45 
     46        # With holding a = -power =4 
    4647        p, dp = fit.fit(power=-4) 
    4748 
     
    4950        self.assertAlmostEquals(p[0], 4) 
    5051        self.assertAlmostEquals(p[1], -4.0676,3) 
    51          
     52 
     53 
    5254class TestLineFitNoweight(unittest.TestCase): 
    5355    """ 
     
    5557    """ 
    5658    def setUp(self): 
    57         self.data = Loader().load("linefittest_no_weight.txt") 
    58          
     59        self.data_list = Loader().load("linefittest_no_weight.txt") 
     60        self.data = self.data_list[0] 
     61 
    5962    def skip_test_fit_line_data_no_weight(self): 
    6063        """  
    6164            Fit_Test_1: test linear fit, ax +b, without fixed 
    6265        """ 
    63          
     66 
    6467        # Create invariant object. Background and scale left as defaults. 
    6568        fit = invariant.Extrapolator(data=self.data) 
    66          
    67         ##Without holding 
     69 
     70        # Without holding 
    6871        p, dp = fit.fit(power=None) 
    6972 
     
    7174        self.assertAlmostEquals(p[0], 2.4727,3) 
    7275        self.assertAlmostEquals(p[1], 0.6,3) 
    73  
    7476 
    7577    def test_fit_line_data_fixed_no_weight(self): 
     
    7779            Fit_Test_2: test linear fit, ax +b, with 'a' fixed 
    7880        """ 
    79          
     81 
    8082        # Create invariant object. Background and scale left as defaults. 
    8183        fit = invariant.Extrapolator(data=self.data) 
    82          
     84 
    8385        #With holding a = -power =4 
    8486        p, dp = fit.fit(power=-4) 
     
    8789        self.assertAlmostEquals(p[0], 4) 
    8890        self.assertAlmostEquals(p[1], -7.8,3) 
    89                  
     91 
     92 
    9093class TestInvPolySphere(unittest.TestCase): 
    9194    """ 
     
    9396    """ 
    9497    def setUp(self): 
    95         self.data = Loader().load("PolySpheres.txt") 
    96          
     98        self.data_list = Loader().load("PolySpheres.txt") 
     99        self.data = self.data_list[0] 
     100 
    97101    def test_wrong_data(self): 
    98102        """ test receiving Data1D not of type loader""" 
    99  
    100  
    101103        self.assertRaises(ValueError,invariant.InvariantCalculator, Data1D()) 
    102          
     104 
    103105    def test_use_case_1(self): 
    104106        """ 
     
    107109        # Create invariant object. Background and scale left as defaults. 
    108110        inv = invariant.InvariantCalculator(data=self.data) 
    109          
     111 
    110112        # We have to be able to tell the InvariantCalculator whether we want the 
    111113        # extrapolation or not. By default, when the user doesn't specify, we 
    112         # should compute Q* without extrapolation. That's what should be done in __init__. 
    113          
     114        # should compute Q* without extrapolation. That's what should be done 
     115        # in __init__. 
     116 
    114117        # We call get_qstar() with no argument, which signifies that we do NOT 
    115118        # want extrapolation. 
    116119        qstar = inv.get_qstar() 
    117          
     120 
    118121        # The volume fraction and surface use Q*. That means that the following  
    119122        # methods should check that Q* has been computed. If not, it should  
     
    121124        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
    122125        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
    123          
     126 
    124127        # Test results 
    125128        self.assertAlmostEquals(qstar, 7.48959e-5,2) 
    126129        self.assertAlmostEquals(v, 0.005644689, 4) 
    127130        self.assertAlmostEquals(s , 941.7452, 3) 
    128          
     131 
    129132    def test_use_case_2(self): 
    130133        """ 
    131             Invariant without extrapolation. Invariant, volume fraction and surface  
    132             are given with errors. 
    133         """ 
    134         # Create invariant object. Background and scale left as defaults. 
    135         inv = invariant.InvariantCalculator(data=self.data) 
    136          
     134        Invariant without extrapolation. Invariant, volume fraction and surface  
     135        are given with errors. 
     136        """ 
     137        # Create invariant object. Background and scale left as defaults. 
     138        inv = invariant.InvariantCalculator(data=self.data) 
     139 
    137140        # Get the invariant with errors 
    138141        qstar, qstar_err = inv.get_qstar_with_error() 
    139          
     142 
    140143        # The volume fraction and surface use Q*. That means that the following  
    141144        # methods should check that Q* has been computed. If not, it should  
     
    147150        self.assertAlmostEquals(v, 0.005644689, 1) 
    148151        self.assertAlmostEquals(s , 941.7452, 3) 
    149         
    150          
     152 
    151153    def test_use_case_3(self): 
    152154        """ 
     
    155157        # Create invariant object. Background and scale left as defaults. 
    156158        inv = invariant.InvariantCalculator(data=self.data) 
    157          
     159 
    158160        # Set the extrapolation parameters for the low-Q range 
    159          
     161 
    160162        # The npts parameter should have a good default. 
    161163        # The range parameter should be 'high' or 'low' 
    162164        # The function parameter should default to None. If it is None, 
    163         #    the method should pick a good default (Guinier at low-Q and 1/q^4 at high-Q). 
    164         #    The method should also check for consistency of the extrapolation and function 
    165         #    parameters. For instance, you might not want to allow 'high' and 'guinier'. 
     165        #    the method should pick a good default 
     166        #    (Guinier at low-Q and 1/q^4 at high-Q). 
     167        #    The method should also check for consistency of the extrapolation 
     168        #    and function parameters. For instance, you might not want to allow 
     169        #    'high' and 'guinier'. 
    166170        # The power parameter (not shown below) should default to 4. 
    167171        inv.set_extrapolation(range='low', npts=10, function='guinier') 
    168          
    169         # The version of the call without error 
    170         # At this point, we could still compute Q* without extrapolation by calling 
    171         # get_qstar with arguments, or with extrapolation=None. 
     172 
     173        # The version of the call without error 
     174        # At this point, we could still compute Q* without extrapolation by 
     175        # calling get_qstar with arguments, or with extrapolation=None. 
    172176        qstar = inv.get_qstar(extrapolation='low') 
    173          
     177 
    174178        # The version of the call with error 
    175179        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') 
     
    178182        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
    179183        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
    180          
     184 
    181185        # Test results 
    182186        self.assertAlmostEquals(qstar, 7.49e-5, 1) 
    183187        self.assertAlmostEquals(v, 0.005648401, 4) 
    184188        self.assertAlmostEquals(s , 941.7452, 3) 
    185              
     189 
    186190    def test_use_case_4(self): 
    187191        """ 
     
    190194        # Create invariant object. Background and scale left as defaults. 
    191195        inv = invariant.InvariantCalculator(data=self.data) 
     196 
     197        # Set the extrapolation parameters for the high-Q range 
     198        inv.set_extrapolation(range='high', npts=10, function='power_law', 
     199                              power=4) 
    192200         
    193         # Set the extrapolation parameters for the high-Q range 
    194         inv.set_extrapolation(range='high', npts=10, function='power_law', power=4) 
    195          
    196         # The version of the call without error 
    197         # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     201        # The version of the call without error 
     202        # The function parameter defaults to None, then is picked to be 
     203        # 'power_law' for extrapolation='high' 
    198204        qstar = inv.get_qstar(extrapolation='high') 
    199          
     205 
    200206        # The version of the call with error 
    201207        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='high') 
     
    204210        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
    205211        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
    206          
     212 
    207213        # Test results 
    208214        self.assertAlmostEquals(qstar, 7.49e-5,2) 
    209215        self.assertAlmostEquals(v, 0.005952674, 3) 
    210216        self.assertAlmostEquals(s , 941.7452, 3) 
    211          
     217 
    212218    def test_use_case_5(self): 
    213219        """ 
     
    216222        # Create invariant object. Background and scale left as defaults. 
    217223        inv = invariant.InvariantCalculator(data=self.data) 
    218          
     224 
    219225        # Set the extrapolation parameters for the low- and high-Q ranges 
    220226        inv.set_extrapolation(range='low', npts=10, function='guinier') 
    221         inv.set_extrapolation(range='high', npts=10, function='power_law', power=4) 
    222          
    223         # The version of the call without error 
    224         # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     227        inv.set_extrapolation(range='high', npts=10, function='power_law', 
     228                              power=4) 
     229 
     230        # The version of the call without error 
     231        # The function parameter defaults to None, then is picked to be 
     232        # 'power_law' for extrapolation='high' 
    225233        qstar = inv.get_qstar(extrapolation='both') 
    226234         
     
    231239        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
    232240        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
    233          
     241 
    234242        # Test results 
    235243        self.assertAlmostEquals(qstar, 7.88981e-5,2) 
    236244        self.assertAlmostEquals(v, 0.005952674, 3) 
    237245        self.assertAlmostEquals(s , 941.7452, 3) 
    238        
     246 
    239247    def test_use_case_6(self): 
    240248        """ 
     
    243251        # Create invariant object. Background and scale left as defaults. 
    244252        inv = invariant.InvariantCalculator(data=self.data) 
    245          
     253 
    246254        # Set the extrapolation parameters for the high-Q range 
    247255        inv.set_extrapolation(range='low', npts=10, function='power_law', power=4) 
    248          
     256 
    249257        # The version of the call without error 
    250258        # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
    251259        qstar = inv.get_qstar(extrapolation='low') 
    252          
     260 
    253261        # The version of the call with error 
    254262        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') 
     
    257265        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
    258266        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
    259          
     267 
    260268        # Test results 
    261269        self.assertAlmostEquals(qstar, 7.49e-5,2) 
    262270        self.assertAlmostEquals(v, 0.005952674, 3) 
    263271        self.assertAlmostEquals(s , 941.7452, 3) 
    264          
     272 
     273 
    265274class TestInvPinholeSmear(unittest.TestCase): 
    266275    """ 
     
    271280        list = Loader().load("latex_smeared.xml") 
    272281        self.data_q_smear = list[0] 
    273      
     282 
    274283    def test_use_case_1(self): 
    275284        """ 
     
    278287        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
    279288        qstar = inv.get_qstar() 
    280          
     289 
    281290        v = inv.get_volume_fraction(contrast=2.6e-6) 
    282291        s = inv.get_surface(contrast=2.6e-6, porod_const=2) 
     
    285294        self.assertAlmostEquals(v, 0.115352622, 2) 
    286295        self.assertAlmostEquals(s , 941.7452, 3 ) 
    287          
     296 
    288297    def test_use_case_2(self): 
    289298        """ 
     
    293302        # Create invariant object. Background and scale left as defaults. 
    294303        inv = invariant.InvariantCalculator(data=self.data_q_smear) 
    295          
     304 
    296305        # Get the invariant with errors 
    297306        qstar, qstar_err = inv.get_qstar_with_error() 
     
    303312        self.assertAlmostEquals(v, 0.115352622, 2) 
    304313        self.assertAlmostEquals(s , 941.7452, 3 ) 
    305         
     314 
    306315    def test_use_case_3(self): 
    307316        """ 
     
    319328        v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) 
    320329        s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) 
    321          
     330 
    322331        # Test results 
    323332        self.assertAlmostEquals(qstar, 0.00138756,2) 
    324333        self.assertAlmostEquals(v, 0.117226896,2) 
    325334        self.assertAlmostEquals(s ,941.7452, 3) 
    326        
     335 
    327336    def test_use_case_4(self): 
    328337        """ 
     
    337346        # The version of the call with error 
    338347        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='high') 
    339          
    340         # Get the volume fraction and surface 
    341         # WHY SHOULD THIS FAIL? 
    342         #self.assertRaises(RuntimeError, inv.get_volume_fraction_with_error, 2.6e-6) 
    343          
    344         # Check that an exception is raised when the 'surface' is not defined 
    345         # WHY SHOULD THIS FAIL? 
    346         #self.assertRaises(RuntimeError, inv.get_surface_with_error, 2.6e-6, 2) 
    347348 
    348349        # Test results 
    349350        self.assertAlmostEquals(qstar, 0.0045773,2) 
    350         
     351 
    351352    def test_use_case_5(self): 
    352353        """ 
     
    357358        # Set the extrapolation parameters for the low- and high-Q ranges 
    358359        inv.set_extrapolation(range='low', npts=10, function='guinier') 
    359         inv.set_extrapolation(range='high', npts=10, function='power_law', power=4) 
    360         # The version of the call without error 
    361         # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' 
     360        inv.set_extrapolation(range='high', npts=10, function='power_law', 
     361                              power=4) 
     362        # The version of the call without error 
     363        # The function parameter defaults to None, then is picked to be 
     364        # 'power_law' for extrapolation='high' 
    362365        qstar = inv.get_qstar(extrapolation='both') 
    363366        # The version of the call with error 
    364367        qstar, qstar_err = inv.get_qstar_with_error(extrapolation='both') 
    365          
    366         # Get the volume fraction and surface 
    367         # WHY SHOULD THIS FAIL? 
    368         #self.assertRaises(RuntimeError, inv.get_volume_fraction_with_error, 2.6e-6) 
    369         #self.assertRaises(RuntimeError, inv.get_surface_with_error, 2.6e-6, 2) 
    370          
     368 
    371369        # Test results 
    372370        self.assertAlmostEquals(qstar, 0.00460319,3) 
Note: See TracChangeset for help on using the changeset viewer.