Changeset b09095a in sasview


Ignore:
Timestamp:
Apr 17, 2017 2:39:50 PM (7 years ago)
Author:
krzywon
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
8ffafd1
Parents:
beba407
git-author:
Jeff Krzywon <krzywon@…> (04/17/17 14:39:50)
git-committer:
krzywon <krzywon@…> (04/17/17 14:39:50)
Message:

Refactor ASCII reader to use FileReader? class.

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/dataloader/file_reader_base_class.py

    rbeba407 rb09095a  
    11""" 
    2 This is the base file reader class all file readers should inherit from. 
     2This is the base file reader class most file readers should inherit from. 
    33All generic functionality required for a file loader/reader is built into this 
    44class 
     
    77import os 
    88import logging 
     9import numpy as np 
    910from abc import abstractmethod 
    1011from loader_exceptions import NoKnownLoaderException, FileContentsException,\ 
     
    1920    # List of Data1D and Data2D objects to be sent back to data_loader 
    2021    output = [] 
    21     # Current plottable1D/2D object being loaded in 
     22    # Current plottable_(1D/2D) object being loaded in 
    2223    current_dataset = None 
    23     # Current DataInfo objecct being loaded in 
     24    # Current DataInfo object being loaded in 
    2425    current_datainfo = None 
    25     # Wildcards 
    26     type = ["Text files (*.txt)"] 
     26    # String to describe the type of data this reader can load 
     27    type_name = "ASCII" 
     28    # Wildcards to display 
     29    type = ["Text files (*.txt|*.TXT)"] 
    2730    # List of allowed extensions 
    2831    ext = ['.txt'] 
    2932    # Bypass extension check and try to load anyway 
    3033    allow_all = False 
     34    # Able to import the unit converter 
     35    has_converter = True 
     36    # Open file handle 
     37    f_open = None 
     38    # Default value of zero 
     39    _ZERO = 1e-16 
    3140 
    3241    def read(self, filepath): 
     
    4251                # Try to load the file, but raise an error if unable to. 
    4352                try: 
    44                     input_f = open(filepath, 'rb') 
    45                     self.get_file_contents(input_f) 
     53                    self.unit_converter() 
     54                    self.f_open = open(filepath, 'rb') 
     55                    self.get_file_contents() 
     56                    self.sort_one_d_data() 
    4657                except RuntimeError: 
     58                    # Reader specific errors 
     59                    # TODO: Give a specific error. 
    4760                    pass 
    4861                except OSError as e: 
     62                    # If the file cannot be opened 
    4963                    msg = "Unable to open file: {}\n".format(filepath) 
    5064                    msg += e.message 
    5165                    self.handle_error_message(msg) 
    5266                except Exception as e: 
    53                     self.handle_error_message(e.message) 
     67                    # Handle any other generic error 
     68                    # TODO: raise or log? 
     69                    raise 
     70                finally: 
     71                    if not self.f_open.closed: 
     72                        self.f_open.close() 
    5473        else: 
    5574            msg = "Unable to find file at: {}\n".format(filepath) 
    5675            msg += "Please check your file path and try again." 
    5776            self.handle_error_message(msg) 
    58         # Return a list of parsed entries that dataloader can manage 
     77        # Return a list of parsed entries that data_loader can manage 
    5978        return self.output 
    6079 
     
    7998        self.output.append(data_obj) 
    8099 
     100    def unit_converter(self): 
     101        """ 
     102        Generic unit conversion import  
     103        """ 
     104        # Check whether we have a converter available 
     105        self.has_converter = True 
     106        try: 
     107            from sas.sascalc.data_util.nxsunit import Converter 
     108        except: 
     109            self.has_converter = False 
     110 
     111    def sort_one_d_data(self): 
     112        """ 
     113        Sort 1D data along the X axis for consistency 
     114        """ 
     115        final_list = [] 
     116        for data in self.output: 
     117            if isinstance(data, Data1D): 
     118                ind = np.lexsort((data.y, data.x)) 
     119                data.x = np.asarray([data.x[i] for i in ind]) 
     120                data.y = np.asarray([data.y[i] for i in ind]) 
     121                if data.dx is not None: 
     122                    data.dx = np.asarray([data.dx[i] for i in ind]) 
     123                if data.dxl is not None: 
     124                    data.dxl = np.asarray([data.dxl[i] for i in ind]) 
     125                if data.dxw is not None: 
     126                    data.dxw = np.asarray([data.dxw[i] for i in ind]) 
     127                if data.dy is not None: 
     128                    data.dy = np.asarray([data.dy[i] for i in ind]) 
     129                if data.lam is not None: 
     130                    data.lam = np.asarray([data.lam[i] for i in ind]) 
     131                if data.dlam is not None: 
     132                    data.dlam = np.asarray([data.dlam[i] for i in ind]) 
     133            final_list.append(data) 
     134        self.output = final_list 
     135 
     136    @staticmethod 
     137    def splitline(line): 
     138        """ 
     139        Splits a line into pieces based on common delimeters 
     140        :param line: A single line of text 
     141        :return: list of values 
     142        """ 
     143        # Initial try for CSV (split on ,) 
     144        toks = line.split(',') 
     145        # Now try SCSV (split on ;) 
     146        if len(toks) < 2: 
     147            toks = line.split(';') 
     148        # Now go for whitespace 
     149        if len(toks) < 2: 
     150            toks = line.split() 
     151        return toks 
     152 
    81153    @abstractmethod 
    82     def get_file_contents(self, contents): 
     154    def get_file_contents(self): 
    83155        """ 
    84         All reader classes that inherit from here should implement 
    85         :param contents:  
     156        All reader classes that inherit from FileReader must implement 
    86157        """ 
    87158        pass 
  • src/sas/sascalc/dataloader/readers/ascii_reader.py

    r235f514 rb09095a  
    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 
     16import numpy as np 
     17from sas.sascalc.dataloader.file_reader_base_class import FileReader 
     18from sas.sascalc.dataloader.data_info import DataInfo, plottable_1D 
    1519 
    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 
     20logger = logging.getLogger(__name__) 
    2721 
    2822 
    29 class Reader: 
     23class Reader(FileReader): 
    3024    """ 
    3125    Class to load ascii files (2, 3 or 4 columns). 
    3226    """ 
    33     ## File type 
     27    # File type 
    3428    type_name = "ASCII" 
    35  
    36     ## Wildcards 
     29    # Wildcards 
    3730    type = ["ASCII files (*.txt)|*.txt", 
    3831            "ASCII files (*.dat)|*.dat", 
    3932            "ASCII files (*.abs)|*.abs", 
    4033            "CSV files (*.csv)|*.csv"] 
    41     ## List of allowed extensions 
    42     ext = ['.txt', '.TXT', '.dat', '.DAT', '.abs', '.ABS', 'csv', 'CSV'] 
     34    # List of allowed extensions 
     35    ext = ['.txt', '.dat', '.abs', '.csv'] 
     36    # Flag to bypass extension check 
     37    allow_all = True 
     38    # data unless that is the only data 
     39    min_data_pts = 5 
    4340 
    44     ## Flag to bypass extension check 
    45     allow_all = True 
     41    def get_file_contents(self): 
     42        """ 
     43        Get the contents of the file 
     44        """ 
    4645 
    47     def read(self, path): 
    48         """ 
    49         Load data file 
     46        buff = self.f_open.read() 
     47        filepath = self.f_open.name 
     48        lines = buff.splitlines() 
     49        self.output = [] 
     50        self.current_datainfo = DataInfo() 
     51        self.current_datainfo.filename = filepath 
     52        self.reset_data_list(len(lines)) 
    5053 
    51         :param path: file path 
    52         :return: Data1D object, or None 
     54        # The first good line of data will define whether 
     55        # we have 2-column or 3-column ascii 
     56        has_error_dx = None 
     57        has_error_dy = None 
    5358 
    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() 
     59        # Initialize counters for data lines and header lines. 
     60        is_data = False 
     61        # More than "5" lines of data is considered as actual 
     62        # To count # of current data candidate lines 
     63        candidate_lines = 0 
     64        # To count total # of previous data candidate lines 
     65        candidate_lines_previous = 0 
     66        # Current line number 
     67        line_no = 0 
     68        # minimum required number of columns of data 
     69        lentoks = 2 
     70        for line in lines: 
     71            toks = self.splitline(line.strip()) 
     72            # To remember the number of columns in the current line of data 
     73            new_lentoks = len(toks) 
     74            try: 
     75                if new_lentoks == 0: 
     76                    # If the line is blank, skip and continue on 
     77                    # In case of breaks within data sets. 
     78                    continue 
     79                elif new_lentoks != lentoks and is_data: 
     80                    # If a footer is found, break the loop and save the data 
     81                    break 
     82                elif new_lentoks != lentoks and not is_data: 
     83                    # If header lines are numerical 
     84                    candidate_lines = 0 
     85                    self.reset_data_list(len(lines) - line_no) 
    6986 
    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) 
     87                candidate_lines += 1 
     88                # If 5 or more lines, this is considering the set data 
     89                if candidate_lines >= self.min_data_pts: 
     90                    is_data = True 
    7591 
    76                 # The first good line of data will define whether 
    77                 # we have 2-column or 3-column ascii 
     92                self.current_dataset.x[candidate_lines - 1] = float(toks[0]) 
     93                self.current_dataset.y[candidate_lines - 1] = float(toks[1]) 
     94 
     95                # If a 3rd row is present, consider it dy 
     96                if new_lentoks > 2: 
     97                    self.current_dataset.dy[candidate_lines - 1] = \ 
     98                        float(toks[2]) 
     99                    has_error_dy = True 
     100 
     101                # If a 4th row is present, consider it dx 
     102                if new_lentoks > 3: 
     103                    self.current_dataset.dx[candidate_lines - 1] = \ 
     104                        float(toks[3]) 
     105                    has_error_dx = True 
     106 
     107                # To remember the # of columns on the current line 
     108                # for the next line of data 
     109                lentoks = new_lentoks 
     110                line_no += 1 
     111            except ValueError: 
     112                # It is data and meet non - number, then stop reading 
     113                if is_data: 
     114                    break 
     115                # Delete the previously stored lines of data candidates if 
     116                # the list is not data 
     117                self.reset_data_list(len(lines) - line_no) 
     118                lentoks = 2 
    78119                has_error_dx = None 
    79120                has_error_dy = None 
     121                # Reset # of lines of data candidates 
     122                candidate_lines = 0 
     123            except Exception: 
     124                # Handle any unexpected exceptions 
     125                raise 
    80126 
    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 
     127        if not is_data: 
     128            # TODO: Check file extension - primary reader, throw error. 
     129            # TODO: Secondary check, pass and try next reader 
     130            msg = "ascii_reader: x has no data" 
     131            raise RuntimeError(msg) 
     132        # Sanity check 
     133        if has_error_dy and not len(self.current_dataset.y) == \ 
     134                len(self.current_dataset.dy): 
     135            msg = "ascii_reader: y and dy have different length" 
     136            raise RuntimeError(msg) 
     137        if has_error_dx and not len(self.current_dataset.x) == \ 
     138                len(self.current_dataset.dx): 
     139            msg = "ascii_reader: y and dy have different length" 
     140            raise RuntimeError(msg) 
     141        # If the data length is zero, consider this as 
     142        # though we were not able to read the file. 
     143        if len(self.current_dataset.x) < 1: 
     144            raise RuntimeError("ascii_reader: could not load file") 
     145            return None 
    111146 
    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]) 
     147        # Data 
     148        self.current_dataset.x = \ 
     149            self.current_dataset.x[self.current_dataset.x != 0] 
     150        self.current_dataset.y = \ 
     151            self.current_dataset.y[self.current_dataset.x != 0] 
     152        self.current_dataset.dy = \ 
     153            self.current_dataset.dy[self.current_dataset.x != 0] if \ 
     154                has_error_dy else np.zeros(len(self.current_dataset.y)) 
     155        self.current_dataset.dx = \ 
     156            self.current_dataset.dx[self.current_dataset.x != 0] if \ 
     157                has_error_dx else np.zeros(len(self.current_dataset.x)) 
    116158 
    117                         candidate_lines += 1 
    118                         _x = float(toks[0]) 
    119                         _y = float(toks[1]) 
    120                         _dx = None 
    121                         _dy = None 
     159        self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') 
     160        self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") 
    122161 
    123                         #If 5 or more lines, this is considering the set data 
    124                         if candidate_lines >= min_data_pts: 
    125                             is_data = True 
     162        # Store loading process information 
     163        self.current_datainfo.meta_data['loader'] = self.type_name 
     164        self.send_to_output() 
    126165 
    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): 
     166    def reset_data_list(self, no_lines): 
    232167        """ 
    233         Splits a line into pieces based on common delimeters 
    234         :param line: A single line of text 
    235         :return: list of values 
     168        Reset the plottable_1D object 
    236169        """ 
    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 
     170        # Initialize data sets with arrays the maximum possible size 
     171        x = np.zeros(no_lines) 
     172        y = np.zeros(no_lines) 
     173        dy = np.zeros(no_lines) 
     174        dx = np.zeros(no_lines) 
     175        self.current_dataset = plottable_1D(x, y, dx, dy) 
  • 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_ascii.py

    r959eb01 rb09095a  
    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() 
     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] 
    1625         
    1726    def test_checkdata(self): 
     
    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") 
     37        self.assertEqual(self.f1.meta_data['loader'],"ASCII") 
    3038         
    3139    def test_truncated_1(self): 
     
    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) 
     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) 
    4652         
    4753    def test_truncated_2(self): 
     
    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) 
     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) 
    6064         
    6165    def test_truncated_3(self): 
     
    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) 
     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) 
    7476         
    7577    def test_truncated_4(self): 
     
    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) 
     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) 
    8686         
    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 
  • test/sasdataloader/test/utest_averaging.py

    r9a5097c rb09095a  
    33import math 
    44 
    5 from sas.sascalc.dataloader.loader import  Loader 
     5from sas.sascalc.dataloader.loader import Loader 
    66from sas.sascalc.dataloader.manipulations import Ring, CircularAverage, SectorPhi, get_q,reader2D_converter 
    77 
     
    110110         
    111111        o = r(self.data) 
    112         answer = Loader().load('ring_testdata.txt') 
     112        data_list = Loader().load('ring_testdata.txt') 
     113        answer = data_list[0] 
    113114         
    114115        for i in range(r.nbins_phi - 1): 
  • 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.