/
SaveVulcanGSS.py
340 lines (261 loc) · 10.4 KB
/
SaveVulcanGSS.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
#pylint: disable=no-init,invalid-name
import mantid.simpleapi as api
from mantid.api import *
from mantid.kernel import *
class SaveVulcanGSS(PythonAlgorithm):
""" Save GSS file for VULCAN
"""
def category(self):
"""
"""
return "Diffraction\\DataHandling"
def name(self):
"""
"""
return "SaveVulcanGSS"
def summary(self):
""" Return summary
"""
return "Load file generated by Fullprof."
def PyInit(self):
""" Declare properties
"""
self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input),\
"Focussed diffraction workspace to be exported to GSAS file. ")
self.declareProperty(FileProperty("BinFilename","", FileAction.Load, ['.dat']),\
"Name of a data file containing the bin boundaries in Log(TOF). ")
self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output),\
"Name of rebinned matrix workspace. ")
self.declareProperty(FileProperty("GSSFilename","", FileAction.Save, ['.gda']),\
"Name of the output GSAS file. ")
self.declareProperty("IPTS", 0, "IPTS number")
self.declareProperty("GSSParmFileName", "", "GSAS parameter file name for this GSAS data file.")
return
def PyExec(self):
""" Main Execution Body
"""
# Properties
inputwsname = self.getPropertyValue("InputWorkspace")
logtoffilename = self.getPropertyValue("BinFilename")
outgssfilename = self.getPropertyValue("GSSFilename")
outputwsname = self.getPropertyValue("OutputWorkspace")
# Check properties
inputws = AnalysisDataService.retrieve(inputwsname)
if inputws is None:
raise NotImplementedError("Inputworkspace does not exist.")
if inputws.getAxis(0).getUnit().unitID() != "TOF":
raise NotImplementedError("InputWorkspace must be in unit as TOF.")
if inputws.isHistogramData() is False:
raise NotImplementedError("InputWorkspace must be histogram, but not point data.")
# Load reference bin file
vec_refT = self._loadRefLogBinFile(logtoffilename)
# Rebin
gsaws = self._rebinVdrive(inputws, vec_refT, outputwsname)
# Generate GSAS file
outputws = self._saveGSAS(gsaws, outgssfilename)
# Convert header and bank information
ipts = self.getPropertyValue("IPTS")
parmfname = self.getPropertyValue("GSSParmFileName")
newheader = self._genVulcanGSSHeader(outputws, outgssfilename, ipts, parmfname)
self._rewriteGSSFile(outgssfilename, newheader)
# Set property
self.setProperty("OutputWorkspace", outputws)
return
def _loadRefLogBinFile(self, logbinfilename):
""" Create a vector of bin in TOF value
Arguments:
- logbinfilename : name of file containing log_10(TOF) bins
"""
import math
bfile = open(logbinfilename, "r")
lines = bfile.readlines()
bfile.close()
vecX = []
for line in lines:
line = line.strip()
if len(line) == 0:
continue
if line[0] == "#":
continue
terms = line.split()
for it in xrange(len(terms)):
x = float(terms[it])
vecX.append(x)
# ENDFOR
# ENDFOR
vecPow10X = []
for i in xrange(len(vecX)):
p10x = math.pow(10, vecX[i])
vecPow10X.append(p10x)
return vecPow10X
def _rebinVdrive(self, inputws, vec_refT, outputwsname):
""" Rebin to match VULCAN's VDRIVE-generated GSAS file
Arguments:
- inputws : focussed workspace
- vec_refT: list of TOF bins
"""
# Create a complicated bin parameter
params = []
for ibin in xrange(len(vec_refT)-1):
x0 = vec_refT[ibin]
xf = vec_refT[ibin+1]
dx = xf-x0
params.append(x0)
params.append(dx)
# last bin
x0 = vec_refT[-1]
xf = 2*dx + x0
params.extend([x0, 2*dx, xf])
# Rebin
tempws = api.Rebin(InputWorkspace=inputws, Params=params, PreserveEvents=False)
# Map to a new workspace with 'vdrive-bin', which is the integer value of log bins
numhist = tempws.getNumberHistograms()
newvecx = []
newvecy = []
newvece = []
for iws in xrange(numhist):
vecx = tempws.readX(iws)
vecy = tempws.readY(iws)
vece = tempws.readE(iws)
for i in xrange( len(vecx)-1 ):
newvecx.append(int(vecx[i]*10)/10.)
newvecy.append(vecy[i])
newvece.append(vece[i])
# ENDFOR (i)
# ENDFOR (iws)
api.DeleteWorkspace(Workspace=tempws)
gsaws = api.CreateWorkspace(DataX=newvecx, DataY=newvecy, DataE=newvece, NSpec=numhist,\
UnitX="TOF", ParentWorkspace=inputws, OutputWorkspace=outputwsname)
return gsaws
def _saveGSAS(self, gsaws, gdafilename):
""" Save file
"""
# Convert from PointData to Histogram
gsaws = api.ConvertToHistogram(InputWorkspace=gsaws, OutputWorkspace=str(gsaws))
# Save
api.SaveGSS(InputWorkspace=gsaws, Filename=gdafilename, SplitFiles=False, Append=False,\
Format="SLOG", MultiplyByBinWidth=False, ExtendedHeader=False, UseSpectrumNumberAsBankID=True)
return gsaws
def _rewriteGSSFile(self, gssfilename, newheader):
""" Re-write GSAS file including header and header for each bank
"""
# Get all lines
gfile = open(gssfilename, "r")
lines = gfile.readlines()
gfile.close()
# New file
filebuffer = ""
filebuffer += newheader
inbank = False
banklines = []
for line in lines:
cline = line.strip()
if len(cline) == 0:
continue
if line.startswith("BANK"):
# Indicate a new bank
if len(banklines) == 0:
# bank line for first bank
inbank = True
banklines.append(line.strip("\n"))
else:
# bank line for non-first bank.
tmpbuffer = self._rewriteOneBankData(banklines)
filebuffer += tmpbuffer
banklines = [line]
# ENDIFELSE
elif inbank is True and cline.startswith("#") is False:
# Write data line
banklines.append(line.strip("\n"))
# ENDFOR
if len(banklines) > 0:
tmpbuffer = self._rewriteOneBankData(banklines)
filebuffer += tmpbuffer
else:
raise NotImplementedError("Impossible to have this")
# Overwrite the original file
ofile = open(gssfilename, "w")
ofile.write(filebuffer)
ofile.close()
return
def _genVulcanGSSHeader(self, ws, gssfilename, ipts, parmfname):
"""
"""
from datetime import datetime
import os.path
# Get necessary information
title = ws.getTitle()
run = ws.getRun()
# Get information on start/stop
processtime = True
if run.hasProperty("run_start") and run.hasProperty("duration"):
runstart = run.getProperty("run_start").value
duration = float(run.getProperty("duration").value)
else:
processtime = False
if processtime is True:
# property run_start and duration exist
runstart_sec = runstart.split(".")[0]
runstart_ns = runstart.split(".")[1]
utctime = datetime.strptime(runstart_sec, '%Y-%m-%dT%H:%M:%S')
time0=datetime.strptime("1990-01-01T0:0:0",'%Y-%m-%dT%H:%M:%S')
delta = utctime-time0
try:
total_nanosecond_start = int(delta.total_seconds()*int(1.0E9)) + int(runstart_ns)
except AttributeError:
total_seconds = delta.days*24*3600 + delta.seconds
total_nanosecond_start = total_seconds * int(1.0E9) + int(runstart_ns)
total_nanosecond_stop = total_nanosecond_start + int(duration*1.0E9)
else:
# not both property is found
total_nanosecond_start = 0
total_nanosecond_stop = 0
self.log().debug("Start = %d, Stop = %d" % (total_nanosecond_start, total_nanosecond_stop))
# Construct new header
newheader = ""
if len(title) > 80:
title = title[0:80]
newheader += "%-80s\n" % (title)
newheader += "%-80s\n" % ( "Instrument parameter file: %s" %(parmfname) )
newheader += "%-80s\n" % ( "#IPTS: %s" % (str(ipts)) )
newheader += "%-80s\n" % ( "#binned by: Mantid" )
newheader += "%-80s\n" % ( "#GSAS file name: %s" % (os.path.basename(gssfilename)) )
newheader += "%-80s\n" % ( "#GSAS IPARM file: %s" % (parmfname) )
newheader += "%-80s\n" % ( "#Pulsestart: %d" % (total_nanosecond_start) )
newheader += "%-80s\n" % ( "#Pulsestop: %d" % (total_nanosecond_stop) )
return newheader
def _rewriteOneBankData(self, banklines):
""" first line is for bank information
"""
wbuf = ""
# Rewrite bank lines
bankline = banklines[0].strip()
terms = bankline.split()
tofmin = float(banklines[1].split()[0])
tofmax = float(banklines[-1].split()[0])
terms[5] = "%.1f" % (tofmin)
terms[6] = "%.1f" % (tofmax)
newbankline = ""
# title
for t in terms:
newbankline += "%s " % (t)
wbuf = "%-80s\n" % (newbankline)
# data
for i in xrange(1, len(banklines)):
cline = banklines[i]
terms = cline.split()
try:
tof = float(terms[0])
y = float(terms[1])
e = float(terms[2])
x_s = "%.1f" % (tof)
y_s = "%.1f" % (y)
e_s = "%.2f" % (e)
temp = "%12s%12s%12s" % (x_s, y_s, e_s)
except TypeError:
temp = "%-80s\n" % (cline.rstrip())
wbuf += "%-80s\n" % (temp)
# ENDFOR
return wbuf
# Register algorithm with Mantid
AlgorithmFactory.subscribe(SaveVulcanGSS)