1 | from mantidsimple import * |
---|
2 | from shutil import copyfile |
---|
3 | |
---|
4 | _NO_INDIVIDUAL_PERIODS = -1 |
---|
5 | |
---|
6 | def add_runs(runs, inst='sans2d', defType='.nxs', rawTypes=('.raw', '.s*', 'add'), lowMem=False, binning='Monitors'): |
---|
7 | #check if there is at least one file in the list |
---|
8 | if len(runs) < 1 : return |
---|
9 | |
---|
10 | if not defType.startswith('.') : defType = '.'+defType |
---|
11 | |
---|
12 | #these input arguments need to be arrays of strings, enforce this |
---|
13 | if type(runs) == str : runs = (runs, ) |
---|
14 | if type(rawTypes) == str : rawTypes = (rawTypes, ) |
---|
15 | |
---|
16 | if lowMem: |
---|
17 | lowMem = _can_load_periods(runs, defType, rawTypes) |
---|
18 | if lowMem: |
---|
19 | period = 1 |
---|
20 | else: |
---|
21 | period = _NO_INDIVIDUAL_PERIODS |
---|
22 | |
---|
23 | userEntry = runs[0] |
---|
24 | |
---|
25 | while(True): |
---|
26 | |
---|
27 | isFirstDataSetEvent = False |
---|
28 | #we need to catch all exceptions to ensure that a dialog box is raised with the error |
---|
29 | try : |
---|
30 | lastPath, lastFile, logFile, num_periods, isFirstDataSetEvent = _loadWS( |
---|
31 | userEntry, defType, inst, 'AddFilesSumTempory', rawTypes, period) |
---|
32 | |
---|
33 | # if event data prevent loop over periods makes no sense |
---|
34 | if isFirstDataSetEvent: |
---|
35 | period = _NO_INDIVIDUAL_PERIODS |
---|
36 | |
---|
37 | if inst.upper() != 'SANS2D' and isFirstDataSetEvent: |
---|
38 | error = 'Adding event data not supported for ' + inst + ' for now' |
---|
39 | print error |
---|
40 | mantid.sendLogMessage(error) |
---|
41 | if mantid.workspaceExists('AddFilesSumTempory') : mantid.deleteWorkspace('AddFilesSumTempory') |
---|
42 | if mantid.workspaceExists('AddFilesSumTempory_monitors') : mantid.deleteWorkspace('AddFilesSumTempory_monitors') |
---|
43 | return "" |
---|
44 | |
---|
45 | for i in range(len(runs)-1): |
---|
46 | userEntry = runs[i+1] |
---|
47 | lastPath, lastFile, logFile, dummy, isDataSetEvent = _loadWS( |
---|
48 | userEntry, defType, inst,'AddFilesNewTempory', rawTypes, period) |
---|
49 | |
---|
50 | if isDataSetEvent != isFirstDataSetEvent: |
---|
51 | error = 'Datasets added must be either ALL histogram data or ALL event data' |
---|
52 | print error |
---|
53 | mantid.sendLogMessage(error) |
---|
54 | if mantid.workspaceExists('AddFilesSumTempory') : mantid.deleteWorkspace('AddFilesSumTempory') |
---|
55 | if mantid.workspaceExists('AddFilesNewTempory') : mantid.deleteWorkspace('AddFilesNewTempory') |
---|
56 | return "" |
---|
57 | |
---|
58 | Plus('AddFilesSumTempory', 'AddFilesNewTempory', 'AddFilesSumTempory') |
---|
59 | if isFirstDataSetEvent: |
---|
60 | Plus('AddFilesSumTempory_monitors', 'AddFilesNewTempory_monitors', 'AddFilesSumTempory_monitors') |
---|
61 | mantid.deleteWorkspace("AddFilesNewTempory") |
---|
62 | if isFirstDataSetEvent: |
---|
63 | mantid.deleteWorkspace("AddFilesNewTempory_monitors") |
---|
64 | |
---|
65 | except ValueError, reason: |
---|
66 | error = 'Error opening file ' + userEntry+': ' + reason.message |
---|
67 | print error |
---|
68 | mantid.sendLogMessage(error) |
---|
69 | if mantid.workspaceExists('AddFilesSumTempory') : mantid.deleteWorkspace('AddFilesSumTempory') |
---|
70 | return "" |
---|
71 | except Exception, reason: |
---|
72 | error = 'Error finding files: ' + reason.message |
---|
73 | print error |
---|
74 | mantid.sendLogMessage(error) |
---|
75 | if mantid.workspaceExists('AddFilesSumTempory') : mantid.deleteWorkspace('AddFilesSumTempory') |
---|
76 | if mantid.workspaceExists('AddFilesNewTempory') : mantid.deleteWorkspace("AddFilesNewTempory") |
---|
77 | return "" |
---|
78 | |
---|
79 | # in case of event file force it into a histogram workspace |
---|
80 | if isFirstDataSetEvent: |
---|
81 | wsInMonitor = mtd['AddFilesSumTempory_monitors'] |
---|
82 | if binning == 'Monitors': |
---|
83 | monX = wsInMonitor.dataX(i) |
---|
84 | binning = str(monX[0]) |
---|
85 | binGap = monX[1] - monX[0] |
---|
86 | binning = binning + "," + str(binGap) |
---|
87 | for j in range(2,len(monX)): |
---|
88 | nextBinGap = monX[j] - monX[j-1] |
---|
89 | if nextBinGap != binGap: |
---|
90 | binGap = nextBinGap |
---|
91 | binning = binning + "," + str(monX[j-1]) + "," + str(binGap) |
---|
92 | binning = binning + "," + str(monX[len(monX)-1]) |
---|
93 | |
---|
94 | mantid.sendLogMessage(binning) |
---|
95 | Rebin('AddFilesSumTempory','AddFilesSumTempory_Rebin', binning, PreserveEvents=False) |
---|
96 | |
---|
97 | filename, ext = _makeFilename(runs[0], defType, inst) |
---|
98 | LoadNexus(filename, OutputWorkspace='AddFilesSumTempory') |
---|
99 | # User may have selected a binning which is different from the default |
---|
100 | Rebin('AddFilesSumTempory','AddFilesSumTempory', binning) |
---|
101 | # For now the monitor binning must be the same as the detector binning |
---|
102 | # since otherwise both cannot exist in the same output histogram file |
---|
103 | Rebin('AddFilesSumTempory_monitors','AddFilesSumTempory_monitors', binning) |
---|
104 | |
---|
105 | wsInMonitor = mtd['AddFilesSumTempory_monitors'] |
---|
106 | wsOut = mtd['AddFilesSumTempory'] |
---|
107 | wsInDetector = mtd['AddFilesSumTempory_Rebin'] |
---|
108 | for i in range(4): |
---|
109 | outY = wsOut.dataY(i) |
---|
110 | outE = wsOut.dataE(i) |
---|
111 | monitorY = wsInMonitor.readY(i) |
---|
112 | monitorE = wsInMonitor.readE(i) |
---|
113 | for j in range(len(outY)): |
---|
114 | outY[j] = monitorY[j] |
---|
115 | outE[j] = monitorE[j] |
---|
116 | |
---|
117 | |
---|
118 | for i in range(4, 73732): |
---|
119 | outY = wsOut.dataY(i+4) |
---|
120 | outE = wsOut.dataE(i+4) |
---|
121 | detectorY = wsInDetector.readY(i) |
---|
122 | detectorE = wsInDetector.readE(i) |
---|
123 | for j in range(len(outY)): |
---|
124 | outY[j] = detectorY[j] |
---|
125 | outE[j] = detectorE[j] |
---|
126 | |
---|
127 | if mantid.workspaceExists('AddFilesSumTempory_Rebin') : mantid.deleteWorkspace('AddFilesSumTempory_Rebin') |
---|
128 | |
---|
129 | lastFile = os.path.splitext(lastFile)[0] |
---|
130 | # now save the added file |
---|
131 | outFile = lastFile+'-add.'+'nxs' |
---|
132 | mantid.sendLogMessage('writing file: '+outFile) |
---|
133 | if period == 1 or period == _NO_INDIVIDUAL_PERIODS: |
---|
134 | #replace the file the first time around |
---|
135 | sav = SaveNexusProcessed("AddFilesSumTempory", outFile, Append=False) |
---|
136 | else: |
---|
137 | #then append |
---|
138 | sav = SaveNexusProcessed("AddFilesSumTempory", outFile, Append=True) |
---|
139 | |
---|
140 | mantid.deleteWorkspace("AddFilesSumTempory") |
---|
141 | if isFirstDataSetEvent: |
---|
142 | mantid.deleteWorkspace("AddFilesSumTempory_monitors") |
---|
143 | |
---|
144 | if period == num_periods: |
---|
145 | break |
---|
146 | |
---|
147 | if period == _NO_INDIVIDUAL_PERIODS: |
---|
148 | break |
---|
149 | else: |
---|
150 | period += 1 |
---|
151 | |
---|
152 | #this adds the path to the filename |
---|
153 | outFile = sav.getPropertyValue('Filename') |
---|
154 | pathout = os.path.split(outFile)[0] |
---|
155 | if logFile: |
---|
156 | _copyLog(lastPath, logFile, pathout) |
---|
157 | |
---|
158 | return 'The following file has been created:\n'+outFile |
---|
159 | |
---|
160 | def _can_load_periods(runs, defType, rawTypes): |
---|
161 | """ |
---|
162 | Searches through the supplied list of run file names and |
---|
163 | returns False if some appear to be raw files else True |
---|
164 | """ |
---|
165 | for i in runs: |
---|
166 | dummy, ext = os.path.splitext(i) |
---|
167 | if ext == '': ext = defType |
---|
168 | if _isType(ext, rawTypes): |
---|
169 | return False |
---|
170 | #no raw files were found, assume we can specify the period number for each |
---|
171 | return True |
---|
172 | |
---|
173 | |
---|
174 | def _makeFilename(entry, ext, inst) : |
---|
175 | """ |
---|
176 | If entry not already a valid filename make it into one |
---|
177 | """ |
---|
178 | try : |
---|
179 | runNum = int(entry) #the user entered something that translates to a run number, convert it to a file |
---|
180 | filename=inst+_padZero(runNum, inst)+ext |
---|
181 | except ValueError : #we don't have a run number, assume it's a valid filename |
---|
182 | filename = entry |
---|
183 | dummy, ext = os.path.splitext(filename) |
---|
184 | |
---|
185 | return filename, ext |
---|
186 | |
---|
187 | def _loadWS(entry, ext, inst, wsName, rawTypes, period=_NO_INDIVIDUAL_PERIODS) : |
---|
188 | |
---|
189 | filename, ext = _makeFilename(entry, ext, inst) |
---|
190 | |
---|
191 | mantid.sendLogMessage('reading file: '+filename) |
---|
192 | |
---|
193 | if period != _NO_INDIVIDUAL_PERIODS: |
---|
194 | #load just a single period |
---|
195 | props = Load(Filename=filename,OutputWorkspace=wsName, EntryNumber=period) |
---|
196 | else: |
---|
197 | props = Load(Filename=filename,OutputWorkspace=wsName) |
---|
198 | |
---|
199 | isDataSetEvent = False |
---|
200 | wsDataSet = mtd[wsName] |
---|
201 | if hasattr(wsDataSet, 'getNumberEvents'): |
---|
202 | isDataSetEvent = True |
---|
203 | |
---|
204 | if isDataSetEvent: |
---|
205 | LoadEventNexus(Filename=filename,OutputWorkspace=wsName, LoadMonitors=True) |
---|
206 | runDetails = mtd[wsName].getRun() |
---|
207 | timeArray = runDetails.getLogData("proton_charge").times |
---|
208 | # There should never be a time increment in the proton charge larger than say "two weeks" |
---|
209 | # SANS2D currently is run at 10 frames per second. This may be increated to 5Hz |
---|
210 | # (step of 0.2 sec). Although time between frames may be larger due to having the SMP veto switched on, |
---|
211 | # but hopefully not longer than two weeks! |
---|
212 | for i in range(len(timeArray)-1): |
---|
213 | # cal time dif in seconds |
---|
214 | timeDif = (timeArray[i+1].total_nanoseconds()-timeArray[i].total_nanoseconds())*1e-9 |
---|
215 | if timeDif > 172800: |
---|
216 | mantid.sendLogMessage('::SANS::WARNING: Time increments in the proton charge log of ' + filename + ' are suspicious large.' + |
---|
217 | ' For example a time difference of ' + str(timeDif) + " seconds has been observed.") |
---|
218 | break |
---|
219 | |
---|
220 | path = props.getPropertyValue('FileName') |
---|
221 | path, fName = os.path.split(path) |
---|
222 | if path.find('/') == -1: |
---|
223 | #looks like we're on a windows system, convert the directory separators |
---|
224 | path = path.replace('\\', '/') |
---|
225 | |
---|
226 | if _isType(ext, rawTypes): |
---|
227 | LoadSampleDetailsFromRaw(wsName, path+'/'+fName) |
---|
228 | |
---|
229 | logFile = None |
---|
230 | #change below when logs in Nexus files work file types of .raw need their log files to be copied too |
---|
231 | if True:#_isType(ext, rawTypes): |
---|
232 | logFile = os.path.splitext(fName)[0]+'.log' |
---|
233 | |
---|
234 | try: |
---|
235 | samp = mtd[wsName].getSampleDetails() |
---|
236 | numPeriods = samp.getLogData('nperiods').value |
---|
237 | except: |
---|
238 | #assume the run file didn't support multi-period data and so there is only one period |
---|
239 | numPeriods = 1 |
---|
240 | |
---|
241 | return path, fName, logFile, numPeriods, isDataSetEvent |
---|
242 | |
---|
243 | def _padZero(runNum, inst='SANS2D'): |
---|
244 | if inst.upper() == 'SANS2D' : numDigits = 8 |
---|
245 | elif inst.upper() == 'LOQ' : numDigits = 5 |
---|
246 | else : raise NotImplementedError('The arguement inst must be set to SANS or LOQ') |
---|
247 | |
---|
248 | run = str(runNum).zfill(numDigits) |
---|
249 | return run |
---|
250 | |
---|
251 | ########################################## |
---|
252 | # returns true if ext is in the tuple allTypes, ext |
---|
253 | # is intended to be a file extension and allTypes a |
---|
254 | # list of allowed extensions. '*' at the end is supported |
---|
255 | def _isType(ext, allTypes): |
---|
256 | for oneType in allTypes: |
---|
257 | oneType = str(oneType) |
---|
258 | if oneType.endswith('*') : |
---|
259 | oneType = oneType[0:len(oneType)-1] |
---|
260 | if ext.startswith(oneType) : |
---|
261 | return True |
---|
262 | else : |
---|
263 | if ext == oneType : |
---|
264 | return True |
---|
265 | return False |
---|
266 | |
---|
267 | def _copyLog(lastPath, logFile, pathout): |
---|
268 | try : |
---|
269 | logFile = lastPath+'/'+logFile |
---|
270 | if os.path.exists(logFile): |
---|
271 | copyfile(logFile, pathout+'/'+os.path.basename(logFile)) |
---|
272 | else: |
---|
273 | mantid.sendLogMessage("Could not find log file %s" % logFile) |
---|
274 | except Exception, reason: |
---|
275 | error = 'Error copying log file ' + logFile + ' to directory ' + pathout+'\n' |
---|
276 | print error |
---|
277 | mantid.sendLogMessage(error) |
---|
278 | |
---|