5 Collection of utilities to interface gallery with python.
7 This module requires ROOT.
13 'make_getValidHandle',
20 'startMessageFacility',
21 'ServiceRegistryClass',
22 'ConfigurationHelper',
27 from ROOTutils
import ROOT
35 SourceCode = cppUtils.SourceCode
36 readHeader = cppUtils.readHeader
44 """Make the ROOT C++ jit compiler instantiate the
45 Event::getValidHandle member template for template parameter klass.
47 Needs to keep track of what was done already, because Cling will protest if
48 the same class is asked twice.
53 if klass
in HandleMaker.AlreadyMade:
return
54 res = HandleMaker.make(klass)
55 if res != ROOT.TInterpreter.kNoError:
57 "Could not create `ROOT.gallery.Event.getValidHandle` for '%s' (code: %d)"
61 HandleMaker.AlreadyMade.add(klass)
63 return event.getValidHandle[klass]
if event \
64 else ROOT.gallery.Event.getValidHandle[klass]
69 ROOT.gROOT.ProcessLine(
'template gallery::ValidHandle<%(name)s> gallery::Event::getValidHandle<%(name)s>(art::InputTag const&) const;' % {
'name' : klass})
77 """Creates a file list suitable for `gallery::Event`."""
78 files = ROOT.vector(ROOT.string)()
79 for path
in filePaths: files.push_back(path)
86 Simplifies sequential event looping.
88 This function handles the state of `event`, moving the current event around.
89 Therefore, it has side effects.
90 The function returns `event` itself, after it has set to the next available
93 This function is actually a generator.
97 for iEvent, event in enumerate(forEach(event)):
102 while (
not event.atEnd()):
111 Iterator for an event sequence.
113 It can be used directly as:
115 for event in EventIterator(event): ...
117 or it can be plugged in directly in the gallery.Event class, making the latter
120 for event in event: ...
122 (or `for evt in event: ...`).
131 if self.
_index is not None:
134 if self._event.atEnd():
raise StopIteration
146 Applies the `process` function to each and every event from the specified
147 input files, in sequence.
149 The `inputFiles` list may be a single file, or a list (or any iterable object)
150 of files, or a `std::vector<std::string>` object.
152 The `process` callable is executed with two arguments: the number of argument
153 in the loop, and the event itself. No information on which file the event is
154 taken from is provided. If a call returns exactly `False`, it is considered
155 to have failed and an error counter is incremented. Exceptions raised in
156 `process` are not handled.
158 The error counter is returned at the end of the execution.
161 - 'nEvents': number of events to be processed (does not include skipped ones)
162 - 'nSkip': number of events from the beginning of the sample to be skipped
166 nSkip = options.get(
'nSkip', 0)
167 nEvents = options.get(
'nEvents',
None)
170 if not isinstance(inputFiles, ROOT.vector(ROOT.string)):
171 if isinstance(inputFiles, str): inputFiles = [ inputFiles, ]
175 event = ROOT.gallery.Event(inputFiles)
186 if iFile != event.fileEntry():
187 iFile = event.fileEntry()
188 print(
"Opening: '%s'" % inputFiles[iFile])
192 if iEvent < nSkip:
continue
193 if (nEvents
is not None)
and (nProcessedEvents >= nEvents):
break
194 nProcessedEvents += 1
199 res = process(event, iEvent)
200 if isinstance(res, bool)
and not res: nErrors += 1
208 print >>sys.stderr,
"Encountered %d/%d errors." % (nErrors, nProcessedEvents)
222 def findFHiCL(configRelPath, extraDirs = []):
224 if os.path.isfile(configRelPath):
225 return os.path.join(os.getcwd(), configRelPath)
226 for path
in extraDirs + os.environ.get(
'FHICL_FILE_PATH',
"").split(
':'):
227 candidate = os.path.join(path, configRelPath)
228 if os.path.isfile(candidate):
return candidate
237 Provides more user-friendly interface for the configuration access.
239 While FHiCL C++ interface is friendly enough, some of that is lost in Python
242 This helper class keeps a reference to the FHiCL configuration object, and
243 provides some `get()` overloads to make the interface easier.
247 def get(self, key, default=None, klass=None):
249 Returns the value associated with the specified key.
255 the key of the configuration parameter to be read
257 the value to provide if no key is present; if default is `None`,
258 no default is present and if key is missing a `KeyError` exception will
261 type of object returned (if `None`, it's taken from `default` if
267 An object of type `klass`, initialised with the value associated to `key`
273 `KeyError` if the `key` is not present in the configuration and `default` is
278 assert default
is not None
279 klass = default.__class__
281 try:
return self.config.get[klass](key)
282 except Exception:
pass
284 if default
is None:
raise KeyError(key)
285 return klass(default)
290 Returns whether there is a value associated with the specified key.
296 the key of the configuration parameter to be read
299 return self.config.has(klass)
304 def pset(self):
return self.config
310 with warnings.catch_warnings():
312 warnings.filterwarnings(
"ignore",
".*tempnam .*", RuntimeWarning)
316 self._file.write(str(data))
321 if not self.
_file:
return
333 SourceCode.loadHeaderFromUPS(
"larcorealg/Geometry/StandaloneBasicSetup.h")
335 if isinstance(configSpec, ConfigurationString):
337 configPath = configFile.name
340 configPath = configSpec
345 raise RuntimeError(
"Couldn't find configuration file '%s'" % configPath)
346 return ROOT.lar.standalone.ParseConfiguration(fullPath)
351 """Wrapper to a string that should be considered configuration text."""
361 return self.config.get[ROOT.fhicl.ParameterSet](FHiCLpath)
363 return self.
paramsFor(
"services." + serviceName)
365 return self.
paramsFor(
"physics.producers." + moduleName)
376 def config(self, serviceName):
return self.fullConfig.service(serviceName)
378 def has(self, serviceName):
return serviceName
in self.services
381 self.
services[serviceName] = service
388 def get(self, serviceName):
return self.
services[serviceName]
391 def create(self, serviceName, serviceClass, *otherServiceConstructorArgs):
392 serviceConfig = self.
config(serviceName)
393 if not serviceConfig:
394 raise RuntimeError(
"Couldn't find the configuration for service '%s'" % serviceName)
395 service = serviceClass(serviceConfig, *otherServiceConstructorArgs)
397 raise RuntimeError(
"Failed to create service '%s' (type: %s)" % (serviceName, serviceClass.__class__.__name__))
398 return self.
register(serviceName, service)
406 """Use it as a function: `startMessageFacility(config, applName)`.
408 `config` either is `ConfigurationClass` object, or it is a parameter set
409 with the configuration for the service.
413 if not startMessageFacility.Init: self.
init(config, applName)
414 def init(self, config, applName):
415 if not applName: applName = os.path.basename(sys.argv[0])
416 if isinstance(config, ConfigurationClass): config = config.service(
"message")
417 print(
"Starting message facility for %s..." % applName)
418 ROOT.mf.StartMessageFacility(config, applName)
419 startMessageFacility.Init =
True
def findFHiCL
Infrastructure.
do one_file $F done echo for F in find $TOP name CMakeLists txt print
def registeredServiceNames
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
open(RACETRACK) or die("Could not open file $RACETRACK for writing")