source: sasview/DataLoader/readers/red2d_reader.py @ e9b12eaf

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 e9b12eaf was 59a2dab, checked in by Jae Cho <jhjcho@…>, 15 years ago

improve handling dq a bit

  • Property mode set to 100644
File size: 10.7 KB
Line 
1"""
2    TXT/IGOR 2D Q Map file reader
3"""
4
5"""
6This software was developed by the University of Tennessee as part of the
7Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
8project funded by the US National Science Foundation.
9
10If you use DANSE applications to do scientific research that leads to
11publication, we ask that you acknowledge the use of the software with the
12following sentence:
13
14"This work benefited from DANSE software developed under NSF award DMR-0520547."
15
16copyright 2008, University of Tennessee
17"""
18
19import os, sys
20import numpy
21import math, logging
22from DataLoader.data_info import Data2D, Detector
23
24# Look for unit converter
25has_converter = True
26try:
27    from data_util.nxsunit import Converter
28except:
29    has_converter = False
30
31class Reader:
32    """ Simple data reader for Igor data files """
33    ## File type
34    type_name = "IGOR/DAT 2D Q_map"   
35    ## Wildcards
36    type = ["IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"]
37    ## Extension
38    ext=['.DAT', '.dat']
39
40    def read(self,filename=None):
41        """ Read file """
42        if not os.path.isfile(filename):
43            raise ValueError, \
44            "Specified file %s is not a regular file" % filename
45
46        # Read file
47        f = open(filename,'r')
48        buf = f.read()
49        f.close()     
50        # Instantiate data object
51        output = Data2D()
52        output.filename = os.path.basename(filename)
53        detector = Detector()
54        if len(output.detector)>0: print str(output.detector[0])
55        output.detector.append(detector)
56               
57        # Get content
58        dataStarted = False
59       
60        ## Defaults     
61        lines = buf.split('\n')
62        itot = 0
63        x = []
64        y = []
65       
66        ncounts = 0
67       
68        wavelength   = None
69        distance     = None
70        transmission = None
71       
72        pixel_x = None
73        pixel_y = None
74       
75        i_x    = 0
76        i_y    = -1
77        pixels = 0
78       
79        isInfo   = False
80        isCenter = False
81
82        data_conv_q = None
83        data_conv_i = None
84       
85        # Set units: This is the unit assumed for Q and I in the data file.
86        if has_converter == True and output.Q_unit != '1/A':
87            data_conv_q = Converter('1/A')
88            # Test it
89            data_conv_q(1.0, output.Q_unit)
90           
91        if has_converter == True and output.I_unit != '1/cm':
92            data_conv_i = Converter('1/cm')
93            # Test it
94            data_conv_i(1.0, output.I_unit)           
95       
96             
97        # Remove the last lines before the for loop if the lines are empty
98        # to calculate the exact number of data points
99        count = 0
100        while (len(lines[len(lines)-(count+1)].lstrip().rstrip()) < 1):
101            del lines[len(lines)-(count+1)]
102            count = count + 1
103
104        #Read Header and find the dimensions of 2D data
105        line_num = 0
106        for line in lines:     
107            line_num += 1
108            ## Reading the header applies only to IGOR/NIST 2D q_map data files
109            # Find setup info line
110            if isInfo:
111                isInfo = False
112                line_toks = line.split()
113                # Wavelength in Angstrom
114                try:
115                    wavelength = float(line_toks[1])
116                    # Units
117                    if has_converter==True and output.source.wavelength_unit != 'A':
118                        conv = Converter('A')
119                        wavelength = conv(wavelength, units=output.source.wavelength_unit)
120                except:
121                    #Not required
122                    pass
123                # Distance in mm
124                try:
125                    distance = float(line_toks[3])
126                    # Units
127                    if has_converter==True and detector.distance_unit != 'm':
128                        conv = Converter('m')
129                        distance = conv(distance, units=detector.distance_unit)
130                except:
131                    #Not required
132                    pass
133               
134                # Distance in meters
135                try:
136                    transmission = float(line_toks[4])
137                except:
138                    #Not required
139                    pass
140                                           
141            if line.count("LAMBDA")>0:
142                isInfo = True
143               
144            # Find center info line
145            if isCenter:
146                isCenter = False               
147                line_toks = line.split()
148                # Center in bin number
149                center_x = float(line_toks[0])
150                center_y = float(line_toks[1])
151
152            if line.count("BCENT")>0:
153                isCenter = True
154                       
155            # Find data start
156            if line.count("Data columns") or line.count("ASCII data")>0:
157                dataStarted = True
158                continue
159
160            ## Read and get data.   
161            if dataStarted == True:
162                line_toks = line.split()             
163                if len(line_toks) == 0:
164                    #empty line
165                    continue
166                # the number of columns must be stayed same
167                col_num = len(line_toks)
168                break
169
170       
171        # Make numpy array to remove header lines using index
172        lines_array = numpy.array(lines)
173
174        # index for lines_array
175        lines_index = numpy.arange(len(lines))
176       
177        # get the data lines
178        data_lines = lines_array[lines_index>=(line_num-1)]
179        # Now we get the total number of rows (i.e., # of data points)
180        row_num = len(data_lines)
181        # make it as list again to control the separators
182        data_list = " ".join(data_lines.tolist())
183        # split all data to one big list w/" "separator
184        data_list = data_list.split()
185 
186        # Check if the size is consistent with data, otherwise try the tab(\t) separator
187        # (this may be removed once get the confidence the former working all cases).
188        if len(data_list) != (len(data_lines)) * col_num:
189            data_list = "\t".join(data_lines.tolist())
190            data_list = data_list.split()
191           
192        # Change it(string) into float
193        data_list = map(float,data_list)
194        # numpy array form
195        data_array = numpy.array(data_list)
196
197        # Redimesion based on the row_num and col_num, otherwise raise an error.
198        try:
199            data_point = data_array.reshape(row_num,col_num).transpose()
200        except:
201            raise ValueError, "red2d_reader: Can't read this file: Not a proper file format"
202       
203        ## Get the all data: Let's HARDcoding; Todo find better way
204        # Defaults
205        dqx_data = numpy.zeros(0)
206        dqy_data = numpy.zeros(0)
207        qz_data = numpy.zeros(row_num)
208        mask = numpy.ones(row_num,dtype=bool)
209        # Get from the array
210        qx_data = data_point[0]
211        qy_data = data_point[1]
212        data = data_point[2]
213        if col_num >3: qz_data = data_point[3]
214        if col_num >4: dqx_data = data_point[4]
215        if col_num >5: dqy_data = data_point[5]
216        if col_num >6: mask[data_point[6]<1] = False
217        q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data+qz_data*qz_data)
218           
219        # Extra protection(it is needed for some data files):
220        # If all mask elements are False, put all True
221        if not mask.any(): mask[mask==False] = True   
222 
223        # Store limits of the image in q space
224        xmin    = numpy.min(qx_data)
225        xmax    = numpy.max(qx_data)
226        ymin    = numpy.min(qy_data)
227        ymax    = numpy.max(qy_data)
228
229        # units
230        if has_converter == True and output.Q_unit != '1/A':
231            xmin = data_conv_q(xmin, units=output.Q_unit)
232            xmax = data_conv_q(xmax, units=output.Q_unit)
233            ymin = data_conv_q(ymin, units=output.Q_unit)
234            ymax = data_conv_q(ymax, units=output.Q_unit)
235           
236        ## calculate the range of the qx and qy_data
237        x_size = math.fabs(xmax - xmin)
238        y_size = math.fabs(ymax - ymin)
239       
240        # calculate the number of pixels in the each axes
241        npix_y = math.floor(math.sqrt(len(data)))
242        npix_x = math.floor(len(data)/npix_y)
243       
244        # calculate the size of bins     
245        xstep = x_size/(npix_x-1)
246        ystep = y_size/(npix_y-1)
247       
248        # store x and y axis bin centers in q space
249        x_bins  = numpy.arange(xmin,xmax+xstep,xstep)
250        y_bins  = numpy.arange(ymin,ymax+ystep,ystep)
251       
252        # get the limits of q values
253        xmin = xmin - xstep/2
254        xmax = xmax + xstep/2
255        ymin = ymin - ystep/2
256        ymax = ymax + ystep/2
257       
258        #Store data in outputs 
259        #TODO: Check the lengths
260        output.data     = data
261        output.err_data = numpy.sqrt(numpy.abs(data))
262        output.qx_data  = qx_data
263        output.qy_data  = qy_data             
264        output.q_data   = q_data
265        output.mask     = mask
266       
267        output.x_bins = x_bins
268        output.y_bins = y_bins
269               
270        output.xmin = xmin
271        output.xmax = xmax
272        output.ymin = ymin
273        output.ymax = ymax
274       
275        output.source.wavelength = wavelength
276       
277        # Store pixel size in mm
278        detector.pixel_size.x = pixel_x
279        detector.pixel_size.y = pixel_y
280       
281        # Store the sample to detector distance
282        detector.distance = distance
283       
284        # optional data: if all of dq data == 0, do not pass to output
285        if len(dqx_data) == len(qx_data) and dqx_data.any()!=0: 
286            # if no dqx_data, do not pass dqy_data.(1 axis dq is not supported yet).
287            if len(dqy_data) == len(qy_data) and dqy_data.any()!=0:
288                output.dqx_data = dqx_data
289                output.dqy_data = dqy_data
290       
291        # Units of axes
292        if data_conv_q is not None:
293            output.xaxis("\\rm{Q_{x}}", output.Q_unit)
294            output.yaxis("\\rm{Q_{y}}", output.Q_unit)
295        else:
296            output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
297            output.yaxis("\\rm{Q_{y}}", 'A^{-1}')           
298        if data_conv_i is not None:
299            output.zaxis("\\rm{Intensity}", output.I_unit)
300        else:
301            output.zaxis("\\rm{Intensity}","cm^{-1}")
302   
303        # Store loading process information
304        output.meta_data['loader'] = self.type_name
305
306        return output
307   
308if __name__ == "__main__": 
309    reader = Reader()
310    print reader.read("../test/exp18_14_igor_2dqxqy.dat") 
311       
312
Note: See TracBrowser for help on using the repository browser.