source: trunk/imports/G2pwd_xye.py @ 3757

Last change on this file since 3757 was 3757, checked in by toby, 4 years ago

fix reading of FullProf? & WinPLOTR-2006 files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 7.9 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2018-12-07 22:03:37 +0000 (Fri, 07 Dec 2018) $
4# $Author: toby $
5# $Revision: 3757 $
6# $URL: trunk/imports/G2pwd_xye.py $
7# $Id: G2pwd_xye.py 3757 2018-12-07 22:03:37Z toby $
8########### SVN repository information ###################
9'''
10*Module G2pwd_xye: Topas .xye data*
11------------------------------------
12
13Routine to read in powder data from a Topas-compatible .xye file
14
15'''
16
17from __future__ import division, print_function
18import os.path as ospath
19import numpy as np
20import GSASIIobj as G2obj
21import GSASIIpath
22
23asind = lambda x: 180.*np.arcsin(x)/np.pi
24
25GSASIIpath.SetVersionNumber("$Revision: 3757 $")
26class xye_ReaderClass(G2obj.ImportPowderData):
27    'Routines to import powder data from a .xye/.chi file'
28    def __init__(self):
29        super(self.__class__,self).__init__( # fancy way to self-reference
30            extensionlist=('.xye','.chi','.qchi',),
31            strictExtension=False,
32            formatName = 'Topas xye or 2th Fit2D chi',
33            longFormatName = 'Topas .xye or 2th Fit2D .chi/.qchi powder data file'
34            )
35        self.scriptable = True
36
37    # Validate the contents -- make sure we only have valid lines
38    def ContentsValidator(self, filename):
39        'Look through the file for expected types of lines in a valid Topas file'
40        gotCcomment = False
41        begin = True
42        self.GSAS = False
43        self.Chi = False
44        Qchi = False
45        self.Wave = None
46        fp = open(filename,'r')
47        if '.chi' in filename:
48            self.Chi = True
49        if '.qchi' in filename:
50            Qchi = True
51        if2theta = False
52        ifQ = False
53        for i,S in enumerate(fp):
54            if not S:
55                break
56            if i > 1000: break
57            if begin:
58                if self.Chi or Qchi:
59                    if i < 4:
60                        if  '2-theta' in S.lower():
61                            if2theta = True
62                        elif  'q ' in S.lower():
63                            ifQ = True
64                            wave = ''
65                            wave = S.split()[1:]
66                            if wave: 
67                                try:
68                                    self.Wave = float(wave[0])
69                                except:
70                                    pass
71                            if not self.Wave:
72                                self.errors = 'No wavelength in a Q chi file'
73                                fp.close()
74                                return False
75                        continue
76                    else:
77                        begin = False
78                else:
79                    if2theta = True
80                    if  i == 0 and 'xydata' in S.lower():
81                        continue   # fullprof header
82                    if gotCcomment and S.find('*/') > -1:
83                        begin = False
84                        continue
85                    if S.strip().startswith('/*'):
86                        gotCcomment = True
87                        continue   
88                    if S[0] in ["'",'#','!']:
89                        continue       #ignore comments, if any
90                    elif S.startswith('TITLE'):
91                        continue
92                    else:
93                        begin = False
94                # valid line to read?
95            #vals = S.split()
96            if ifQ:
97                pass
98            elif not if2theta:
99                self.errors = 'Not a 2-theta chi file'
100                fp.close()
101                return False
102            vals = S.replace(',',' ').replace(';',' ').split()
103            if len(vals) == 2 or len(vals) == 3:
104                continue
105            else:
106                self.errors = 'Unexpected information in line: '+str(i+1)
107                if all([ord(c) < 128 and ord(c) != 0 for c in str(S)]): # show only if ASCII
108                    self.errors += '  '+str(S)
109                else: 
110                    self.errors += '  (binary)'
111                fp.close()
112                return False
113        fp.close()
114        return True # no errors encountered
115
116    def Reader(self,filename, ParentFrame=None, **unused):
117        'Read a Topas file'
118        x = []
119        y = []
120        w = []
121        gotCcomment = False
122        begin = True
123        fp = open(filename,'r')
124        for i,S in enumerate(fp):
125            self.errors = 'Error reading line: '+str(i+1)
126            # or a block of comments delimited by /* and */
127            # or (GSAS style) each line can begin with '#'
128            # or WinPLOTR style, a '!'
129            if begin:
130                if self.Chi or self.Wave:
131                    if i < 4:
132                        continue
133                    else:
134                        begin = False
135                else:       
136                    if gotCcomment and S.find('*/') > -1:
137                        self.comments.append(S[:-1])
138                        begin = False
139                        continue
140                    if S.strip().startswith('/*'):
141                        self.comments.append(S[:-1])
142                        gotCcomment = True
143                        continue   
144                    if S[0] in ["'",'#','!']:
145                        self.comments.append(S[:-1])
146                        continue       #ignore comments, if any
147                    elif  i == 0 and 'xydata' in S.lower():
148                        continue   # fullprof header
149                    elif S.startswith('TITLE'):
150                        self.comments = [S]
151                        continue
152                    else:
153                        begin = False
154            # valid line to read
155            #vals = S.split()
156            vals = S.replace(',',' ').replace(';',' ').split()
157            if len(vals) < 2:
158                print ('Line '+str(i+1)+' cannot be read:\n\t'+S)
159                continue
160            try:
161                if self.Wave:
162                    try:
163                        val = min(0.995,self.Wave/(4.*np.pi/float(vals[0])))  #set max at 168deg
164                        x.append(2.0*asind(val))
165                    except:
166                        msg = 'Error converting '+str(vals[0]
167                        ) + 'with wavelength ' + str(self.Wave) 
168                        break
169                else:
170                    x.append(float(vals[0]))
171                f = float(vals[1])
172                if f <= 0.0:
173                    y.append(0.0)
174                    w.append(0.0)
175                elif len(vals) == 3:
176                    y.append(float(vals[1]))
177                    w.append(1.0/float(vals[2])**2)
178                else:
179                    y.append(float(vals[1]))
180                    w.append(1.0/float(vals[1]))
181            except ValueError:
182                msg = 'Error parsing number in line '+str(i+1)
183                if GSASIIpath.GetConfigValue('debug'):
184                    print (msg)
185                    print (S.strip())
186                break
187            except:
188                msg = 'Error in line '+str(i+1)
189                if GSASIIpath.GetConfigValue('debug'):
190                    print (msg)
191                    print (S.strip())
192                break
193        N = len(x)
194        self.powderdata = [
195            np.array(x), # x-axis values
196            np.array(y), # powder pattern intensities
197            np.array(w), # 1/sig(intensity)^2 values (weights)
198            np.zeros(N), # calc. intensities (zero)
199            np.zeros(N), # calc. background (zero)
200            np.zeros(N), # obs-calc profiles
201            ]
202        self.powderentry[0] = filename
203        #self.powderentry[1] = pos # bank offset (N/A here)
204        #self.powderentry[2] = 1 # xye file only has one bank
205        self.idstring = ospath.basename(filename)
206        # scan comments for temperature
207        Temperature = 300
208        for S in self.comments:
209            if 'temp' in S.lower().split('=')[0]:
210                try:
211                    Temperature = float(S.split('=')[1])
212                except:
213                    pass
214        self.Sample['Temperature'] = Temperature
215        fp.close()
216        return True
Note: See TracBrowser for help on using the repository browser.