| 1 | ################################################################################ |
|---|
| 2 | # |
|---|
| 3 | # Auto reduction script for VULCAN |
|---|
| 4 | # Input |
|---|
| 5 | # - Event file name with path |
|---|
| 6 | # - Output directory |
|---|
| 7 | # |
|---|
| 8 | # Test example: |
|---|
| 9 | # 1. reduce_VULCAN.py /SNS/VULCAN/IPTS-11090/0/41703/NeXus/VULCAN_41703_event.nxs |
|---|
| 10 | # /SNS/users/wzz/Projects/VULCAN/AutoReduction/autoreduce/Temp |
|---|
| 11 | # |
|---|
| 12 | # 2. reduce_VULCAN.py /SNS/VULCAN/IPTS-11090/0/41739/NeXus/VULCAN_41739_event.nxs |
|---|
| 13 | # /SNS/users/wzz/Projects/VULCAN/AutoReduction/autoreduce/Temp |
|---|
| 14 | # |
|---|
| 15 | ################################################################################ |
|---|
| 16 | |
|---|
| 17 | import os |
|---|
| 18 | import sys |
|---|
| 19 | import shutil |
|---|
| 20 | import xml.etree.ElementTree as ET |
|---|
| 21 | |
|---|
| 22 | sys.path.append("/opt/mantidnightly/bin") |
|---|
| 23 | |
|---|
| 24 | mantidpathlocal = "/home/wzz/Projects/MantidProjects/Mantid2/Code/debug/bin" |
|---|
| 25 | if os.path.exists(mantidpathlocal) is True: |
|---|
| 26 | USELOCAL = True |
|---|
| 27 | sys.path.append(mantidpathlocal) |
|---|
| 28 | |
|---|
| 29 | from mantid.simpleapi import * |
|---|
| 30 | import mantid |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | def changeOutputDir(outputdir): |
|---|
| 34 | """ Change the output direction from ..../autoreduce/ to ..../logs/ |
|---|
| 35 | If the new directory does not exist, make it |
|---|
| 36 | """ |
|---|
| 37 | # Change path from ..../autoreduce/ ... to .../logs/ |
|---|
| 38 | if outputdir.endswith("/"): |
|---|
| 39 | outputdir = os.path.split(outputdir)[0] |
|---|
| 40 | lastdir = os.path.split(outputdir)[-1] |
|---|
| 41 | # print "Furance: last dir of output dir = %s. " % (lastdir) |
|---|
| 42 | |
|---|
| 43 | if lastdir == "autoreduce": |
|---|
| 44 | modoutputdir = os.path.join(os.path.split(outputdir)[0], "logs") |
|---|
| 45 | print "Log file will be written to directory %s. " % (modoutputdir) |
|---|
| 46 | else: |
|---|
| 47 | modoutputdir = outputdir |
|---|
| 48 | print "Log file will be written to directory %s as auto reduction service specified. " % (modoutputdir) |
|---|
| 49 | |
|---|
| 50 | # Create path |
|---|
| 51 | if os.path.exists(modoutputdir) is False: |
|---|
| 52 | # create |
|---|
| 53 | os.mkdir(modoutputdir) |
|---|
| 54 | |
|---|
| 55 | return modoutputdir |
|---|
| 56 | |
|---|
| 57 | |
|---|
| 58 | def exportFurnaceLog(logwsname, outputDir, runNumber): |
|---|
| 59 | """ Export the furnace log |
|---|
| 60 | """ |
|---|
| 61 | logfilename = os.path.join(outputDir, "furnace%d.txt" % (runNumber)) |
|---|
| 62 | |
|---|
| 63 | ExportSampleLogsToCSVFile(InputWorkspace = logwsname, |
|---|
| 64 | OutputFilename = logfilename, |
|---|
| 65 | SampleLogNames = ["furnace.temp1", "furnace.temp2", "furnace.power"]) |
|---|
| 66 | |
|---|
| 67 | return |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | def exportMTSLog(logwsname, outputDir, ipts, runnumber): |
|---|
| 71 | """ Export MTS log |
|---|
| 72 | List of MTS Log: |
|---|
| 73 | X Y Z O HROT |
|---|
| 74 | MTSDisplacement MTSForce MTSStrain MTSStress MTSAngle |
|---|
| 75 | MTSTorque MTSLaser MTSlaserstrain MTSDisplaceoffset MTSAngleceoffset |
|---|
| 76 | MTST1 MTST2 MTST3 MTST4 FurnaceT |
|---|
| 77 | FurnaceOT FurnacePower VacT VacOT |
|---|
| 78 | """ |
|---|
| 79 | # Organzied by dictionary |
|---|
| 80 | vulcanheaderlist = [] |
|---|
| 81 | vulcanheaderlist.append( ("TimeStamp" , "") ) |
|---|
| 82 | vulcanheaderlist.append( ("Time [sec]" , "") ) |
|---|
| 83 | vulcanheaderlist.append( ("MPTIndex" , "loadframe.MPTIndex") ) |
|---|
| 84 | vulcanheaderlist.append( ("X" , "X") ) |
|---|
| 85 | vulcanheaderlist.append( ("Y" , "Y") ) |
|---|
| 86 | vulcanheaderlist.append( ("Z" , "Z") ) |
|---|
| 87 | vulcanheaderlist.append( ("O" , "OMEGA") ) |
|---|
| 88 | vulcanheaderlist.append( ("HROT" , "HROT") ) |
|---|
| 89 | vulcanheaderlist.append( ("MTSDisplacement" , "loadframe.displacement") ) |
|---|
| 90 | vulcanheaderlist.append( ("MTSForce" , "loadframe.force") ) |
|---|
| 91 | vulcanheaderlist.append( ("MTSStrain" , "loadframe.strain") ) |
|---|
| 92 | vulcanheaderlist.append( ("MTSStress" , "loadframe.stress") ) |
|---|
| 93 | vulcanheaderlist.append( ("MTSAngle" , "loadframe.rot_angle") ) |
|---|
| 94 | vulcanheaderlist.append( ("MTSTorque" , "loadframe.torque") ) |
|---|
| 95 | vulcanheaderlist.append( ("MTSLaser" , "loadframe.laser") ) |
|---|
| 96 | vulcanheaderlist.append( ("MTSlaserstrain" , "loadframe.laserstrain") ) |
|---|
| 97 | vulcanheaderlist.append( ("MTSDisplaceoffset" , "loadframe.x_offset") ) |
|---|
| 98 | vulcanheaderlist.append( ("MTSAngleceoffset" , "loadframe.rot_offset") ) |
|---|
| 99 | vulcanheaderlist.append( ("MTS1" , "loadframe.furnace1") ) |
|---|
| 100 | vulcanheaderlist.append( ("MTS2" , "loadframe.furnace2") ) |
|---|
| 101 | vulcanheaderlist.append( ("MTS3" , "loadframe.extTC3") ) |
|---|
| 102 | vulcanheaderlist.append( ("MTS4" , "loadframe.extTC4") ) |
|---|
| 103 | vulcanheaderlist.append( ("FurnaceT" , "furnace.temp1") ) |
|---|
| 104 | vulcanheaderlist.append( ("FurnaceOT" , "furnace.temp2") ) |
|---|
| 105 | vulcanheaderlist.append( ("FurnacePower" , "furnace.power") ) |
|---|
| 106 | vulcanheaderlist.append( ("VacT" , "partlow1.temp") ) |
|---|
| 107 | vulcanheaderlist.append( ("VacOT" , "partlow2.temp") ) |
|---|
| 108 | |
|---|
| 109 | # Format to lists for input |
|---|
| 110 | samplelognames = [] |
|---|
| 111 | header = [] |
|---|
| 112 | for i in xrange(len(vulcanheaderlist)): |
|---|
| 113 | title = vulcanheaderlist[i][0] |
|---|
| 114 | logname = vulcanheaderlist[i][1] |
|---|
| 115 | |
|---|
| 116 | header.append(title) |
|---|
| 117 | if len(logname) > 0: |
|---|
| 118 | samplelognames.append(logname) |
|---|
| 119 | |
|---|
| 120 | headstr = "" |
|---|
| 121 | for title in header: |
|---|
| 122 | headstr += "%s\t" % (title) |
|---|
| 123 | |
|---|
| 124 | """ |
|---|
| 125 | print header |
|---|
| 126 | print samplelognames |
|---|
| 127 | print headstr |
|---|
| 128 | """ |
|---|
| 129 | |
|---|
| 130 | outputfilename = "IPTS-%d-MTSLoadFrame-%d.txt" % (ipts, runnumber) |
|---|
| 131 | outputfilename = os.path.join(outputDir, outputfilename) |
|---|
| 132 | # print "Loadframe output filename: %s" % (outputfilename) |
|---|
| 133 | |
|---|
| 134 | ExportSampleLogsToCSVFile( |
|---|
| 135 | InputWorkspace = logwsname, |
|---|
| 136 | OutputFilename = outputfilename, |
|---|
| 137 | SampleLogNames = samplelognames, |
|---|
| 138 | WriteHeaderFile = True, |
|---|
| 139 | Header = headstr) |
|---|
| 140 | |
|---|
| 141 | |
|---|
| 142 | return |
|---|
| 143 | |
|---|
| 144 | RecordBase = [ |
|---|
| 145 | ("RUN", "run_number", None), |
|---|
| 146 | ("IPTS", "IPTS", None), |
|---|
| 147 | ("Title", "run_title", None), |
|---|
| 148 | ("Notes", "Notes", None), |
|---|
| 149 | ("Sample", "Sample", None), |
|---|
| 150 | ("StartTime", "run_start", "localtime"), |
|---|
| 151 | ("Duration", "duration", None), |
|---|
| 152 | ("ProtonCharge", "protoncharge", "sum"), |
|---|
| 153 | ("TotalCounts", "das.counts", "sum"), |
|---|
| 154 | ("Monitor1", "das.monitor2counts", "sum"), |
|---|
| 155 | ("Monitor2", "das.monitor3counts", "sum"), |
|---|
| 156 | ("X", "X", "0"), |
|---|
| 157 | ("Y", "Y", "0"), |
|---|
| 158 | ("Z", "Z", "0"), |
|---|
| 159 | ("O", "Omega", "0"), |
|---|
| 160 | ("HROT", "HROT", "0"), |
|---|
| 161 | ("BandCentre", "lambda", "0"), |
|---|
| 162 | ("BandWidth", "bandwidth", "0"), |
|---|
| 163 | ("Frequency", "skf1.speed", "0"), |
|---|
| 164 | ("Guide", "Guide", "0"), |
|---|
| 165 | ("IX", "IX", "0"), |
|---|
| 166 | ("IY", "IY", "0"), |
|---|
| 167 | ("IZ", "IZ", "0"), |
|---|
| 168 | ("IHA", "IHA", "0"), |
|---|
| 169 | ("IVA", "IVA", "0"), |
|---|
| 170 | ("Collimator", "Vcollimator", None), |
|---|
| 171 | ("MTSDisplacement", "loadframe.displacement", "0"), |
|---|
| 172 | ("MTSForce", "loadframe.force", "0"), |
|---|
| 173 | ("MTSStrain", "loadframe.strain", "0"), |
|---|
| 174 | ("MTSStress", "loadframe.stress", "0"), |
|---|
| 175 | ("MTSAngle", "loadframe.rot_angle", "0"), |
|---|
| 176 | ("MTSTorque", "loadframe.torque", "0"), |
|---|
| 177 | ("MTSLaser", "loadframe.laser", "0"), |
|---|
| 178 | ("MTSlaserstrain", "loadframe.laserstrain", "0"), |
|---|
| 179 | ("MTSDisplaceoffset","loadframe.x_offset", "0"), |
|---|
| 180 | ("MTSAngleceoffset", "loadframe.rot_offset", "0"), |
|---|
| 181 | ("MTST1", "loadframe.furnace1", "0"), |
|---|
| 182 | ("MTST2", "loadframe.furnace2", "0"), |
|---|
| 183 | ("MTST3", "loadframe.extTC3", "0"), |
|---|
| 184 | ("MTST4", "loadframe.extTC4", "0"), |
|---|
| 185 | ("FurnaceT", "furnace.temp1", "0"), |
|---|
| 186 | ("FurnaceOT", "furnace.temp2", "0"), |
|---|
| 187 | ("FurnacePower", "furnace.power", "0"), |
|---|
| 188 | ("VacT", "partlow1.temp", "0"), |
|---|
| 189 | ("VacOT", "partlow2.temp", "0") |
|---|
| 190 | ] |
|---|
| 191 | |
|---|
| 192 | |
|---|
| 193 | class PatchRecord: |
|---|
| 194 | """ A class whose task is to make patch to Record.txt generated from |
|---|
| 195 | Mantid.simpleapi.ExportExperimentLog(), which may not be able to retrieve |
|---|
| 196 | all information from NeXus file. |
|---|
| 197 | |
|---|
| 198 | This class will not be used after all the required information/logs are |
|---|
| 199 | added to NeXus file or exported to Mantid workspace |
|---|
| 200 | """ |
|---|
| 201 | def __init__(self, instrument, ipts, run): |
|---|
| 202 | """ Init |
|---|
| 203 | """ |
|---|
| 204 | # Generate run_info and cv_info files |
|---|
| 205 | self._cvinfofname = "/SNS/%s/IPTS-%d/0/%d/preNeXus/%s_%d_cvinfo.xml" % ( |
|---|
| 206 | instrument, ipts, run, instrument, run) |
|---|
| 207 | |
|---|
| 208 | self._runinfofname = "/SNS/%s/IPTS-%d/0/%d/preNeXus/%s_%d_runinfo.xml" % ( |
|---|
| 209 | instrument, ipts, run, instrument, run) |
|---|
| 210 | |
|---|
| 211 | self._beaminfofname = "/SNS/%s/IPTS-%d/0/%d/preNeXus/%s_beamtimeinfo.xml" % ( |
|---|
| 212 | instrument, ipts, run, instrument) |
|---|
| 213 | |
|---|
| 214 | # Verify whether these 2 files are accessible |
|---|
| 215 | if os.path.exists(self._cvinfofname) is False or os.path.exists(self._runinfofname) is False or os.path.exists(self._beaminfofname) is False: |
|---|
| 216 | raise NotImplementedError("PreNexus log file %s and/or %s cannot be accessed. " % ( |
|---|
| 217 | self._cvinfofname, self._runinfofname)) |
|---|
| 218 | |
|---|
| 219 | return |
|---|
| 220 | |
|---|
| 221 | def patchRecord(self, recordfilename): |
|---|
| 222 | """ Patch record |
|---|
| 223 | """ |
|---|
| 224 | # Get last line |
|---|
| 225 | titleline, lastline = self._getLastLine(recordfilename) |
|---|
| 226 | |
|---|
| 227 | # print "First line: ", titleline |
|---|
| 228 | # print "Last line: ", lastline |
|---|
| 229 | |
|---|
| 230 | # Parse last line and first line |
|---|
| 231 | rtitles = titleline.split("\t") |
|---|
| 232 | titles = [] |
|---|
| 233 | for title in rtitles: |
|---|
| 234 | title = title.strip() |
|---|
| 235 | titles.append(title) |
|---|
| 236 | |
|---|
| 237 | values = lastline.split("\t") |
|---|
| 238 | |
|---|
| 239 | valuedict = {} |
|---|
| 240 | if len(titles) != len(values): |
|---|
| 241 | raise NotImplementedError("Number of tiles are different than number of values.") |
|---|
| 242 | for itit in xrange(len(titles)): |
|---|
| 243 | valuedict[titles[itit]] = values[itit] |
|---|
| 244 | |
|---|
| 245 | # Substitute |
|---|
| 246 | ipts = self._getIPTS() |
|---|
| 247 | cvdict = self._readCvInfoFile() |
|---|
| 248 | rundict = self._readRunInfoFile() |
|---|
| 249 | |
|---|
| 250 | valuedict["IPTS"] = "%s" % (str(ipts)) |
|---|
| 251 | for title in cvdict.keys(): |
|---|
| 252 | valuedict[title] = cvdict[title] |
|---|
| 253 | |
|---|
| 254 | # print valuedict.keys() |
|---|
| 255 | |
|---|
| 256 | for title in rundict.keys(): |
|---|
| 257 | valuedict[title] = rundict[title] |
|---|
| 258 | |
|---|
| 259 | # Form the line again: with 7 spaces in front |
|---|
| 260 | newline = " " |
|---|
| 261 | for i in xrange(len(titles)): |
|---|
| 262 | title = titles[i] |
|---|
| 263 | if i > 0: |
|---|
| 264 | newline += "\t" |
|---|
| 265 | newline += "%s" % (str(valuedict[title])) |
|---|
| 266 | |
|---|
| 267 | # Remove last line and append the patched line |
|---|
| 268 | self._removeLastLine(recordfilename) |
|---|
| 269 | |
|---|
| 270 | with open(recordfilename, "a") as myfile: |
|---|
| 271 | myfile.write("\n"+newline) |
|---|
| 272 | |
|---|
| 273 | return |
|---|
| 274 | |
|---|
| 275 | |
|---|
| 276 | def _getLastLine(self, filename): |
|---|
| 277 | """ Get the last line of a (possibly long) file |
|---|
| 278 | """ |
|---|
| 279 | with open(filename, 'rb') as fh: |
|---|
| 280 | # Determine a rougly size of a line |
|---|
| 281 | firstline = next(fh).decode().strip() |
|---|
| 282 | secondline = next(fh).decode().strip() |
|---|
| 283 | linesize = len(secondline) |
|---|
| 284 | |
|---|
| 285 | # print "Title line: ", firstline |
|---|
| 286 | # print "Second line: ", secondline |
|---|
| 287 | |
|---|
| 288 | try: |
|---|
| 289 | fh.seek(-2*linesize, 2) |
|---|
| 290 | lastline = fh.readlines()[-1].decode().strip() |
|---|
| 291 | fh.close() |
|---|
| 292 | except IOError as err: |
|---|
| 293 | # File is short |
|---|
| 294 | fh.close() |
|---|
| 295 | fh = open(filename, 'rb') |
|---|
| 296 | lines = fh.readlines() |
|---|
| 297 | lastline = lines[-1] |
|---|
| 298 | |
|---|
| 299 | #print lastline |
|---|
| 300 | return (firstline, lastline) |
|---|
| 301 | |
|---|
| 302 | def _removeLastLine(self, filename): |
|---|
| 303 | """ Remove last line |
|---|
| 304 | """ |
|---|
| 305 | import sys |
|---|
| 306 | import os |
|---|
| 307 | |
|---|
| 308 | #ifile = open(sys.argv[1], "r+", encoding = "utf-8") |
|---|
| 309 | ifile = open(filename, "r+") |
|---|
| 310 | |
|---|
| 311 | ifile.seek(0, os.SEEK_END) |
|---|
| 312 | pos = ifile.tell() - 1 |
|---|
| 313 | while pos > 0 and ifile.read(1) != "\n": |
|---|
| 314 | pos -= 1 |
|---|
| 315 | ifile.seek(pos, os.SEEK_SET) |
|---|
| 316 | |
|---|
| 317 | if pos > 0: |
|---|
| 318 | ifile.seek(pos, os.SEEK_SET) |
|---|
| 319 | ifile.truncate() |
|---|
| 320 | |
|---|
| 321 | ifile.close() |
|---|
| 322 | |
|---|
| 323 | return |
|---|
| 324 | |
|---|
| 325 | def _getIPTS(self): |
|---|
| 326 | """ Get IPTS |
|---|
| 327 | """ |
|---|
| 328 | tree = ET.parse(self._beaminfofname) |
|---|
| 329 | |
|---|
| 330 | root = tree.getroot() |
|---|
| 331 | if root.tag != 'Instrument': |
|---|
| 332 | raise NotImplementedError("Not an instrument") |
|---|
| 333 | |
|---|
| 334 | proposal = None |
|---|
| 335 | for child in root: |
|---|
| 336 | if child.tag == "Proposal": |
|---|
| 337 | proposal = child |
|---|
| 338 | break |
|---|
| 339 | if proposal is None: |
|---|
| 340 | raise NotImplementedError("Not have proposal") |
|---|
| 341 | |
|---|
| 342 | id = None |
|---|
| 343 | for child in proposal: |
|---|
| 344 | if child.tag == "ID": |
|---|
| 345 | id = child |
|---|
| 346 | break |
|---|
| 347 | if id is None: |
|---|
| 348 | raise NotImplementedError("No ID") |
|---|
| 349 | |
|---|
| 350 | ipts = id.text |
|---|
| 351 | |
|---|
| 352 | return ipts |
|---|
| 353 | |
|---|
| 354 | def _readCvInfoFile(self): |
|---|
| 355 | """ read CV info |
|---|
| 356 | """ |
|---|
| 357 | cvinfodict = {} |
|---|
| 358 | |
|---|
| 359 | # Parse the XML file to tree |
|---|
| 360 | tree = ET.parse(self._cvinfofname) |
|---|
| 361 | root = tree.getroot() |
|---|
| 362 | |
|---|
| 363 | # Find "DAS_process" |
|---|
| 364 | das_process = None |
|---|
| 365 | for child in root: |
|---|
| 366 | if child.tag == "DAS_process": |
|---|
| 367 | das_process = child |
|---|
| 368 | if das_process is None: |
|---|
| 369 | raise NotImplementedError("DAS_process is not in cv_info.") |
|---|
| 370 | |
|---|
| 371 | # Parse all the entries to a dictionary |
|---|
| 372 | attribdict = {} |
|---|
| 373 | for child in das_process: |
|---|
| 374 | attrib = child.attrib |
|---|
| 375 | name = attrib['name'] |
|---|
| 376 | value = attrib['value'] |
|---|
| 377 | attribdict[name] = value |
|---|
| 378 | |
|---|
| 379 | name = "das.neutrons" |
|---|
| 380 | if attribdict.has_key(name): |
|---|
| 381 | cvinfodict["TotalCounts"] = attribdict[name] |
|---|
| 382 | |
|---|
| 383 | name = "das.protoncharge" |
|---|
| 384 | if attribdict.has_key(name): |
|---|
| 385 | cvinfodict["ProtonCharge"] = attribdict[name] |
|---|
| 386 | |
|---|
| 387 | name = "das.runtime" |
|---|
| 388 | if attribdict.has_key(name): |
|---|
| 389 | cvinfodict["Duration(sec)"] = attribdict[name] |
|---|
| 390 | |
|---|
| 391 | name = "das.monitor2counts" |
|---|
| 392 | if attribdict.has_key(name): |
|---|
| 393 | cvinfodict["Monitor1"] = attribdict[name] |
|---|
| 394 | |
|---|
| 395 | name = "das.monitor3counts" |
|---|
| 396 | if attribdict.has_key(name): |
|---|
| 397 | cvinfodict["Monitor2"] = attribdict[name] |
|---|
| 398 | |
|---|
| 399 | return cvinfodict |
|---|
| 400 | |
|---|
| 401 | def _readRunInfoFile(self): |
|---|
| 402 | """ Read Run info file |
|---|
| 403 | """ |
|---|
| 404 | runinfodict = {} |
|---|
| 405 | |
|---|
| 406 | tree = ET.parse(self._runinfofname) |
|---|
| 407 | root = tree.getroot() |
|---|
| 408 | |
|---|
| 409 | # Get SampleInfo and GenerateInfo node |
|---|
| 410 | sampleinfo = None |
|---|
| 411 | generalinfo = None |
|---|
| 412 | for child in root: |
|---|
| 413 | if child.tag == "SampleInfo": |
|---|
| 414 | sampleinfo = child |
|---|
| 415 | elif child.tag == "GeneralInfo": |
|---|
| 416 | generalinfo = child |
|---|
| 417 | |
|---|
| 418 | if sampleinfo is None: |
|---|
| 419 | raise NotImplementedError("SampleInfo is missing.") |
|---|
| 420 | if generalinfo is None: |
|---|
| 421 | raise NotImplementedError("GeneralInfo is missing.") |
|---|
| 422 | |
|---|
| 423 | for child in sampleinfo: |
|---|
| 424 | if child.tag == "SampleDescription": |
|---|
| 425 | sampledes = child |
|---|
| 426 | runinfodict["Sample"] = sampledes.text.replace("\n", " ") |
|---|
| 427 | break |
|---|
| 428 | |
|---|
| 429 | for child in generalinfo: |
|---|
| 430 | if child.tag == "Notes": |
|---|
| 431 | origtext = child.text |
|---|
| 432 | if origtext is None: |
|---|
| 433 | runinfodict["Notes"] = "(No Notes)" |
|---|
| 434 | else: |
|---|
| 435 | runinfodict["Notes"] = child.text.replace("\n", " ") |
|---|
| 436 | break |
|---|
| 437 | |
|---|
| 438 | return runinfodict |
|---|
| 439 | |
|---|
| 440 | # ENDCLASS |
|---|
| 441 | |
|---|
| 442 | |
|---|
| 443 | def generateRecordFormat(): |
|---|
| 444 | """ |
|---|
| 445 | """ |
|---|
| 446 | sampletitles = [] |
|---|
| 447 | samplenames = [] |
|---|
| 448 | sampleoperations = [] |
|---|
| 449 | for ib in xrange(len(RecordBase)): |
|---|
| 450 | sampletitles.append(RecordBase[ib][0]) |
|---|
| 451 | samplenames.append(RecordBase[ib][1]) |
|---|
| 452 | sampleoperations.append(RecordBase[ib][2]) |
|---|
| 453 | |
|---|
| 454 | return (sampletitles, samplenames, sampleoperations) |
|---|
| 455 | |
|---|
| 456 | |
|---|
| 457 | def write_record(wsname, instrument, ipts, run, rfilename): |
|---|
| 458 | """ Write the run info to a record file |
|---|
| 459 | """ |
|---|
| 460 | # Convert the record base to input arrays |
|---|
| 461 | sampletitles, samplenames, sampleoperations = generateRecordFormat() |
|---|
| 462 | |
|---|
| 463 | # Load NeXus file |
|---|
| 464 | # eventnexus = "/SNS/%s/IPTS-%d/0/%d/NeXus/%s_%d_event.nxs" % (instrument, ipts, run, instrument, run) |
|---|
| 465 | |
|---|
| 466 | |
|---|
| 467 | """ |
|---|
| 468 | try: |
|---|
| 469 | Load(Filename = eventnexus, OutputWorkspace = wsname, |
|---|
| 470 | LoadLogs = True, MetaDataOnly = True) |
|---|
| 471 | except RuntimeError as err: |
|---|
| 472 | print "Unable to load NeXus file %s. Error message: %s. " % (eventnexus, str(err)) |
|---|
| 473 | return False |
|---|
| 474 | """ |
|---|
| 475 | |
|---|
| 476 | # Determine mode |
|---|
| 477 | if os.path.exists(rfilename) is True: |
|---|
| 478 | filemode = "fastappend" |
|---|
| 479 | else: |
|---|
| 480 | filemode = "new" |
|---|
| 481 | |
|---|
| 482 | print "Output record file will be written to %s. " % (rfilename) |
|---|
| 483 | |
|---|
| 484 | # Write log |
|---|
| 485 | ExportExperimentLog(InputWorkspace = wsname, |
|---|
| 486 | OutputFilename = rfilename, |
|---|
| 487 | FileMode = filemode, |
|---|
| 488 | SampleLogNames = samplenames, |
|---|
| 489 | SampleLogTitles = sampletitles, |
|---|
| 490 | SampleLogOperation = sampleoperations, |
|---|
| 491 | TimeZone = "America/New_York") |
|---|
| 492 | |
|---|
| 493 | # Patch for logs that do not exist in event NeXus yet |
|---|
| 494 | testclass = PatchRecord(instrument, ipts, run) |
|---|
| 495 | testclass.patchRecord(rfilename) |
|---|
| 496 | |
|---|
| 497 | return True |
|---|
| 498 | |
|---|
| 499 | |
|---|
| 500 | def mainProcess(eventFileAbs, outputDir): |
|---|
| 501 | """ Main |
|---|
| 502 | eventFileAbs=sys.argv[1] |
|---|
| 503 | """ |
|---|
| 504 | |
|---|
| 505 | # Obtain information from input file name and path |
|---|
| 506 | eventFile = os.path.split(eventFileAbs)[-1] |
|---|
| 507 | nexusDir = eventFileAbs.replace(eventFile, '') |
|---|
| 508 | runNumber = int(eventFile.split('_')[1]) |
|---|
| 509 | configService = mantid.config |
|---|
| 510 | dataSearchPath = configService.getDataSearchDirs() |
|---|
| 511 | dataSearchPath.append(nexusDir) |
|---|
| 512 | configService.setDataSearchDirs(";".join(dataSearchPath)) |
|---|
| 513 | |
|---|
| 514 | # Check file's existence |
|---|
| 515 | if os.path.exists(eventFileAbs) is False: |
|---|
| 516 | print "NeXus file %s is not accessible or does not exist. " % (eventFileAbs) |
|---|
| 517 | return |
|---|
| 518 | |
|---|
| 519 | # Find out IPTS |
|---|
| 520 | if eventFileAbs.count("IPTS") == 1: |
|---|
| 521 | terms = eventFileAbs.split("/") |
|---|
| 522 | for t in terms: |
|---|
| 523 | if t.count("IPTS") == 1: |
|---|
| 524 | iptsstr = t |
|---|
| 525 | break |
|---|
| 526 | ipts = int(iptsstr.split("-")[1]) |
|---|
| 527 | else: |
|---|
| 528 | ipts = 0 |
|---|
| 529 | |
|---|
| 530 | # Change the input 'OutputDir' to .../logs/ as instrument scientist requests |
|---|
| 531 | outputDir = changeOutputDir(outputDir) |
|---|
| 532 | |
|---|
| 533 | # Load file to generate the matrix workspace with some logs |
|---|
| 534 | logwsname = "VULCAN_%d_MetaDataOnly" % (runNumber) |
|---|
| 535 | |
|---|
| 536 | try: |
|---|
| 537 | Load(Filename=eventFileAbs, OutputWorkspace=logwsname, MetaDataOnly = True, LoadLogs = True) |
|---|
| 538 | except RuntimeError as err: |
|---|
| 539 | print "Unable to load NeXus file %s. Error message: %s. " % (eventFileAbs, str(err)) |
|---|
| 540 | return |
|---|
| 541 | |
|---|
| 542 | # Convert Furnace"/tmp/furnace41703.txt" |
|---|
| 543 | exportFurnaceLog(logwsname, outputDir, runNumber) |
|---|
| 544 | |
|---|
| 545 | # Write out loadframe /MTS log |
|---|
| 546 | exportMTSLog(logwsname, outputDir, ipts, runNumber) |
|---|
| 547 | |
|---|
| 548 | # Write experiment log (Record.txt) |
|---|
| 549 | rfilename = "/SNS/VULCAN/IPTS-%d/shared/AutoRecord_Manual.txt" % (ipts) |
|---|
| 550 | if USELOCAL is True: |
|---|
| 551 | rfilename = "%s/AutoRecord_Manual.txt" % (outputDir) |
|---|
| 552 | instrument="VULCAN" |
|---|
| 553 | exportgood = write_record(logwsname, instrument, ipts, runNumber, rfilename) |
|---|
| 554 | |
|---|
| 555 | # SNSPowderReduction(Instrument="PG3", RunNumber=runNumber, Extension="_event.nxs", |
|---|
| 556 | # PreserveEvents=True,PushDataPositive="AddMinimum", |
|---|
| 557 | # CalibrationFile=cal_file, CharacterizationRunsFile=char_file, |
|---|
| 558 | # LowResRef=0, RemovePromptPulseWidth=50, |
|---|
| 559 | # Binning=-0.0008, BinInDspace=True, FilterBadPulses=True, |
|---|
| 560 | # ScaleData =100, |
|---|
| 561 | # SaveAs="gsas topas and fullprof", OutputDirectory=outputDir, |
|---|
| 562 | # FinalDataUnits="dSpacing") |
|---|
| 563 | |
|---|
| 564 | return |
|---|
| 565 | |
|---|
| 566 | |
|---|
| 567 | def main(): |
|---|
| 568 | """ Main |
|---|
| 569 | """ |
|---|
| 570 | if len(sys.argv) < 3: |
|---|
| 571 | print "Inputs: [1. IPTS] [2. File containing run number] [3. Output directory]" |
|---|
| 572 | return |
|---|
| 573 | |
|---|
| 574 | ipts = int(sys.argv[1]) |
|---|
| 575 | runfilename = sys.argv[2] |
|---|
| 576 | outputDir=sys.argv[3] |
|---|
| 577 | |
|---|
| 578 | # parse run number file |
|---|
| 579 | rfile = open(runfilename) |
|---|
| 580 | lines = rfile.readlines() |
|---|
| 581 | rfile.close() |
|---|
| 582 | |
|---|
| 583 | runs = [] |
|---|
| 584 | for line in lines: |
|---|
| 585 | line = line.strip() |
|---|
| 586 | if len(line) > 0: |
|---|
| 587 | terms = line.split() |
|---|
| 588 | for t in terms: |
|---|
| 589 | run = int(t) |
|---|
| 590 | runs.append(run) |
|---|
| 591 | |
|---|
| 592 | # sort runs |
|---|
| 593 | runs = sorted(runs) |
|---|
| 594 | |
|---|
| 595 | # generate log |
|---|
| 596 | for run in runs: |
|---|
| 597 | eventFileAbs = "/SNS/VULCAN/IPTS-%d/0/%d/NeXus/VULCAN_%d_event.nxs" % (ipts, run, run) |
|---|
| 598 | mainProcess(eventFileAbs, outputDir) |
|---|
| 599 | |
|---|
| 600 | return |
|---|
| 601 | |
|---|
| 602 | |
|---|
| 603 | if __name__ == "__main__": |
|---|
| 604 | main() |
|---|