source: trunk/imports/G2pwd_fxye.py @ 1834

Last change on this file since 1834 was 1834, checked in by vondreele, 8 years ago

redefine azimuthal angle in Sample Parms as the center of the azimuthal bin; the azimuthat angle in Instrument parms is defined as the mean angle for polarization (only 0-90 & slightly different)
some cosmetic changes to GUI displays
fix imports/G2pwd_fxye.py to handle multi time-maps found in HIPPO data & the slightly screwy one in HIPD data

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 17.1 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2015-05-04 14:10:23 +0000 (Mon, 04 May 2015) $
4# $Author: vondreele $
5# $Revision: 1834 $
6# $URL: trunk/imports/G2pwd_fxye.py $
7# $Id: G2pwd_fxye.py 1834 2015-05-04 14:10:23Z vondreele $
8########### SVN repository information ###################
9'''
10*Module G2pwd_fxye: GSAS data files*
11------------------------------------
12Routine to read in powder data in a variety of formats
13that are defined for GSAS.
14
15'''
16import sys
17import os.path as ospath
18import numpy as np
19import GSASIIIO as G2IO
20import GSASIIpath
21GSASIIpath.SetVersionNumber("$Revision: 1834 $")
22
23class GSAS_ReaderClass(G2IO.ImportPowderData):
24    'Routines to import powder data from a GSAS files'
25    def __init__(self):
26        super(self.__class__,self).__init__( # fancy way to self-reference
27            extensionlist=('.fxye','.raw','.gsas','.gda','gsa.','.RAW','.GSAS','.GDA','.GSA'),
28            strictExtension=False,
29            formatName = 'GSAS powder data',
30            longFormatName = 'GSAS powder data files (.fxye, .raw, .gsas...)'
31            )
32        self.clockWd = {}
33        self.TimeMap = {}
34
35    # Validate the contents -- look for a bank line
36    def ContentsValidator(self, filepointer):
37        'Validate by checking to see if the file has BANK lines'
38        #print 'ContentsValidator: '+self.formatName
39        for i,line in enumerate(filepointer):
40            self.GSAS = True
41            if i==0: # first line is always a comment
42                continue
43            if i==1 and line[:4].lower() == 'inst':
44                # 2nd line is optional instrument parameter file
45                continue
46            if line[0] == '#': continue
47            if line[:4] == 'BANK':
48                return True
49            elif line[:7] == 'Monitor': continue
50            elif line [:8] == 'TIME_MAP':          #LANSCE TOF data
51                return True
52            else:
53                self.errors = 'Unexpected information in line: '+str(i+1)
54                self.errors += '  '+str(line)
55                return False
56        return False # no bank records
57
58    def Reader(self,filename,filepointer, ParentFrame=None, **kwarg):
59        '''Read a GSAS (old formats) file of type FXY, FXYE, ESD or STD types.
60        If multiple datasets are requested, use self.repeat and buffer caching.
61        '''
62        def GetFXYEdata(File,Pos,Bank):
63            File.seek(Pos)
64            x = []
65            y = []
66            w = []
67            S = File.readline()
68            while S and S[:4] != 'BANK' and S[0] != '#':
69                vals = S.split()
70                x.append(float(vals[0])/100.)               #CW: from centidegrees to degrees
71                f = float(vals[1])
72                s = float(vals[2])
73                if f <= 0.0 or s <= 0.0:
74                    y.append(0.0)
75                    w.append(0.0)
76                else:
77                    y.append(float(vals[1]))
78                    w.append(1.0/float(vals[2])**2)
79                S = File.readline()
80            N = len(x)
81            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]   
82           
83        def GetFXYdata(File,Pos,Bank):
84            File.seek(Pos)
85            x = []
86            y = []
87            w = []
88            S = File.readline()
89            while S and S[:4] != 'BANK' and S[0] != '#':
90                vals = S.split()
91                x.append(float(vals[0])/100.)               #CW: from centidegrees to degrees
92                f = float(vals[1])
93                if f > 0.0:
94                    y.append(f)
95                    w.append(1.0/f)
96                else:             
97                    y.append(0.0)
98                    w.append(0.0)
99                S = File.readline()
100            N = len(x)
101            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
102           
103        def GetESDdata(File,Pos,Bank):
104            File.seek(Pos)
105            cons = Bank.split()
106            if 'TIME_MAP' == cons[4]:
107                start = 0
108                step = 1
109            else:
110                start = float(cons[5])/100.0               #CW: from centidegrees to degrees
111                step = float(cons[6])/100.0
112            x = []
113            y = []
114            w = []
115            S = File.readline()
116            j = 0
117            while S and S[:4] != 'BANK' and S[0] != '#':
118                if 'TIME_MAP' in S:
119                    break
120                for i in range(0,80,16):
121                    if S[i:i+8] == 8*' ':
122                        break
123                    xi = start+step*j
124                    yi = sfloat(S[i:i+8])
125                    ei = sfloat(S[i+8:i+16])
126                    x.append(xi)
127                    if yi > 0.0:
128                        y.append(yi)
129                        w.append(1.0/ei**2)
130                    else:             
131                        y.append(0.0)
132                        w.append(0.0)
133                    j += 1
134                S = File.readline()
135            N = len(x)
136            if self.clockWd:
137                if len(self.clockWd) == 1:
138                    x = Tmap2TOF(self.TimeMap['1'],self.clockWd['1'])
139                else:
140                    x = Tmap2TOF(self.TimeMap[cons[5]],self.clockWd[cons[5]])
141            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
142       
143        def GetSTDdata(File,Pos,Bank):
144            File.seek(Pos)
145            cons = Bank.split()
146            Nch = int(cons[2])
147            if self.clockWd:
148                start = 0
149                step = 1
150            else:
151                start = float(cons[5])/100.0               #CW: from centidegrees to degrees
152                step = float(cons[6])/100.0                 #NB TOF 0.1*ms!
153            x = []
154            y = []
155            w = []
156            S = File.readline()
157            j = 0
158            while S and S[:4] != 'BANK' and S[0] != '#':
159                for i in range(0,80,8):
160                    if S[i:i+10] == 10*' ':
161                        break
162                    xi = start+step*j
163                    ni = max(sint(S[i:i+2]),1)
164                    yi = max(sfloat(S[i+2:i+8]),0.0)
165                    if yi:
166                        vi = yi/ni
167                    else:
168                        yi = 0.0
169                        vi = 0.0
170                    j += 1
171                    if j < Nch:
172                        x.append(xi)
173                        if vi <= 0.:
174                            y.append(0.)
175                            w.append(0.)
176                        else:
177                            y.append(yi)
178                            w.append(1.0/vi)
179                S = File.readline()
180            N = len(x)
181            if self.clockWd:
182                if len(self.clockWd) == 1:
183                    x = Tmap2TOF(self.TimeMap['1'],self.clockWd['1'])
184                else:
185                    x = Tmap2TOF(self.TimeMap[cons[5]],self.clockWd[cons[5]])
186            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
187           
188        def GetALTdata(File,Pos,Bank):
189            File.seek(Pos)
190            cons = Bank.split()
191            x = []
192            y = []
193            w = []
194            S = File.readline()
195            j = 0
196            while S and S[:4] != 'BANK' and S[0] != '#':
197                for i in range(0,80,20):
198                    if S[i:i+8] == 9*' ':
199                        break
200                    xi = sfloat(S[i:i+9])/3200.
201                    yi = sfloat(S[i+9:i+16])/1000.
202                    ei = sfloat(S[i+16:i+21])/1000.
203                    x.append(xi)
204                    if yi > 0.0:
205                        y.append(yi)
206                        w.append(1.0/ei**2)
207                    else:             
208                        y.append(0.0)
209                        w.append(0.0)
210                    j += 1
211                S = File.readline()
212            N = len(x)
213            if self.clockWd:
214                x = Tmap2TOF(self.TimeMap[cons[5]],self.clockWd[cons[5]])
215            return [np.array(x),np.array(y),np.array(w),np.zeros(N),np.zeros(N),np.zeros(N)]
216           
217        def GetTimeMap(File,Pos,TimeMap):
218            File.seek(Pos)
219            cons = TimeMap[8:].split()
220            mapNo = cons[0]
221            if 'TIME_MAP10' in TimeMap: mapNo = '1'   #HIPD cluge!
222            Nch = int(cons[1])
223            Nrec = int(cons[2])
224            clockWd = float(cons[4])/1000.          #in mus
225            TMap = np.zeros(Nch+2,dtype=int)
226            ind = 0
227            for i in range(Nrec):
228                S = File.readline().rstrip('\n')
229                vals = S.split()
230                for val in vals:
231                    TMap[ind] = int(val)
232                    ind += 1
233            TMap = np.reshape(TMap,(-1,3))
234            TMax = TMap[-1][0]
235            Nch = TMap[-2][0]+(TMax-TMap[-2][1]+TMap[-2][2]-1)/TMap[-2][2]
236            TMap[-1] = [Nch+1,TMax,0]
237            TMap = TMap.T
238            TMap[0] -= 1
239            return TMap.T,clockWd,mapNo
240           
241        def Tmap2TOF(TMap,clockWd):
242            TOF = []
243            chWdt = []
244            Tch,T,Step = TMap[0]
245            for tmap in TMap[1:]:
246                tch,t,step = tmap
247                TOF += [T+Step*(i-Tch) for i in range(Tch,tch)]
248                Tch,T,Step = tmap
249            TOF = np.array(TOF)*clockWd
250            return TOF
251
252        x = []
253        y = []
254        w = []
255        Banks = []
256        Pos = []
257        rdbuffer = kwarg.get('buffer')
258        title = ''
259        comments = None
260#        selections = None
261
262        # reload previously saved values
263        if self.repeat and rdbuffer is not None:
264            Banks = rdbuffer.get('Banks')
265            Pos = rdbuffer.get('Pos')
266            self.selections = rdbuffer.get('selections')
267            comments = rdbuffer.get('comments')
268
269        # read through the file and find the beginning of each bank
270        # Save the offset (Pos), BANK line (Banks), comments for each bank
271        #
272        # This is going to need a fair amount of work to track line numbers
273        # in the input file.
274        if len(Banks) != len(Pos) or len(Banks) == 0:
275            try:
276                i = -1
277                while True:
278                    i += 1
279                    S = filepointer.readline()
280                    if len(S) == 0: break
281                       
282                    if i==0: # first line is always a comment
283                        self.errors = 'Error reading title'
284                        title = S[:-1]
285                        comments = [[title,]]
286                        continue
287                    if i==1 and S[:4].lower() == 'inst' and ':' in S:
288                        # 2nd line is instrument parameter file (optional)
289                        self.errors = 'Error reading instrument parameter filename'
290                        self.instparm = S.split(':')[1].strip('[]').strip()
291                        continue
292                    if S[0] == '#': # allow comments anywhere in the file
293                        # comments in fact should only preceed BANK lines
294                        comments[-1].append(S[:-1])
295                        continue
296                    if S[:4] == 'BANK':
297                        self.errors = 'Error reading bank:'
298                        self.errors += '  '+str(S)
299                        comments.append([title,])
300                        Banks.append(S)
301                        Pos.append(filepointer.tell())
302                    if S[:8] == 'TIME_MAP':     #assumes one time map; HIPPO has multiple time maps
303                        if len(Banks) == 0:
304                            self.errors = 'Error reading time map before any bank lines'
305                        else:
306                            self.errors = 'Error reading time map after bank:\n  '+str(Banks[-1])
307                        timemap,clockwd,mapNo = GetTimeMap(filepointer,filepointer.tell(),S)
308                        self.TimeMap[mapNo] = timemap
309                        self.clockWd[mapNo] = clockwd
310                       
311            except Exception as detail:
312                self.errors += '\n  '+str(detail)
313                print self.formatName+' scan error:'+str(detail) # for testing
314                import traceback
315                traceback.print_exc(file=sys.stdout)
316                return False
317
318        # Now select the bank to read
319        if not Banks: # use of ContentsValidator should prevent this error
320            print self.formatName+' scan error: no BANK records'
321            selblk = None # no block to choose
322            self.errors = 'No BANK records found (strange!)'
323            return False
324        elif len(Banks) == 1: # only one Bank, don't ask
325            selblk = 0
326        elif self.repeat and self.selections is not None:
327            # we were called to repeat the read
328            #print 'debug: repeat #',self.repeatcount,'selection',self.selections[self.repeatcount]
329            selblk = self.selections[self.repeatcount]
330            self.repeatcount += 1
331            if self.repeatcount >= len(self.selections): self.repeat = False
332        else:                       # choose from options
333            if not len(self.selections):    #use previous selection, otherwise...
334                self.selections = self.MultipleBlockSelector(
335                    Banks,
336                    ParentFrame=ParentFrame,
337                    title='Select Bank(s) to read from the list below',
338                    size=(600,100),
339                    header='Dataset Selector')
340            if len(self.selections) == 0: return False
341            selblk = self.selections[0] # select first in list
342            if len(self.selections) > 1: # prepare to loop through again
343                self.repeat = True
344                self.repeatcount = 1
345                if rdbuffer is not None:
346                    rdbuffer['Banks'] = Banks
347                    rdbuffer['Pos'] = Pos
348                    rdbuffer['selections'] = self.selections
349                    rdbuffer['comments'] = comments
350
351        # got a selection, now read it
352        Bank = Banks[selblk]
353        try:
354            bnkNo = int(Bank.split()[1])
355        except ValueError:
356            bnkNo = 1
357        try:
358            if 'FXYE' in Bank:
359                self.errors = 'Error reading FXYE data in Bank\n  '+Banks[selblk]
360                self.powderdata = GetFXYEdata(filepointer,Pos[selblk],Banks[selblk])
361            elif 'FXY' in Bank:
362                self.errors = 'Error reading FXY data in Bank\n  '+Banks[selblk]
363                self.powderdata = GetFXYdata(filepointer,Pos[selblk],Banks[selblk])
364            elif 'ESD' in Bank:
365                self.errors = 'Error reading ESD data in Bank\n  '+Banks[selblk]
366                self.powderdata = GetESDdata(filepointer,Pos[selblk],Banks[selblk])
367            elif 'STD' in Bank:
368                self.errors = 'Error reading STD data in Bank\n  '+Banks[selblk]
369                self.powderdata = GetSTDdata(filepointer,Pos[selblk],Banks[selblk])
370            elif 'ALT' in Bank:
371                self.errors = 'Error reading ALT data in Bank\n  '+Banks[selblk]
372                self.powderdata = GetALTdata(filepointer,Pos[selblk],Banks[selblk])
373            else:
374                self.errors = 'Error reading STD data in Bank\n  '+Banks[selblk]
375                self.powderdata = GetSTDdata(filepointer,Pos[selblk],Banks[selblk])
376        except Exception as detail:
377            self.errors += '\n  '+str(detail)
378            print self.formatName+' read error:'+str(detail) # for testing
379            import traceback
380            traceback.print_exc(file=sys.stdout)
381            return False
382
383        self.errors = 'Error processing information after read complete'
384        if comments is not None:
385            self.comments = comments[selblk]
386        self.powderentry[0] = filename
387        self.powderentry[1] = Pos # position offset (never used, I hope)
388        self.powderentry[2] = bnkNo #selblk+1 # bank number
389        self.idstring = ospath.basename(filename) + ' Bank '+str(bnkNo) #selblk+1)
390        self.numbanks=len(Banks)
391        # scan comments for temperature & radius
392        Temperature = 300.
393        for S in self.comments:
394            if 'Temp' in S.split('=')[0]:
395                try:
396                    Temperature = float(S.split('=')[1])
397                except:
398                    pass
399            elif 'Gonio' in S.split('=')[0]:
400                try:
401                    self.Sample['Gonio. radius'] = float(S.split('=')[1])
402                except:
403                    pass
404            elif 'Omega' in S.split('=')[0] or 'Theta' in S.split('=')[0]:  #HIPD weirdness
405                try:
406                    self.Sample['Omega'] = 90.-float(S.split('=')[1])
407                except:
408                    pass
409            elif 'Chi' in S.split('=')[0]:
410                try:
411                    self.Sample['Chi'] = -float(S.split('=')[1])
412                except:
413                    pass                   
414            elif 'Phi' in S.split('=')[0]:
415                try:
416                    self.Sample['Phi'] = float(S.split('=')[1])
417                except:
418                    pass                   
419        self.Sample['Temperature'] = Temperature
420        return True       
421
422def sfloat(S):
423    'convert a string to a float, treating an all-blank string as zero'
424    if S.strip():
425        return float(S)
426    else:
427        return 0.0
428
429def sint(S):
430    'convert a string to an integer, treating an all-blank string as zero'
431    if S.strip():
432        return int(S)
433    else:
434        return 0
Note: See TracBrowser for help on using the repository browser.