source: trunk/imports/G2pwd_fxye.py @ 845

Last change on this file since 845 was 845, checked in by vondreele, 9 years ago

fix of fxye reader to include Goniometer radius

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2012-02-13 11:33:35 -0600 (Mon, 13 Feb 2012) $
4# $Author: vondreele & toby $
5# $Revision: 482 $
6# $URL: https://subversion.xor.aps.anl.gov/pyGSAS/trunk/G2importphase.py $
7# $Id: G2importphase.py 482 2012-02-13 17:33:35Z vondreele $
8########### SVN repository information ###################
9# a routine to read in powder data from a GSAS-compatible files
10#
11import sys
12import os.path as ospath
13import numpy as np
14import GSASIIIO as G2IO
15
16class GSAS_ReaderClass(G2IO.ImportPowderData):
17    'Routines to import powder data from a GSAS files'
18    def __init__(self):
19        super(self.__class__,self).__init__( # fancy way to self-reference
20            extensionlist=('.fxye','.raw','.gsas','.gsa','.RAW','.GSAS','.GSA'),
21            strictExtension=False,
22            formatName = 'GSAS',
23            longFormatName = 'GSAS powder data files'
24            )
25        self.clockWd = None
26
27    # Validate the contents -- look for a bank line
28    def ContentsValidator(self, filepointer):
29        #print 'ContentsValidator: '+self.formatName
30        for i,line in enumerate(filepointer):
31            self.GSAS = True
32            if i==0: # first line is always a comment
33                continue
34#            if i==1 and line[:4].lower() == 'inst' and ':' in line:
35            if i==1 and line[:4].lower() == 'inst':
36                # 2nd line is optional instrument parameter file
37                continue
38            if line[0] == '#': continue
39            if line[:4] == 'BANK':
40                return True
41            elif line[:7] == 'Monitor': continue
42            elif line [:8] == 'TIME_MAP':          #LANSCE TOF data
43                return True
44            else:
45                print 'ContentsValidator: '+self.formatName
46                print 'Unexpected information in line:',i+1 # debug info
47                print line
48                return False
49        return False # no bank records
50
51    def Reader(self,filename,filepointer, ParentFrame=None, **kwarg):
52       
53        def GetFXYEdata(File,Pos,Bank):
54            File.seek(Pos)
55            x = []
56            y = []
57            w = []
58            S = File.readline()
59            while S and S[:4] != 'BANK':
60                vals = S.split()
61                x.append(float(vals[0])/100.)               #CW: from centidegrees to degrees
62                f = float(vals[1])
63                s = float(vals[2])
64                if f <= 0.0 or s <= 0.0:
65                    y.append(0.0)
66                    w.append(1.0)
67                else:
68                    y.append(float(vals[1]))
69                    w.append(1.0/float(vals[2])**2)
70                S = File.readline()
71            N = len(x)
72            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]   
73           
74        def GetFXYdata(File,Pos,Bank):
75            File.seek(Pos)
76            x = []
77            y = []
78            w = []
79            S = File.readline()
80            while S and S[:4] != 'BANK':
81                vals = S.split()
82                x.append(float(vals[0])/100.)               #CW: from centidegrees to degrees
83                f = float(vals[1])
84                if f > 0.0:
85                    y.append(f)
86                    w.append(1.0/f)
87                else:             
88                    y.append(0.0)
89                    w.append(1.0)
90                S = File.readline()
91            N = len(x)
92            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
93           
94        def GetESDdata(File,Pos,Bank):
95            File.seek(Pos)
96            cons = Bank.split()
97            if self.clockWd:
98                start = 0
99                step = 1
100            else:
101                start = float(cons[5])/100.0               #CW: from centidegrees to degrees
102                step = float(cons[6])/100.0
103            x = []
104            y = []
105            w = []
106            S = File.readline()
107            j = 0
108            while S and S[:4] != 'BANK':
109                for i in range(0,80,16):
110                    xi = start+step*j
111                    yi = sfloat(S[i:i+8])
112                    ei = sfloat(S[i+8:i+16])
113                    x.append(xi)
114                    if yi > 0.0:
115                        y.append(yi)
116                        w.append(1.0/ei**2)
117                    else:             
118                        y.append(0.0)
119                        w.append(1.0)
120                    j += 1
121                S = File.readline()
122            N = len(x)
123            if self.clockWd:
124                x = Tmap2TOF(self.TimeMap,clockWd)
125            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
126       
127        def GetSTDdata(File,Pos,Bank):
128            File.seek(Pos)
129            cons = Bank.split()
130            Nch = int(cons[2])
131            if self.clockWd:
132                start = 0
133                step = 1
134            else:
135                start = float(cons[5])/100.0               #CW: from centidegrees to degrees
136                step = float(cons[6])/100.0                 #NB TOF 0.1*ms!
137            x = []
138            y = []
139            w = []
140            S = File.readline()
141            j = 0
142            while S and S[:4] != 'BANK':
143                for i in range(0,80,8):
144                    xi = start+step*j
145                    ni = max(sint(S[i:i+2]),1)
146                    yi = max(sfloat(S[i+2:i+8]),0.0)
147                    if yi:
148                        vi = yi/ni
149                    else:
150                        yi = 0.0
151                        vi = 1.0
152                    j += 1
153                    if j < Nch:
154                        x.append(xi)
155                        y.append(yi)
156                        w.append(1.0/vi)
157                S = File.readline()
158            N = len(x)
159            if self.clockWd:
160                x = Tmap2TOF(self.TimeMap,self.clockWd)[:-2]
161            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
162           
163        def GetTimeMap(File,Pos,TimeMap):
164            File.seek(Pos)
165            cons = TimeMap.split()
166            Nch = int(cons[1])
167            Nrec = int(cons[2])
168            clockWd = float(cons[4])/1000.          #in mus
169            TMap = np.zeros(Nch+2,dtype=int)
170            ind = 0
171            for i in range(Nrec):
172                S = File.readline().rstrip('\n')
173                vals = S.split()
174                for val in vals:
175                    TMap[ind] = int(val)
176                    ind += 1
177            TMap = np.reshape(TMap,(-1,3))
178            TMax = TMap[-1][0]
179            Nch = TMap[-2][0]+(TMax-TMap[-2][1]+TMap[-2][2]-1)/TMap[-2][2]
180            TMap[-1] = [Nch+1,TMax,0]
181            TMap = TMap.T
182            TMap[0] -= 1
183            return TMap.T,clockWd
184           
185        def Tmap2TOF(TMap,clockWd):
186            TOF = []
187            chWdt = []
188            Tch,T,Step = TMap[0]
189            for tmap in TMap[1:]:
190                tch,t,step = tmap
191                TOF += [T+Step*(i-Tch) for i in range(Tch,tch)]
192                Tch,T,Step = tmap
193            TOF = np.array(TOF)*clockWd
194            return TOF
195
196        x = []
197        y = []
198        w = []
199        Banks = []
200        Pos = []
201        rdbuffer = kwarg.get('buffer')
202        title = ''
203        comments = None
204        selections = None
205
206        # reload previously saved values
207        if self.repeat and rdbuffer is not None:
208            Banks = rdbuffer.get('Banks')
209            Pos = rdbuffer.get('Pos')
210            selections = rdbuffer.get('selections')
211            comments = rdbuffer.get('comments')
212
213        # read through the file and find the beginning of each bank
214        # Save the offset (Pos), BANK line (Banks), comments for each
215        # bank
216        if len(Banks) != len(Pos) or len(Banks) == 0:
217            try:
218                i = -1
219                while True:
220                    i += 1
221                    S = filepointer.readline()
222                    if len(S) == 0: break
223                       
224                    if i==0: # first line is always a comment
225                        title = S[:-1]
226                        comments = [[title,]]
227                        continue
228                    if i==1 and S[:4].lower() == 'inst' and ':' in S:
229                        # 2nd line is instrument parameter file (optional)
230                        self.instparm = S.split(':')[1].strip()
231                        continue
232                    if S[0] == '#': # allow comments anywhere in the file
233                        # comments in fact should only preceed BANK lines
234                        comments[-1].append(S[:-1])
235                        continue
236                    if S[:4] == 'BANK':
237                        comments.append([title,])
238                        Banks.append(S)
239                        Pos.append(filepointer.tell())
240                    if S[:8] == 'TIME_MAP':
241                        self.TimeMap,self.clockWd = GetTimeMap(filepointer,filepointer.tell(),S)
242            except Exception as detail:
243                print self.formatName+' scan error:'+str(detail) # for testing
244                import traceback
245                traceback.print_exc(file=sys.stdout)
246                return False
247
248        # Now select the bank to read
249        if not Banks: # use of ContentsValidator should prevent this error
250            print self.formatName+' scan error: no BANK records'
251            selblk = None # no block to choose
252            return False
253        elif len(Banks) == 1: # only one Bank, don't ask
254            selblk = 0
255        elif self.repeat and selections is not None:
256            # we were called to repeat the read
257            print 'debug: repeat #',self.repeatcount,'selection',selections[self.repeatcount]
258            selblk = selections[self.repeatcount]
259            self.repeatcount += 1
260            if self.repeatcount >= len(selections): self.repeat = False
261        else:                       # choose from options
262            selections = self.MultipleBlockSelector(
263                Banks,
264                ParentFrame=ParentFrame,
265                title='Select Bank(s) to read from the list below',
266                size=(600,100),
267                header='Dataset Selector')
268            if len(selections) == 0: return False
269            selblk = selections[0] # select first in list
270            if len(selections) > 1: # prepare to loop through again
271                self.repeat = True
272                self.repeatcount = 1
273                if rdbuffer is not None:
274                    rdbuffer['Banks'] = Banks
275                    rdbuffer['Pos'] = Pos
276                    rdbuffer['selections'] = selections
277                    rdbuffer['comments'] = comments
278
279        # got a selection, now read it
280        Bank = Banks[selblk]
281        try:
282            if 'FXYE' in Bank:
283                self.powderdata = GetFXYEdata(filepointer,Pos[selblk],Banks[selblk])
284            elif 'FXY' in Bank:
285                self.powderdata = GetFXYdata(filepointer,Pos[selblk],Banks[selblk])
286            elif 'ESD' in Bank:
287                self.powderdata = GetESDdata(filepointer,Pos[selblk],Banks[selblk])
288            elif 'STD' in Bank:
289                self.powderdata = GetSTDdata(filepointer,Pos[selblk],Banks[selblk])
290            else:
291                self.powderdata = GetSTDdata(filepointer,Pos[selblk],Banks[selblk])
292        except Exception as detail:
293            print self.formatName+' read error:'+str(detail) # for testing
294            import traceback
295            traceback.print_exc(file=sys.stdout)
296            return False
297        if comments is not None:
298            self.comments = comments[selblk]
299        self.powderentry[0] = filename
300        self.powderentry[1] = Pos # position offset (never used, I hope)
301        self.powderentry[2] = selblk+1 # bank number
302        self.idstring = ospath.basename(filename) + ' Bank '+str(selblk+1)
303        self.numbanks=len(Banks)
304        # scan comments for temperature
305        Temperature = 300
306        Radius = 200
307        for S in self.comments:
308            if 'Temp' in S.split('=')[0]:
309                try:
310                    Temperature = float(S.split('=')[1])
311                except:
312                    pass
313            elif 'Gonio' in S.split('=')[0]:
314                try:
315                    Radius = float(S.split('=')[1])
316                except:
317                    pass
318        self.Sample['Temperature'] = Temperature
319        self.Sample['Gonio. radius'] = Radius
320        return True       
321
322def sfloat(S):
323    'convert a string to a float, treating an all-blank string as zero'
324    if S.strip():
325        return float(S)
326    else:
327        return 0.0
328
329def sint(S):
330    'convert a string to an integer, treating an all-blank string as zero'
331    if S.strip():
332        return int(S)
333    else:
334        return 0
Note: See TracBrowser for help on using the repository browser.