source: sasview/sansdataloader/src/sans/dataloader/readers/ascii_reader.py @ a36a22a

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since a36a22a was 83b81b8, checked in by Jae Cho <jhjcho@…>, 13 years ago

a little better data error control

  • Property mode set to 100644
File size: 15.4 KB
RevLine 
[7d6351e]1"""
2    ASCII reader
3"""
[0997158f]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.
[7d6351e]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
[0997158f]10#following sentence:
[7d6351e]11#This work benefited from DANSE software developed under NSF award DMR-0520547.
[0997158f]12#copyright 2008, University of Tennessee
13#############################################################################
14
[8bd8ea4]15
16import numpy
17import os
[ad8034f]18from sans.dataloader.data_info import Data1D
[8bd8ea4]19
[daa56d0]20# Check whether we have a converter available
[99d1af6]21has_converter = True
22try:
23    from data_util.nxsunit import Converter
24except:
25    has_converter = False
[da96629]26_ZERO = 1e-16
[99d1af6]27
[7d6351e]28
[8bd8ea4]29class Reader:
30    """
[0997158f]31    Class to load ascii files (2, 3 or 4 columns).
[8bd8ea4]32    """
[8780e9a]33    ## File type
[28caa03]34    type_name = "ASCII"
35   
36    ## Wildcards
[8780e9a]37    type = ["ASCII files (*.txt)|*.txt",
[470bf7e]38            "ASCII files (*.dat)|*.dat",
[ef9d209]39            "ASCII files (*.abs)|*.abs",
40            "CSV files (*.csv)|*.csv"]
[8bd8ea4]41    ## List of allowed extensions
[7d6351e]42    ext = ['.txt', '.TXT', '.dat', '.DAT', '.abs', '.ABS', 'csv', 'CSV']
[8bd8ea4]43   
[e082e2c]44    ## Flag to bypass extension check
45    allow_all = True
46   
[8bd8ea4]47    def read(self, path):
[7d6351e]48        """
[0997158f]49        Load data file
50       
51        :param path: file path
52       
53        :return: Data1D object, or None
54       
55        :raise RuntimeError: when the file can't be opened
56        :raise ValueError: when the length of the data vectors are inconsistent
[8bd8ea4]57        """
58        if os.path.isfile(path):
[7d6351e]59            basename = os.path.basename(path)
[a7a5886]60            _, extension = os.path.splitext(basename)
[e082e2c]61            if self.allow_all or extension.lower() in self.ext:
[8bd8ea4]62                try:
[9cd0baa]63                    # Read in binary mode since GRASP frequently has no-ascii
64                    # characters that brakes the open operation
[7d6351e]65                    input_f = open(path,'rb')
66                except:
[8bd8ea4]67                    raise  RuntimeError, "ascii_reader: cannot open %s" % path
68                buff = input_f.read()
69                lines = buff.split('\n')
[470bf7e]70               
[7d6351e]71                #Jae could not find python universal line spliter:
[a7a5886]72                #keep the below for now
73                # some ascii data has \r line separator,
74                # try it when the data is on only one long line
[7d6351e]75                if len(lines) < 2 :
[470bf7e]76                    lines = buff.split('\r')
77                 
[8bd8ea4]78                x  = numpy.zeros(0)
79                y  = numpy.zeros(0)
80                dy = numpy.zeros(0)
[de1da34]81                dx = numpy.zeros(0)
82               
83               #temp. space to sort data
84                tx  = numpy.zeros(0)
85                ty  = numpy.zeros(0)
86                tdy = numpy.zeros(0)
87                tdx = numpy.zeros(0)
88               
89                output = Data1D(x, y, dy=dy, dx=dx)
[8bd8ea4]90                self.filename = output.filename = basename
[99d1af6]91           
92                data_conv_q = None
93                data_conv_i = None
94               
[ca10d8e]95                if has_converter == True and output.x_unit != '1/A':
96                    data_conv_q = Converter('1/A')
[99d1af6]97                    # Test it
98                    data_conv_q(1.0, output.x_unit)
99                   
[ca10d8e]100                if has_converter == True and output.y_unit != '1/cm':
101                    data_conv_i = Converter('1/cm')
[99d1af6]102                    # Test it
103                    data_conv_i(1.0, output.y_unit)
104           
[8bd8ea4]105                # The first good line of data will define whether
106                # we have 2-column or 3-column ascii
[de1da34]107                has_error_dx = None
108                has_error_dy = None
[8bd8ea4]109               
[892f246]110                #Initialize counters for data lines and header lines.
[7d6351e]111                is_data = False  # Has more than 5 lines
[a7a5886]112                # More than "5" lines of data is considered as actual
113                # data unless that is the only data
[7d6351e]114                mum_data_lines = 5
[a7a5886]115                # To count # of current data candidate lines
[7d6351e]116                i = -1
117                # To count total # of previous data candidate lines
118                i1 = -1
119                # To count # of header lines
[a7a5886]120                j = -1
[7d6351e]121                # Helps to count # of header lines
[a7a5886]122                j1 = -1
[7d6351e]123                #minimum required number of columns of data; ( <= 4).
124                lentoks = 2
[8bd8ea4]125                for line in lines:
[ef9d209]126                    toks = line.split(',')
127                    if len(toks) < 2:
128                        toks = line.split()
[8bd8ea4]129                    try:
[5f2d3c78]130                        #Make sure that all columns are numbers.
131                        for colnum in range(len(toks)):
132                            float(toks[colnum])
133                           
[8bd8ea4]134                        _x = float(toks[0])
135                        _y = float(toks[1])
136                       
[892f246]137                        #Reset the header line counters
138                        if j == j1:
139                            j = 0
140                            j1 = 0
141                           
142                        if i > 1:
143                            is_data = True
[d508be9]144                       
[99d1af6]145                        if data_conv_q is not None:
146                            _x = data_conv_q(_x, units=output.x_unit)
147                           
148                        if data_conv_i is not None:
[7d6351e]149                            _y = data_conv_i(_y, units=output.y_unit)
[99d1af6]150                       
[8bd8ea4]151                        # If we have an extra token, check
152                        # whether it can be interpreted as a
153                        # third column.
154                        _dy = None
[a7a5886]155                        if len(toks) > 2:
[8bd8ea4]156                            try:
157                                _dy = float(toks[2])
[99d1af6]158                               
159                                if data_conv_i is not None:
160                                    _dy = data_conv_i(_dy, units=output.y_unit)
161                               
[8bd8ea4]162                            except:
163                                # The third column is not a float, skip it.
164                                pass
165                           
166                        # If we haven't set the 3rd column
167                        # flag, set it now.
[de1da34]168                        if has_error_dy == None:
169                            has_error_dy = False if _dy == None else True
170                           
171                        #Check for dx
172                        _dx = None
[a7a5886]173                        if len(toks) > 3:
[de1da34]174                            try:
175                                _dx = float(toks[3])
176                               
177                                if data_conv_i is not None:
178                                    _dx = data_conv_i(_dx, units=output.x_unit)
179                               
180                            except:
181                                # The 4th column is not a float, skip it.
182                                pass
183                           
184                        # If we haven't set the 3rd column
185                        # flag, set it now.
186                        if has_error_dx == None:
187                            has_error_dx = False if _dx == None else True
[892f246]188                       
[7d6351e]189                        #After talked with PB, we decided to take care of only
[a7a5886]190                        # 4 columns of data for now.
[d508be9]191                        #number of columns in the current line
[7d6351e]192                        #To remember the # of columns in the current
[a7a5886]193                        #line of data
[0e5e586]194                        new_lentoks = len(toks)
[d508be9]195                       
[7d6351e]196                        #If the previous columns not equal to the current,
197                        #mark the previous as non-data and reset the dependents.
198                        if lentoks != new_lentoks:
[272b107]199                            if is_data == True:
200                                break
201                            else:
[d508be9]202                                i = -1
203                                i1 = 0
204                                j = -1
205                                j1 = -1
206                           
[a7a5886]207                        #Delete the previously stored lines of data candidates
208                        # if is not data.
209                        if i < 0 and -1 < i1 < mum_data_lines and \
210                            is_data == False:
[892f246]211                            try:
[a7a5886]212                                x = numpy.zeros(0)
213                                y = numpy.zeros(0)
[892f246]214                            except:
215                                pass
216                           
[7d6351e]217                        x = numpy.append(x, _x) 
218                        y = numpy.append(y, _y)
[892f246]219                       
[de1da34]220                        if has_error_dy == True:
[a7a5886]221                            #Delete the previously stored lines of
222                            # data candidates if is not data.
223                            if i < 0 and -1 < i1 < mum_data_lines and \
224                                is_data == False:
[892f246]225                                try:
[7d6351e]226                                    dy = numpy.zeros(0)
[892f246]227                                except:
[7d6351e]228                                    pass
[8bd8ea4]229                            dy = numpy.append(dy, _dy)
[892f246]230                           
[de1da34]231                        if has_error_dx == True:
[a7a5886]232                            #Delete the previously stored lines of
233                            # data candidates if is not data.
234                            if i < 0 and -1 < i1 < mum_data_lines and \
235                                is_data == False:
[892f246]236                                try:
[7d6351e]237                                    dx = numpy.zeros(0)
[892f246]238                                except:
[7d6351e]239                                    pass
[de1da34]240                            dx = numpy.append(dx, _dx)
241                           
242                        #Same for temp.
[a7a5886]243                        #Delete the previously stored lines of data candidates
244                        # if is not data.
245                        if i < 0 and -1 < i1 < mum_data_lines and\
246                            is_data == False:
[892f246]247                            try:
248                                tx = numpy.zeros(0)
249                                ty = numpy.zeros(0)
250                            except:
[7d6351e]251                                pass
[892f246]252
[7d6351e]253                        tx = numpy.append(tx, _x)
254                        ty = numpy.append(ty, _y)
[892f246]255                       
[de1da34]256                        if has_error_dy == True:
[a7a5886]257                            #Delete the previously stored lines of
258                            # data candidates if is not data.
259                            if i < 0 and -1 < i1 < mum_data_lines and \
260                                is_data == False:
[892f246]261                                try:
262                                    tdy = numpy.zeros(0)
263                                except:
[7d6351e]264                                    pass
[de1da34]265                            tdy = numpy.append(tdy, _dy)
266                        if has_error_dx == True:
[a7a5886]267                            #Delete the previously stored lines of
268                            # data candidates if is not data.
269                            if i < 0 and -1 < i1 < mum_data_lines and \
270                                is_data == False:
[892f246]271                                try:
272                                    tdx = numpy.zeros(0)
273                                except:
[7d6351e]274                                    pass
[de1da34]275                            tdx = numpy.append(tdx, _dx)
[d508be9]276
277                        #reset i1 and flag lentoks for the next
[a7a5886]278                        if lentoks < new_lentoks:
[d508be9]279                            if is_data == False:
[7d6351e]280                                i1 = -1
[a7a5886]281                        #To remember the # of columns on the current line
282                        # for the next line of data
[0e5e586]283                        lentoks = len(toks)
[8bd8ea4]284                       
[7d6351e]285                        #Reset # of header lines and counts #
286                        # of data candidate lines
[a7a5886]287                        if j == 0 and j1 == 0:
[7d6351e]288                            i1 = i + 1
[a7a5886]289                        i += 1
[8bd8ea4]290                    except:
[892f246]291
292                        # It is data and meet non - number, then stop reading
293                        if is_data == True:
[7d6351e]294                            break
[d508be9]295                        lentoks = 2
[7d6351e]296                        #Counting # of header lines
[a7a5886]297                        j += 1
298                        if j == j1 + 1:
[7d6351e]299                            j1 = j
300                        else:
[892f246]301                            j = -1
302                        #Reset # of lines of data candidates
303                        i = -1
304                       
[7d6351e]305                        # Couldn't parse this line, skip it
[8bd8ea4]306                        pass
[892f246]307                   
[7d6351e]308                input_f.close()
[8bd8ea4]309                # Sanity check
[de1da34]310                if has_error_dy == True and not len(y) == len(dy):
[a7a5886]311                    msg = "ascii_reader: y and dy have different length"
312                    raise RuntimeError, msg
[de1da34]313                if has_error_dx == True and not len(x) == len(dx):
[a7a5886]314                    msg = "ascii_reader: y and dy have different length"
315                    raise RuntimeError, msg
[8bd8ea4]316                # If the data length is zero, consider this as
317                # though we were not able to read the file.
[a7a5886]318                if len(x) == 0:
[daa56d0]319                    raise RuntimeError, "ascii_reader: could not load file"
[de1da34]320               
[a7a5886]321                #Let's re-order the data to make cal.
322                # curve look better some cases
323                ind = numpy.lexsort((ty, tx))
[de1da34]324                for i in ind:
325                    x[i] = tx[ind[i]]
326                    y[i] = ty[ind[i]]
327                    if has_error_dy == True:
328                        dy[i] = tdy[ind[i]]
329                    if has_error_dx == True:
330                        dx[i] = tdx[ind[i]]
[7d6351e]331                # Zeros in dx, dy
[da96629]332                if has_error_dx:
[7d6351e]333                    dx[dx == 0] = _ZERO
[da96629]334                if has_error_dy:
[7d6351e]335                    dy[dy == 0] = _ZERO
336                #Data
337                output.x = x[x != 0]
338                output.y = y[x != 0]
339                output.dy = dy[x != 0] if has_error_dy == True\
340                    else numpy.zeros(len(output.y))
341                output.dx = dx[x != 0] if has_error_dx == True\
342                    else numpy.zeros(len(output.x))
[fca90f82]343                               
[99d1af6]344                if data_conv_q is not None:
345                    output.xaxis("\\rm{Q}", output.x_unit)
346                else:
347                    output.xaxis("\\rm{Q}", 'A^{-1}')
348                if data_conv_i is not None:
[0e2aa40]349                    output.yaxis("\\rm{Intensity}", output.y_unit)
[99d1af6]350                else:
[7d6351e]351                    output.yaxis("\\rm{Intensity}", "cm^{-1}")
[fe78c7b]352                   
353                # Store loading process information
[7d6351e]354                output.meta_data['loader'] = self.type_name
[83b81b8]355                if len(output.x) < 1:
356                    raise RuntimeError, "%s is empty" % path
[8bd8ea4]357                return output
[892f246]358           
[8bd8ea4]359        else:
360            raise RuntimeError, "%s is not a file" % path
361        return None
Note: See TracBrowser for help on using the repository browser.