source: trunk/imports/G2pwd_xye.py @ 3670

Last change on this file since 3670 was 3670, checked in by toby, 3 years ago

read in qchi files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 7.4 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2018-10-11 16:52:33 +0000 (Thu, 11 Oct 2018) $
4# $Author: toby $
5# $Revision: 3670 $
6# $URL: trunk/imports/G2pwd_xye.py $
7# $Id: G2pwd_xye.py 3670 2018-10-11 16:52:33Z 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: 3670 $")
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 gotCcomment and S.find('*/') > -1:
81                        begin = False
82                        continue
83                    if S.strip().startswith('/*'):
84                        gotCcomment = True
85                        continue   
86                    if S[0] in ["'",'#']:
87                        continue       #ignore comments, if any
88                    else:
89                        begin = False
90                # valid line to read?
91            #vals = S.split()
92            if ifQ:
93                pass
94            elif not if2theta:
95                self.errors = 'Not a 2-theta chi file'
96                fp.close()
97                return False
98            vals = S.replace(',',' ').replace(';',' ').split()
99            if len(vals) == 2 or len(vals) == 3:
100                continue
101            else:
102                self.errors = 'Unexpected information in line: '+str(i+1)
103                if all([ord(c) < 128 and ord(c) != 0 for c in str(S)]): # show only if ASCII
104                    self.errors += '  '+str(S)
105                else: 
106                    self.errors += '  (binary)'
107                fp.close()
108                return False
109        fp.close()
110        return True # no errors encountered
111
112    def Reader(self,filename, ParentFrame=None, **unused):
113        'Read a Topas file'
114        x = []
115        y = []
116        w = []
117        gotCcomment = False
118        begin = True
119        fp = open(filename,'r')
120        for i,S in enumerate(fp):
121            self.errors = 'Error reading line: '+str(i+1)
122            # or a block of comments delimited by /* and */
123            # or (GSAS style) each line can begin with '#'
124            if begin:
125                if self.Chi or self.Wave:
126                    if i < 4:
127                        continue
128                    else:
129                        begin = False
130                else:       
131                    if gotCcomment and S.find('*/') > -1:
132                        self.comments.append(S[:-1])
133                        begin = False
134                        continue
135                    if S.strip().startswith('/*'):
136                        self.comments.append(S[:-1])
137                        gotCcomment = True
138                        continue   
139                    if S[0] in ["'",'#']:
140                        self.comments.append(S[:-1])
141                        continue       #ignore comments, if any
142                    else:
143                        begin = False
144            # valid line to read
145            #vals = S.split()
146            vals = S.replace(',',' ').replace(';',' ').split()
147            if len(vals) < 2:
148                print ('Line '+str(i+1)+' cannot be read:\n\t'+S)
149                continue
150            try:
151                if self.Wave:
152                    try:
153                        val = min(0.995,self.Wave/(4.*np.pi/float(vals[0])))  #set max at 168deg
154                        x.append(2.0*asind(val))
155                    except:
156                        msg = 'Error converting '+str(vals[0]
157                        ) + 'with wavelength ' + str(self.Wave) 
158                        break
159                else:
160                    x.append(float(vals[0]))
161                f = float(vals[1])
162                if f <= 0.0:
163                    y.append(0.0)
164                    w.append(0.0)
165                elif len(vals) == 3:
166                    y.append(float(vals[1]))
167                    w.append(1.0/float(vals[2])**2)
168                else:
169                    y.append(float(vals[1]))
170                    w.append(1.0/float(vals[1]))
171            except ValueError:
172                msg = 'Error parsing number in line '+str(i+1)
173                if GSASIIpath.GetConfigValue('debug'):
174                    print (msg)
175                    print (S.strip())
176                break
177            except:
178                msg = 'Error in line '+str(i+1)
179                if GSASIIpath.GetConfigValue('debug'):
180                    print (msg)
181                    print (S.strip())
182                break
183        N = len(x)
184        self.powderdata = [
185            np.array(x), # x-axis values
186            np.array(y), # powder pattern intensities
187            np.array(w), # 1/sig(intensity)^2 values (weights)
188            np.zeros(N), # calc. intensities (zero)
189            np.zeros(N), # calc. background (zero)
190            np.zeros(N), # obs-calc profiles
191            ]
192        self.powderentry[0] = filename
193        #self.powderentry[1] = pos # bank offset (N/A here)
194        #self.powderentry[2] = 1 # xye file only has one bank
195        self.idstring = ospath.basename(filename)
196        # scan comments for temperature
197        Temperature = 300
198        for S in self.comments:
199            if 'temp' in S.lower().split('=')[0]:
200                try:
201                    Temperature = float(S.split('=')[1])
202                except:
203                    pass
204        self.Sample['Temperature'] = Temperature
205        fp.close()
206        return True
Note: See TracBrowser for help on using the repository browser.