Ticket #6594: SANSadd2.py

File SANSadd2.py, 10.6 KB (added by Gesner Passos, 8 years ago)

Old version of SANSadd2.py that has bug.

Line 
1from mantidsimple import *
2from shutil import copyfile
3
4_NO_INDIVIDUAL_PERIODS = -1
5
6def 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
160def _can_load_periods(runs, defType, rawTypes):
161  """
162Searches through the supplied list of run file names and
163returns 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
174def _makeFilename(entry, ext, inst) :
175  """
176If 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
187def _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
243def _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
255def _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
267def _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