4
4
import os
5
5
import sys
6
6
import imp
7
- import copy
8
7
import logging
9
8
import pprint
10
- from platform import platform
9
+ from math import ceil
11
10
from event import Event
12
-
11
+ import timeit
13
12
14
13
class Setup (object ):
15
14
'''The Looper creates a Setup object to hold information relevant during
@@ -32,7 +31,7 @@ def __init__(self, config, services):
32
31
services: dictionary of services indexed by service name.
33
32
The service name has the form classObject_instanceLabel
34
33
as in this example:
35
- heppy .framework.services.tfile.TFileService_myhists
34
+ <base_heppy_path> .framework.services.tfile.TFileService_myhists
36
35
To find out about the service name of a given service,
37
36
load your configuration file in python, and print the service.
38
37
'''
@@ -51,7 +50,7 @@ class Looper(object):
51
50
def __init__ ( self , name ,
52
51
config ,
53
52
nEvents = None ,
54
- firstEvent = 0 , nPrint = 0 ):
53
+ firstEvent = 0 , nPrint = 0 , timeReport = False ):
55
54
"""Handles the processing of an event sample.
56
55
An Analyzer is built for each Config.Analyzer present
57
56
in sequence. The Looper can then be used to process an event,
@@ -79,20 +78,33 @@ def __init__( self, name,
79
78
self .nEvents = nEvents
80
79
self .firstEvent = firstEvent
81
80
self .nPrint = int (nPrint )
81
+ self .timeReport = [ {'time' :0.0 ,'events' :0 } for a in self .analyzers ] if timeReport else False
82
82
tree_name = None
83
83
if ( hasattr (self .cfg_comp , 'tree_name' ) ):
84
84
tree_name = self .cfg_comp .tree_name
85
85
if len (self .cfg_comp .files )== 0 :
86
86
errmsg = 'please provide at least an input file in the files attribute of this component\n ' + str (self .cfg_comp )
87
87
raise ValueError ( errmsg )
88
88
self .events = config .events_class (self .cfg_comp .files , tree_name )
89
+ if hasattr (self .cfg_comp , 'fineSplit' ):
90
+ fineSplitIndex , fineSplitFactor = self .cfg_comp .fineSplit
91
+ if fineSplitFactor > 1 :
92
+ if len (self .cfg_comp .files ) != 1 :
93
+ raise RuntimeError , "Any component with fineSplit > 1 is supposed to have just a single file, while %s has %s" % (self .cfg_comp .name , self .cfg_comp .files )
94
+ totevents = min (len (self .events ),int (nEvents )) if (nEvents and int (nEvents ) not in [- 1 ,0 ]) else len (self .events )
95
+ self .nEvents = int (ceil (totevents / float (fineSplitFactor )))
96
+ self .firstEvent = firstEvent + fineSplitIndex * self .nEvents
97
+ #print "For component %s will process %d events starting from the %d one" % (self.cfg_comp.name, self.nEvents, self.firstEvent)
89
98
# self.event is set in self.process
90
99
self .event = None
91
100
services = dict ()
92
101
for cfg_serv in config .services :
93
102
service = self ._build (cfg_serv )
94
103
services [cfg_serv .name ] = service
95
- self .setup = Setup ( copy .deepcopy (config ), services )
104
+ # would like to provide a copy of the config to the setup,
105
+ # so that analyzers cannot modify the config of other analyzers.
106
+ # but cannot copy the autofill config.
107
+ self .setup = Setup (config , services )
96
108
97
109
def _build (self , cfg ):
98
110
theClass = cfg .class_object
@@ -102,14 +114,16 @@ def _build(self, cfg):
102
114
def _prepareOutput (self , name ):
103
115
index = 0
104
116
tmpname = name
105
- while True :
117
+ while True and index < 2000 :
106
118
try :
107
119
# print 'mkdir', self.name
108
120
os .mkdir ( tmpname )
109
121
break
110
122
except OSError :
111
123
index += 1
112
124
tmpname = '%s_%d' % (name , index )
125
+ if index == 2000 :
126
+ raise ValueError ( "More than 2000 output folder with same name or 2000 attempts failed, please clean-up, change name or check permissions" )
113
127
return tmpname
114
128
115
129
@@ -141,8 +155,18 @@ def loop(self):
141
155
# if iEv == nEvents:
142
156
# break
143
157
if iEv % 100 == 0 :
144
- print 'event' , iEv
158
+ # print 'event', iEv
159
+ if not hasattr (self ,'start_time' ):
160
+ print 'event' , iEv
161
+ self .start_time = timeit .default_timer ()
162
+ self .start_time_event = iEv
163
+ else :
164
+ print 'event %d (%.1f ev/s)' % (iEv , (iEv - self .start_time_event )/ float (timeit .default_timer () - self .start_time ))
165
+
145
166
self .process ( iEv )
167
+ if iEv < self .nPrint :
168
+ print self .event
169
+
146
170
except UserWarning :
147
171
print 'Stopped loop following a UserWarning exception'
148
172
for analyzer in self .analyzers :
@@ -162,10 +186,16 @@ def process(self, iEv ):
162
186
"""
163
187
self .event = Event (iEv , self .events [iEv ], self .setup )
164
188
self .iEvent = iEv
165
- for analyzer in self .analyzers :
189
+ for i , analyzer in enumerate ( self .analyzers ) :
166
190
if not analyzer .beginLoopCalled :
167
191
analyzer .beginLoop ()
168
- if analyzer .process ( self .event ) == False :
192
+ start = timeit .default_timer ()
193
+ ret = analyzer .process ( self .event )
194
+ if self .timeReport :
195
+ self .timeReport [i ]['events' ] += 1
196
+ if self .timeReport [i ]['events' ] > 0 :
197
+ self .timeReport [i ]['time' ] += timeit .default_timer () - start
198
+ if ret == False :
169
199
return (False , analyzer .name )
170
200
if iEv < self .nPrint :
171
201
self .logger .info ( self .event .__str__ () )
@@ -177,8 +207,17 @@ def write(self):
177
207
See Analyzer.Write for more information.
178
208
"""
179
209
for analyzer in self .analyzers :
180
- analyzer .write ()
210
+ analyzer .write (self . setup )
181
211
self .setup .close ()
212
+
213
+ if self .timeReport :
214
+ allev = max ([x ['events' ] for x in self .timeReport ])
215
+ print "\n ---- TimeReport (all times in ms; first evt is skipped) ---- "
216
+ print "%9s %9s %9s %9s %s" % ("processed" ,"all evts" ,"time/proc" , " time/all" , "analyer" )
217
+ print "%9s %9s %9s %9s %s" % ("---------" ,"--------" ,"---------" , "---------" , "-------------" )
218
+ for ana ,rep in zip (self .analyzers ,self .timeReport ):
219
+ print "%9d %9d %10.2f %10.2f %s" % ( rep ['events' ], allev , 1000 * rep ['time' ]/ (rep ['events' ]- 1 ) if rep ['events' ]> 1 else 0 , 1000 * rep ['time' ]/ (allev - 1 ) if allev > 1 else 0 , ana .name )
220
+ print ""
182
221
pass
183
222
184
223
@@ -187,16 +226,22 @@ def write(self):
187
226
import pickle
188
227
import sys
189
228
import os
190
-
191
- cfgFileName = sys .argv [1 ]
192
- pckfile = open ( cfgFileName , 'r' )
193
- config = pickle .load ( pckfile )
194
- comp = config .components [0 ]
195
- events_class = config .events_class
196
- looper = Looper ( 'Loop' , comp ,
197
- config .sequence ,
198
- config .services ,
199
- events_class ,
200
- nPrint = 5 )
229
+ if len (sys .argv ) == 2 :
230
+ cfgFileName = sys .argv [1 ]
231
+ pckfile = open ( cfgFileName , 'r' )
232
+ config = pickle .load ( pckfile )
233
+ comp = config .components [0 ]
234
+ events_class = config .events_class
235
+ elif len (sys .argv ) == 3 :
236
+ cfgFileName = sys .argv [1 ]
237
+ file = open ( cfgFileName , 'r' )
238
+ cfg = imp .load_source ( 'cfg' , cfgFileName , file )
239
+ compFileName = sys .argv [2 ]
240
+ pckfile = open ( compFileName , 'r' )
241
+ comp = pickle .load ( pckfile )
242
+ cfg .config .components = [comp ]
243
+ events_class = cfg .config .events_class
244
+
245
+ looper = Looper ( 'Loop' , cfg .config ,nPrint = 5 )
201
246
looper .loop ()
202
247
looper .write ()
0 commit comments