source: sasview/src/sas/sascalc/dataloader/readers/IgorReader.py @ 71ac835

Last change on this file since 71ac835 was b699768, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 9 years ago

Initial commit of the refactored SasCalc? module.

  • Property mode set to 100644
File size: 10.6 KB
RevLine 
[7d6351e]1"""
2    IGOR 2D reduced file 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.
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
13#############################################################################
[a7a5886]14import os
[b99ac227]15import numpy
[a7a5886]16import math
17#import logging
[b699768]18from sas.sascalc.dataloader.data_info import Data2D
19from sas.sascalc.dataloader.data_info import Detector
20from sas.sascalc.dataloader.manipulations import reader2D_converter
[b99ac227]21
22# Look for unit converter
23has_converter = True
24try:
[b699768]25    from sas.sascalc.data_util.nxsunit import Converter
[b99ac227]26except:
27    has_converter = False
28
[7d6351e]29
[bb03739]30class Reader:
[11a0319]31    """ Simple data reader for Igor data files """
[b99ac227]32    ## File type
[7d6351e]33    type_name = "IGOR 2D"
[28caa03]34    ## Wildcards
[b99ac227]35    type = ["IGOR 2D files (*.ASC)|*.ASC"]
36    ## Extension
37    ext=['.ASC', '.asc']
38
[7d6351e]39    def read(self, filename=None):
[11a0319]40        """ Read file """
[b99ac227]41        if not os.path.isfile(filename):
[11a0319]42            raise ValueError, \
[b99ac227]43            "Specified file %s is not a regular file" % filename
[11a0319]44       
45        # Read file
[7d6351e]46        f = open(filename, 'r')
[11a0319]47        buf = f.read()
48       
[b99ac227]49        # Instantiate data object
50        output = Data2D()
51        output.filename = os.path.basename(filename)
52        detector = Detector()
[7d6351e]53        if len(output.detector) > 0:
54            print str(output.detector[0])
[b99ac227]55        output.detector.append(detector)
[f55af70]56               
[11a0319]57        # Get content
58        dataStarted = False
59       
60        lines = buf.split('\n')
61        itot = 0
[b99ac227]62        x = []
63        y = []
[11a0319]64       
65        ncounts = 0
66       
67        xmin = None
68        xmax = None
69        ymin = None
70        ymax = None
71       
72        i_x = 0
73        i_y = -1
[f55af70]74        i_tot_row = 0
[11a0319]75       
76        isInfo = False
77        isCenter = False
[f55af70]78       
79        data_conv_q = None
80        data_conv_i = None
81       
[ca10d8e]82        if has_converter == True and output.Q_unit != '1/A':
83            data_conv_q = Converter('1/A')
[f55af70]84            # Test it
85            data_conv_q(1.0, output.Q_unit)
86           
[ca10d8e]87        if has_converter == True and output.I_unit != '1/cm':
88            data_conv_i = Converter('1/cm')
[f55af70]89            # Test it
[7d6351e]90            data_conv_i(1.0, output.I_unit)
[f55af70]91         
[11a0319]92        for line in lines:
93           
94            # Find setup info line
95            if isInfo:
96                isInfo = False
97                line_toks = line.split()
98                # Wavelength in Angstrom
99                try:
100                    wavelength = float(line_toks[1])
101                except:
[a7a5886]102                    msg = "IgorReader: can't read this file, missing wavelength"
103                    raise ValueError, msg
[f55af70]104               
105            #Find # of bins in a row assuming the detector is square.
106            if dataStarted == True:
107                try:
108                    value = float(line)
109                except:
110                    # Found a non-float entry, skip it
111                    continue
112               
113                # Get total bin number
114               
115            i_tot_row += 1
[7d6351e]116        i_tot_row = math.ceil(math.sqrt(i_tot_row)) - 1
[f55af70]117        #print "i_tot", i_tot_row
[7d6351e]118        size_x = i_tot_row  # 192#128
119        size_y = i_tot_row  # 192#128
120        output.data = numpy.zeros([size_x, size_y])
121        output.err_data = numpy.zeros([size_x, size_y])
[f55af70]122     
123        #Read Header and 2D data
124        for line in lines:
125            # Find setup info line
126            if isInfo:
127                isInfo = False
128                line_toks = line.split()
129                # Wavelength in Angstrom
130                try:
131                    wavelength = float(line_toks[1])
132                except:
[a7a5886]133                    msg = "IgorReader: can't read this file, missing wavelength"
134                    raise ValueError, msg
[11a0319]135                # Distance in meters
136                try:
137                    distance = float(line_toks[3])
138                except:
[a7a5886]139                    msg = "IgorReader: can't read this file, missing distance"
140                    raise ValueError, msg
[11a0319]141               
[b99ac227]142                # Distance in meters
143                try:
144                    transmission = float(line_toks[4])
145                except:
[a7a5886]146                    msg = "IgorReader: can't read this file, "
147                    msg += "missing transmission"
148                    raise ValueError, msg
[f55af70]149                                           
[7d6351e]150            if line.count("LAMBDA") > 0:
[11a0319]151                isInfo = True
152               
153            # Find center info line
154            if isCenter:
[7d6351e]155                isCenter = False
[11a0319]156                line_toks = line.split()
[eadf1f9]157               
[7d6351e]158                # Center in bin number: Must substrate 1 because
[a7a5886]159                #the index starts from 1
[7d6351e]160                center_x = float(line_toks[0]) - 1
161                center_y = float(line_toks[1]) - 1
[11a0319]162
[7d6351e]163            if line.count("BCENT") > 0:
[11a0319]164                isCenter = True
165               
166            # Find data start
167            if line.count("***")>0:
168                dataStarted = True
169               
170                # Check that we have all the info
171                if wavelength == None \
172                    or distance == None \
173                    or center_x == None \
174                    or center_y == None:
[a7a5886]175                    msg = "IgorReader:Missing information in data file"
176                    raise ValueError, msg
[11a0319]177               
178            if dataStarted == True:
179                try:
180                    value = float(line)
181                except:
[b99ac227]182                    # Found a non-float entry, skip it
[11a0319]183                    continue
184               
185                # Get bin number
[7d6351e]186                if math.fmod(itot, i_tot_row) == 0:
[11a0319]187                    i_x = 0
188                    i_y += 1
189                else:
190                    i_x += 1
191                   
[b99ac227]192                output.data[i_y][i_x] = value
[7d6351e]193                ncounts += 1
[11a0319]194               
195                # Det 640 x 640 mm
196                # Q = 4pi/lambda sin(theta/2)
[4cc8e14b]197                # Bin size is 0.5 cm
[7d6351e]198                #REmoved +1 from theta = (i_x-center_x+1)*0.5 / distance
[a7a5886]199                # / 100.0 and
200                #REmoved +1 from theta = (i_y-center_y+1)*0.5 /
201                # distance / 100.0
202                #ToDo: Need  complete check if the following
203                # covert process is consistent with fitting.py.
[7d6351e]204                theta = (i_x - center_x) * 0.5 / distance / 100.0
205                qx = 4.0 * math.pi / wavelength * math.sin(theta/2.0)
[b99ac227]206
[ca10d8e]207                if has_converter == True and output.Q_unit != '1/A':
[b99ac227]208                    qx = data_conv_q(qx, units=output.Q_unit)
209
[7d6351e]210                if xmin == None or qx < xmin:
[11a0319]211                    xmin = qx
[7d6351e]212                if xmax == None or qx > xmax:
[11a0319]213                    xmax = qx
214               
[7d6351e]215                theta = (i_y - center_y) * 0.5 / distance / 100.0
216                qy = 4.0 * math.pi / wavelength * math.sin(theta / 2.0)
[b99ac227]217
[ca10d8e]218                if has_converter == True and output.Q_unit != '1/A':
[b99ac227]219                    qy = data_conv_q(qy, units=output.Q_unit)
220               
[7d6351e]221                if ymin == None or qy < ymin:
[11a0319]222                    ymin = qy
[7d6351e]223                if ymax == None or qy > ymax:
[11a0319]224                    ymax = qy
225               
[b99ac227]226                if not qx in x:
227                    x.append(qx)
228                if not qy in y:
229                    y.append(qy)
[11a0319]230               
231                itot += 1
232                 
233                 
234        theta = 0.25 / distance / 100.0
[7d6351e]235        xstep = 4.0 * math.pi / wavelength * math.sin(theta / 2.0)
[11a0319]236       
237        theta = 0.25 / distance / 100.0
[7d6351e]238        ystep = 4.0 * math.pi/ wavelength * math.sin(theta / 2.0)
[11a0319]239       
[b99ac227]240        # Store all data ######################################
241        # Store wavelength
[7d6351e]242        if has_converter == True and output.source.wavelength_unit != 'A':
[b99ac227]243            conv = Converter('A')
244            wavelength = conv(wavelength, units=output.source.wavelength_unit)
245        output.source.wavelength = wavelength
246
247        # Store distance
[7d6351e]248        if has_converter == True and detector.distance_unit != 'm':
[b99ac227]249            conv = Converter('m')
250            distance = conv(distance, units=detector.distance_unit)
251        detector.distance = distance
252 
253        # Store transmission
254        output.sample.transmission = transmission
[11a0319]255       
[b99ac227]256        # Store pixel size
257        pixel = 5.0
[7d6351e]258        if has_converter == True and detector.pixel_size_unit != 'mm':
[b99ac227]259            conv = Converter('mm')
260            pixel = conv(pixel, units=detector.pixel_size_unit)
261        detector.pixel_size.x = pixel
262        detector.pixel_size.y = pixel
[11a0319]263 
[b99ac227]264        # Store beam center in distance units
[7d6351e]265        detector.beam_center.x = center_x * pixel
266        detector.beam_center.y = center_y * pixel
[b99ac227]267       
268        # Store limits of the image (2D array)
[7d6351e]269        xmin = xmin - xstep / 2.0
270        xmax = xmax + xstep / 2.0
271        ymin = ymin - ystep / 2.0
272        ymax = ymax + ystep / 2.0
[ca10d8e]273        if has_converter == True and output.Q_unit != '1/A':
[b99ac227]274            xmin = data_conv_q(xmin, units=output.Q_unit)
275            xmax = data_conv_q(xmax, units=output.Q_unit)
276            ymin = data_conv_q(ymin, units=output.Q_unit)
277            ymax = data_conv_q(ymax, units=output.Q_unit)
278        output.xmin = xmin
279        output.xmax = xmax
280        output.ymin = ymin
281        output.ymax = ymax
282       
283        # Store x and y axis bin centers
[7d6351e]284        output.x_bins = x
285        output.y_bins = y
[b99ac227]286       
287        # Units
288        if data_conv_q is not None:
[b568ec1b]289            output.xaxis("\\rm{Q_{x}}", output.Q_unit)
290            output.yaxis("\\rm{Q_{y}}", output.Q_unit)
[b99ac227]291        else:
[b568ec1b]292            output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
293            output.yaxis("\\rm{Q_{y}}", 'A^{-1}')
[b99ac227]294           
295        if data_conv_i is not None:
[0e2aa40]296            output.zaxis("\\rm{Intensity}", output.I_unit)
[b99ac227]297        else:
[7d6351e]298            output.zaxis("\\rm{Intensity}", "cm^{-1}")
[b99ac227]299   
[fe78c7b]300        # Store loading process information
301        output.meta_data['loader'] = self.type_name
[eadf1f9]302        output = reader2D_converter(output)
303
[16d8e5f]304        return output
Note: See TracBrowser for help on using the repository browser.