-
Notifications
You must be signed in to change notification settings - Fork 122
/
LoadLogPropertyTable.py
170 lines (147 loc) · 7.57 KB
/
LoadLogPropertyTable.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#pylint: disable=no-init,invalid-name
import time
import datetime
import numbers
import bisect
import numpy
from mantid.api import * # PythonAlgorithm, AlgorithmFactory, WorkspaceProperty
from mantid.kernel import * # StringArrayProperty
from mantid.simpleapi import * # needed for Load
class LoadLogPropertyTable(PythonAlgorithm):
def summary(self):
""" Return summary
"""
return "Creates a table of Run number against the log values for that run for a range of files.\
It can use a single log value or a list of log values."
# same concept as built in "CreateLogPropertyTable" but loads its own workspaces and needn't hold all in memory at once
# select log values to put in table (list)
# special cases for:
# beamlog_(counts, frames, etc): last few points end up in next run's log. Find Maximum.
# comment (separate function)
# time series, take average for t>0 (if available)
def PyInit(self):
self.declareProperty(FileProperty(name="FirstFile",defaultValue="",action=FileAction.Load,extensions = ["nxs","raw"]),
"The first file to load from")
self.declareProperty(FileProperty(name="LastFile",defaultValue="",action=FileAction.Load,extensions = ["nxs","raw"]),
"The Last file to load from, must be in the same directory, all files in between will also be used")
self.declareProperty(StringArrayProperty("LogNames",direction=Direction.Input),
"The comma seperated list of properties to include. \n"+\
"The full list will be printed if an invalid value is used.")
self.declareProperty(WorkspaceProperty("OutputWorkspace","",Direction.Output),"Table of results")
def category(self):
return "DataHandling\\Logs;Muon\\DataHandling"
def getGeneralLogValue(self,ws,name,begin):
# get log value
# average time series over run
# for beamlog, etc return flag=true and value to push into previous run
if name=="comment":
return (ws.getComment(),False,0)
try:
v=ws.getRun().getProperty(name)
except:
possibleLogs = ws.getRun().keys()
possibleLogs.insert(0,'comment')
message = "The log name '" + name + "' was not found, possible choices are: " + str(possibleLogs)
raise ValueError(message)
try:
times2=[]
if hasattr(v,"unfiltered"):
v=v.unfiltered()
for tt in v.times:
times2.append((datetime.datetime(*(time.strptime(str(tt),"%Y-%m-%dT%H:%M:%S")[0:6]))-begin).total_seconds())
except StandardError:
# print "probably not a time series"
pass
if name[0:8]=="Beamlog_" and (name.find("Counts")>0 or name.find("Frames")>0):
i=bisect.bisect_right(times2,2) # allowance for "slow" clearing of DAE
#print "returning max beam log, list cut 0:",i,":",len(times2)
return (numpy.amax(v.value[i:]),True,numpy.amax(v.value[:i]))
if v.__class__.__name__ =="TimeSeriesProperty_dbl" or v.__class__.__name__ =="FloatTimeSeriesProperty":
i=bisect.bisect_left(times2,0)
return (numpy.average(v.value[i:]),False,0)
return (v.value,False,0)
#pylint: disable=too-many-branches
def PyExec(self):
firstFileName=self.getProperty("FirstFile").value
lastFileName=self.getProperty("LastFile").value
firstRunNum, firstFileFirstDigit,firstFileLastDigit = self.getRunNumber(firstFileName)
lastRunNum, lastFileFirstDigit,LastFileLastDigit = self.getRunNumber(lastFileName)
if firstFileName[:lastFileFirstDigit] != lastFileName[:lastFileFirstDigit]:
raise Exception("Files from different directories or instruments")
if firstFileName[firstFileName.rindex('.')] != lastFileName[firstFileName.rindex('.')]:
raise Exception("Files of different types")
if firstFileLastDigit-firstFileFirstDigit != LastFileLastDigit-lastFileFirstDigit:
raise Exception("File numbering error")
if lastRunNum < firstRunNum:
raise Exception("Run numbers must increase")
# table. Rows=runs, columns=logs (col 0 = run number)
collist=self.getProperty("LogNames").value
wsOutput=WorkspaceFactory.createTable()
wsOutput.addColumn("int","RunNumber")
# loop and load files. Absolute numbers for now.
for loopRunNum in range(firstRunNum,lastRunNum+1):
# create a file path for intervening files, based from the 1st filename
thispath=firstFileName[:firstFileFirstDigit] + \
str(loopRunNum).zfill(firstFileLastDigit-firstFileFirstDigit) + \
firstFileName[firstFileLastDigit:]
loadedWs = self.loadMetaData(thispath)
if loadedWs is None:
continue
#check if the ws is a group
ws = loadedWs
if ws.id() == 'WorkspaceGroup':
ws=ws[0]
begin=datetime.datetime(*(time.strptime(ws.getRun().getProperty("run_start").value,"%Y-%m-%dT%H:%M:%S")[0:6])) # start of day
vallist=[loopRunNum]
for col in collist:
try:
(colValue, leftover, lval)=self.getGeneralLogValue(ws, col, begin)
except ValueError:
# this is a failure to find the named log
raise
vallist.append(colValue)
if loopRunNum==firstRunNum:
if isinstance(colValue, numbers.Number):
wsOutput.addColumn("double",col)
else:
wsOutput.addColumn("str",col)
if leftover and loopRunNum>firstRunNum:
if lval>wsOutput.cell(col,loopRunNum-firstRunNum-1):
wsOutput.setCell(col,loopRunNum-firstRunNum-1, lval)
wsOutput.addRow(vallist)
self.setProperty("OutputWorkspace",wsOutput)
def loadMetaData(self, thispath):
loadedWs = None
try:
loadAlg = self.createChildAlgorithm('Load')
#set Filename first
loadAlg.setProperty('Filename', thispath)
loadAlg.setProperty('OutputWorkspace', '__CopyLogsTmp')
try:
#try to set MetaDataOnly
loadAlg.setProperty('MetaDataOnly', True)
except (ValueError,RuntimeError):
#If that fails set SpectrumMin and SpectrumMax
loadAlg.setProperty('SpectrumMin', 1)
loadAlg.setProperty('SpectrumMax', 1)
loadAlg.execute()
outWSPropName = 'OutputWorkspace'
try:
loadedWs = loadAlg.getProperty(outWSPropName).value
except RuntimeError:
raise RuntimeError("No output workspace for " + thispath)
except (ValueError,RuntimeError):
return None
return loadedWs
def getRunNumber(self, fileName):
# Find last . and step back until you find a digit
lastDigitIndex = fileName.rindex('.')
while not fileName[lastDigitIndex - 1].isdigit():
lastDigitIndex -= 1
# Keep going back until you find the start of the number sequence
firstDigitIndex = lastDigitIndex - 1
while fileName[firstDigitIndex - 1].isdigit():
firstDigitIndex -= 1
runNumber = int(fileName[firstDigitIndex:lastDigitIndex])
return runNumber, firstDigitIndex, lastDigitIndex
AlgorithmFactory.subscribe(LoadLogPropertyTable())