1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 __id__ = "$Id: fitrt.py 6626 2011-06-07 08:32:48Z yshang $"
16
17 import tempfile, shutil, copy, os
18 from diffpy.srrietveld.exceptions import SrrRunTimeError
19 from diffpy.refinementdata.refinement import Refinement
20 from diffpy.pyfullprof.exception import RietException as FPError
21 from diffpy.pygsas.exception import RietException as GSASError
22 from diffpy.srrietveld.gui import srrguiglobals as GLOBALS
23 from diffpy.srrietveld.utility import printWarning
24 from diffpy.srrietveld.convert.datafile import DataFile
25 import diffpy.srrietveld.utility as UTILS
26
28 """FitRT provides the runtime control of refinements. It uses two basic ways
29 to run a refinement, either step by step or finish everything by one call.
30
31 Data member:
32
33 fit -- a diffpy.refinementdata.Refinement object that stores a fit
34 strategy -- a refine strategy to be applied
35 index -- the index to a single fit (if multiple fits are saved
36 together as an array)
37 enginefit -- the engine fit object
38 step -- record the refinement step
39 tempDir -- the working folder
40 workdingDir -- the current working directory
41 """
42 - def __init__(self, job, fit,index=None):
43 """ Initialization.
44
45 job -- the job this fitrt belonged to
46 fit -- a diffpy.refinementdata.Refinement object that stores a fit
47 index -- the index to a single fit (if multiple fits are saved
48 together as an array)
49 """
50 self.fit = fit
51 self.job = job
52
53 self.index = index
54
55 self.enginefit = None
56 self.step = 0
57
58 self.tempDir = None
59
60 self.workingDir = os.getcwd()
61
62
63 self.isStrategyEnabled = GLOBALS.isStrategyEnabled
64
65 return
66
68 '''Set the strategy based on the global settings'''
69 if isStrategyEnabled:
70 self.strategy = copy.deepcopy(self.fit.getPyObj("Strategy"))
71 else:
72 self.strategy = self.fit.getOneStepStrategy()
73
74 return
75
76 - def run(self, isStrategyEnabled = False, continuous=True):
77 """Run the refinement according to its strategy.
78
79 isStrategyEnabled -- if the strategy is enabled
80
81 continuous -- run the whole refinement continuously or not
82
83 return: True if the refinement finished. False if not.
84 """
85
86
87 self.isStrategyEnabled = isStrategyEnabled
88
89
90 if self.prepare():
91
92 try:
93 os.chdir(self.tempDir)
94
95 self.enginefit.fixAll()
96 self.enginefit.refine(cycle=5, srtype="l",
97 mode="refine", signature=["dry", '.'])
98
99 except (FPError, GSASError), e:
100 self.fit.setStatus(Refinement.ERROR, self.index)
101 self.enginefit = None
102 self.tempDir = None
103 os.chdir(self.workingDir)
104 self.clean()
105 UTILS.printWarning(e.message)
106
107 return True
108
109 GLOBALS.project.updateFit(self)
110 if not continuous:
111 return False
112
113 else:
114 self.fit.setStatus(Refinement.ERROR, self.index)
115 self.enginefit = None
116 self.tempDir = None
117 os.chdir(self.workingDir)
118 self.clean()
119
120 return True
121
122
123 self.__setStrategy(isStrategyEnabled)
124
125 while self.step < len(self.strategy):
126
127 try:
128
129 self.refineSingleStep()
130 except (FPError, GSASError), e:
131 self.fit.setStatus(Refinement.ERROR, self.index)
132 self.enginefit = None
133 self.tempDir = None
134 os.chdir(self.workingDir)
135 self.clean()
136 return True
137
138 GLOBALS.project.updateFit(self)
139 self.step += 1
140
141 if not continuous:
142 break
143
144
145 if self.step < len(self.strategy):
146
147 os.chdir(self.workingDir)
148 return False
149
150 self.fit.setStatus(self.fit.FINISHED, self.index)
151
152 os.chdir(self.workingDir)
153 self.clean()
154
155 return True
156
157
158
160 """Prepare the refinement, consisting of three steps:
161 1. Check if the engine fit object is available
162 2. Create temporary folder for running
163 3. Generate the data file
164
165 return: True if it runs sucessfully, otherwise False.
166 """
167
168 if self.tempDir:
169 return False
170
171
172 if self.enginefit is None:
173 self.enginefit = self.fit.owner.exportEngineFit(self.fit, self.index)
174
175
176 self.tempDir = tempfile.mkdtemp()
177
178
179 patterns = self.fit.getObject('Pattern')
180
181
182 engineName = self.fit.getEngineType()
183
184
185
186 for bankid, pattern in enumerate(patterns):
187
188 ds = pattern.get('Instrumentfile')
189 if ds is not None:
190 instFilePath = self.fit.findFileFromDataset(ds, self.index)
191 else: instFilePath = None
192
193 for param in ['Datafile', 'MFIL']:
194
195 ds = pattern.get(param)
196
197 if ds is None:
198 if param == "Datafile":
199 __msg = 'The data file path is not specified. '
200 UTILS.printWarning(__msg)
201 return False
202 else:
203 continue
204
205 filepath = self.fit.findFileFromDataset(ds, self.index)
206
207 if filepath:
208
209
210 filepath = os.path.abspath(
211 os.path.join(GLOBALS.project.basepath,
212 filepath)
213 )
214 else:
215 if param == 'Datafile':
216 __msg = 'The data file is not found. '
217 UTILS.printWarning(__msg)
218 return False
219 else:
220 continue
221
222 dataFile = DataFile(filepath = filepath, engine = engineName)
223
224 filepath = dataFile.prepDataFile(self.tempDir,
225 instFilePath)
226
227
228
229 engPattern = self.enginefit.Pattern.get(bankid)
230 if hasattr(engPattern, param):
231 engPattern.set( param, os.path.basename(filepath) )
232 else:
233 if param == "Datafile":
234 __msg = 'The data file path is not set in the engine file. '
235 UTILS.printWarning(__msg)
236 return False
237
238 return True
239
241 '''Clean up after each refinement'''
242 from diffpy.srrietveld.gui.srrguiglobals import isDebug
243 if not isDebug:
244 if self.tempDir:
245 from shutil import rmtree
246 from os import path
247 if path.exists(self.tempDir):
248 rmtree(self.tempDir)
249
250 return
251
252 - def prepareFile(self, fid, engineName, bankid = None, instFilePath = None):
253 """Write or move data/instrument files in running/tmp directory
254
255 enginename -- the type of engine, can be either gsas or fullprof
256 fid -- the file id
257 bankid -- the bankid, used to convert the file format
258 instFilePath -- The instrument file path
259
260 return the file name
261 """
262 from hashlib import sha1
263
264 bankid = 1
265
266 from diffpy.srrietveld.addon.datafile import DataFileConverter as DFC
267
268 fileList = GLOBALS.project.getObject('SourceFileList')
269
270 fileObj = fileList.findFileByID(fid)
271
272
273
274 fileObj.dump(self.tempDir)
275
276 oldPath = os.path.join(self.tempDir, fileObj.fileName)
277
278
279 root, ext = os.path.splitext(fileObj.fileName)
280 if engineName == 'gsas':
281
282 if ext.lower() in [".chi", ".dat", ".txt"]:
283
284 fileName = root + '.gsa'
285 newPath = os.path.join(self.tempDir, fileName)
286
287
288
289 if os.path.isfile(newPath) and \
290 fileObj.fid == sha1(open(newPath, 'rb').read()).hexdigest():
291 __message = "A different file with same name exist. " + \
292 "will be replaced with the new one"
293 print __message
294
295 dfc = DFC(oldPath)
296
297 dfc.toGSASFile(oldPath, newPath, bankid)
298
299
300 if engineName == 'fullprof':
301 fileName = root + '.dat'
302 newPath = os.path.join(self.tempDir, fileName)
303
304 if ext.lower() in [".chi", ".gsa", ".gda", "fxye"]:
305 if instFilePath is not None:
306 instFid = sha1(open(instFilePath, 'rb').read()).hexdigest()
307
308 if ext.lower() != '.chi' and fid != instFid:
309 __warningMsg = 'To convert GSAS data file, installation of ' + \
310 'GSAS is needed and an instrument file is required. '
311
312 printWarning(__warningMsg)
313
314
315
316 dfc = DFC(oldPath, instFilePath)
317 import glob
318 desfile = os.path.join(os.getcwd(), "*.EXP")
319 for fn in glob.glob(desfile):
320 expfilename = fn
321 if expfilename:
322 dfc.toFPFile(oldPath, newPath, bankid, expfilename)
323 elif ext.lower() == '.chi':
324 dfc.toFPFile(oldPath, newPath, bankid)
325 else:
326 __warningMsg = "To convert GSAS data file, GSAS is needed " + \
327 "to be installed and an instrument file is required." + \
328 "The gsas data file can not be converted. The refinment may " + \
329 "not run. "
330 printWarning(__warningMsg)
331
332 if ext.lower() not in [".chi", ".gsa", ".gda", "fxye", '.dat', '.raw']:
333 __warningMsg = 'Data file extension is not recognized. The ' + \
334 'refinement may not run correctly. '
335 printWarning(__warningMsg)
336
337 return fileName
338
339
341 """Refine a single step in the strategy list.
342 """
343 import re
344
345
346 strategystep = copy.deepcopy(self.strategy[self.step])
347 method, paramlist = strategystep.items()[0]
348
349 headparam = paramlist[0][0]
350 refmsg = "\nRefinable Parameter = %-10s Over-all Step = %-5s Refine-Type = %-10s\n"% \
351 (headparam, self.step, method)
352 refmsg += "%-10sNew Variables: \n"% ("")
353 for param in paramlist:
354
355 fullpath = param[0]
356 formula = param[2]
357 self.setConstraint(fullpath, formula)
358 refmsg += "%-20s%-20s: %-20s\n"% ("", fullpath, formula)
359 print refmsg
360
361
362 sig = str(self.step) + "_" + headparam.split(".")[-1]
363 '''Windows directory name can not include following chars:
364 < (less than)> (greater than) : (colon) " (double quote)
365 / (forward slash) \ (backslash) | (vertical bar or pipe)
366 ? (question mark) * (asterisk)'''
367 sig = sig.replace(':','.')
368 fitsummary = self.enginefit.refine(40, srtype = method.lower()[0],
369 mode = "refine", signature=[sig, '.'])
370
371
372 chi2 = fitsummary.getResidueValue(-1, residname="Chi2")
373 rwp = fitsummary.getResidueValue(-1, residname="Rwp")
374 re = fitsummary.getResidueValue(-1, residname="Re")
375
376 print "%-10s: Chi2 = %-15s Rp = %-15s Rexp = %-15s"% (method, chi2, rwp, re)
377 print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
378
379 return
380
381
383 """ Turn on the refinement flag for parameters
384 """
385 fitname = key.split(".")[0]
386 key = key.replace(fitname+".", "")
387 try:
388
389 newvalue = int(formula)
390 except:
391
392 try:
393 newvalue = float(formula)
394 except:
395 self.enginefit.setConstraintByPath(key, formula)
396 return
397 self.enginefit.setByPath(key, newvalue)
398 return
399
400