Package diffpy :: Package srrietveld :: Module fitrt
[frames] | no frames]

Source Code for Module diffpy.srrietveld.fitrt

  1  ############################################################################## 
  2  # 
  3  # diffpy.srrietveld by DANSE Diffraction group 
  4  #                   Simon J. L. Billinge 
  5  #                   (c) 2009 Trustees of the Columbia University 
  6  #                   in the City of New York.  All rights reserved. 
  7  # 
  8  # File coded by:    Wenduo Zhou, Peng Tian, Jiwu Liu 
  9  # 
 10  # See AUTHORS.txt for a list of people who contributed. 
 11  # See LICENSE.txt for license information. 
 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   
27 -class FitRT(object):
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 # temp working directory 58 self.tempDir = None 59 # main working directory 60 self.workingDir = os.getcwd() 61 # the strategy may be enabled temporarily even when the global variable 62 # is false 63 self.isStrategyEnabled = GLOBALS.isStrategyEnabled 64 65 return
66
67 - def __setStrategy(self, isStrategyEnabled):
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 # Prepare 90 if self.prepare(): 91 # FIXME: if fit is built from a exp/pcr file, dry run should be skipped 92 try: 93 os.chdir(self.tempDir) 94 # fix all parameters 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 # in this case, do not go on. 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 # in this case, do not go on. 120 return True 121 122 # Run the strategy 123 self.__setStrategy(isStrategyEnabled) 124 125 while self.step < len(self.strategy): 126 127 try: 128 # when refine diverges, 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 # Not finish yet 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
159 - def prepare(self):
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 #NOTE: if tempDir is created, the preparation should have been done already. 168 if self.tempDir: 169 return False 170 171 # A. check if my engine fit is available 172 if self.enginefit is None: 173 self.enginefit = self.fit.owner.exportEngineFit(self.fit, self.index) 174 175 # B. Backup Directory 176 self.tempDir = tempfile.mkdtemp() 177 178 # C. Generate the datafile 179 patterns = self.fit.getObject('Pattern') 180 181 #check the engine type 182 engineName = self.fit.getEngineType() 183 184 # loop through all tbe patterns and dump the files into the temp folder 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 # convert to gsas file 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 # get the file abs path from the rel path stored, and the base 209 # path of the fit object 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 # the data file name may be updated, change the file name 228 # in engine fit 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
240 - def clean(self):
241 '''Clean up after each refinement''' 242 from diffpy.srrietveld.gui.srrguiglobals import isDebug 243 if not isDebug: # only remove the tmp directories when not debugging 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 #FIXME:The datafile converter does not take bank id other htan 1 so far 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 # dump the file content to the tempDir with the file name saved 273 # in fileObj.fileName 274 fileObj.dump(self.tempDir) 275 276 oldPath = os.path.join(self.tempDir, fileObj.fileName) 277 278 # convert the fullprof type file to gsas 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 #check if the file already exist 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 # FIXME: only export the first bank? 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 # FIXM: convert gsas data file name to fullprof data file name 314 # search the local directory for EXP files, may implement a 315 # better algrethm 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
340 - def refineSingleStep(self):
341 """Refine a single step in the strategy list. 342 """ 343 import re 344 345 # Set addlist + currenttuple 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 # Set constraint 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 # Refine and Save 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 # Screen Output 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
382 - def setConstraint(self, key, formula):
383 """ Turn on the refinement flag for parameters 384 """ 385 fitname = key.split(".")[0] 386 key = key.replace(fitname+".", "") 387 try: 388 # Set the int value 389 newvalue = int(formula) 390 except: 391 # Set the float value 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 # End Of File 400