-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIO.py
More file actions
215 lines (205 loc) · 7.76 KB
/
Copy pathIO.py
File metadata and controls
215 lines (205 loc) · 7.76 KB
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
"""
IO Module
This module defines the inout/output interfaces
"""
from Utils import Error,logger,NotYet,WrongDataType
_logger=logger().getLogger('IO')
class Input:
"""
Base Class for input
"""
def __init__(self):
self.input = None
self.name = None
def getObject(self):
"""
Returns the input object
"""
return self.input
def __str__(self):
try:
return 'Input: %s'%self.name
except:
return 'Input: %s'%self.name
def __call__(self):
raise BaseClass()
class FileInput(Input):
"""
Read input from File.
Currently ROOT's TFile inputs are supported
"""
class FileType:
ROOT = 1
def __init__(self,filename,afiletype=FileType.ROOT):
self.filetype = afiletype
if filename != None:
if self.filetype == FileInput.FileType.ROOT:
from ROOT import TFile
self.tfile = TFile.Open( filename )
else:
_logger.error("Functionality not yet implemented")
raise NotYet()
else:
self.tfile = None
Input.__init__(self)
def _readHisto(self,name):
self.input = self.tfile.Get( name )
if not self.input.IsA().InheritsFrom("TH1"):
raise WrongDataType()
def _readBranch(self,treename,branchname):
tree=self.tfile.Get(treename)
if not tree.IsA().InheritsFrom("TTree"):
raise WrongDataType()
self.input = tree.GetBranch(branchname)
def getFileObject(self):
return self.tfile
def __str__(self):
fn = str(self.tfile)
if self.tfile.__class__.__name__ == 'TFile':
fn = self.tfile.GetName()
return "%s (from file:%s)"%(Input.__str__(self),fn)
class Histogram(FileInput):
"""
Get a histogram from a file
"""
def __init__(self,afile,hname):
"""
Create an Input histogram contained in file 'file'
"""
#Check if file is a name (string) or object
if type(afile)==type(str()):
if afile.find('.root')>0:
FileInput.__init__(self,afile,FileInput.FileType.ROOT)
else:
_logger.error("Cannot recognize filen: %s"%file)
raise NotYet()
else:
FileInput.__init__(self,None)
self.tfile=afile
self._readHisto(hname)
def __call__(self):
return self.getObject()
class Branch(FileInput):
"""
Get data from a Branch
"""
class BranchType:
"""
Supported data types: float, double, int, vector<double>
"""
from ctypes import c_float,c_double,c_int
FLOAT = 1
DOUBLE = 2
INT = 3
VECTORDOUBLE = 4 #Special case for std::vector<double>
_typesMap={ FLOAT : c_float ,
DOUBLE : c_double ,
INT : c_int ,
VECTORDOUBLE : None , #Need special care
}
@staticmethod
def stringToValue( str ):
if str == "FLOAT":
return Branch.BranchType.FLOAT
elif str == "DOUBLE":
return Branch.BranchType.DOUBLE
elif str == "INT":
return Branch.BranchType.INT
elif str == "VECTORDOUBLE":
return Branch.BranchType.VECTORDOUBLE
print "ERROR: Cannot recognize %s"%str
raise WrongDataType()
def __init__(self,afile,treename,brname,brtype=BranchType.DOUBLE,nelements=1,element=-1):
"""
Create a Branch input
@input afile: the file from where to read
@input treename: the tree name
@input brname: the name of the branch to read from
@input brtype: the data type contained in the branch
@input nelements: number of elements in the branch (i.e. array size of the branch)
@input element: which element of the array to use (-1: all)
Note: data are cached, use resetCache function to reset cache.
"""
self._cache=None
self.branchType = brtype
self.nelements = nelements
self.element = element
#Check if file is a name (string) or object
if type(afile)==type(str()):
if afile.find('.root')>0:
FileInput.__init__(self,afile,FileInput.FileType.ROOT)
else:
_logger.error("Cannot recognize file name: %s"%afile)
raise NotYet()
else:
FileInput.__init__(self,None)
self.tfile=afile
self._readBranch(treename,brname)
def resetCache(self):
self._cache=None
def __call__(self):
if self.filetype == FileInput.FileType.ROOT:
return self.readFromROOT()
else:
_logger.error("Input File Type not supported")
raise NotYet()
def readFromROOT(self):
#Check if data have already been read,
#if not read in branch data
if self._cache == None:
branch = self.getObject()
if self.branchType == Branch.BranchType.VECTORDOUBLE:
#Use some ROOT's stuff to read vector<double>
#Note we need to use ROOT.Double to have correct data type in vectors
from ROOT import std,Double,AddressOf
#Create a vector to contain doubles
vect = std.vector(Double)(self.nelements,0)
data = AddressOf( vect )
else:
#Create an array to store data for each entry
datatype = self.nelements * Branch.BranchType._typesMap[ self.branchType ]
data = datatype()
#Set address of branch to the array
branch.SetAddress( data )
#Loop on events
self._cache = []
for entry in xrange( branch.GetEntries() ):
branch.GetEntry( entry )
#First simple case of simple variable
if self.nelements == 1 and self.branchType != Branch.BranchType.VECTORDOUBLE:
self._cache.append( data[0] )
else:
#Check if specific element is needed or all elements
if self.element == -1:
#Loop on elements of arrays
d = []
for elem in xrange( self.nelements ):
if self.branchType == Branch.BranchType.VECTORDOUBLE:
d.append( vect.at(elem) )
else:
d.append( data[elem] )
else:
#Get array/vector element self.element
if self.branchType == Branch.BranchType.VECTORDOUBLE:
d = vect.at( self.element )
else:
d = data[self.element]
self._cache.append( d )
return self._cache
def testme(fn="AtlasECAL_pi-_100_QGSP_BERT_95ref02.root"):
input1 = Histogram( fn , "Spectra/hProtonSpectrum" )
histogram1= input1()
print input1,histogram1
#Re-use open file
input2 = Histogram( input1.getFileObject() , "Spectra/hNeutronSpectrum" )
print input2,input2()
input3 = Branch( "AtlasECAL_pi-_100_QGSP_BERT_95p01.root", "SimplifiedCalorimeter","EDEP_ACT" , Branch.BranchType.FLOAT )
branch=input3()
print input3,len(branch)
input4 = Branch( input3.getFileObject() ,"SimplifiedCalorimeter","EDEP_CAL" , Branch.BranchType.FLOAT )
br2=input4()
print input4,len(input4()),br2[0:3] #Pring using cached values
#Reading a std::vector<double>
input5 = Branch( input3.getFileObject() , "SimplifiedCalorimeter","R",Branch.BranchType.VECTORDOUBLE,10)
br3 = input5()
print input4,len(br3),br3[0]