source: trunk/imports/G2pwd_fxye.py @ 2927

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

fixes to scripts & fxye importer

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