3 from __future__
import print_function
6 Collection of utilities to interface LArSoft with python and gallery.
8 This module requires ROOT.
14 'make_getValidHandle',
21 'startMessageFacility',
22 'ServiceRegistryClass',
23 'ConfigurationHelper',
31 from ROOTutils
import ROOT
33 from galleryUtils
import (
34 make_getValidHandle, makeFileList, forEach, eventLoop,
35 findFHiCL, loadConfiguration, ConfigurationHelper, ConfigurationClass,
36 startMessageFacility, ServiceRegistryClass,
43 SourceCode = galleryUtils.SourceCode
44 readHeader = galleryUtils.readHeader
50 def loadGeometry(config=None, registry=None, mapping=None):
51 """The argument `config` is an instance of `ConfigurationClass`.
53 If a config object is provided, configurations will be read from there.
54 Otherwise, they will be read from the registry.
55 If a registry is provided, the services will be registered in there.
57 assert(config
or registry)
58 serviceName =
'Geometry'
61 if not (registry
and registry.has(
"message")):
62 messageConfig = config.service(
"message")
if config
else registry.config(
"message")
63 startMessageFacility(messageConfig)
64 if registry: registry.register(
"message",
None)
67 geometryConfig = config.service(serviceName)
if config
else registry.config(serviceName)
68 if geometryConfig
is None:
69 raise RuntimeError(
"Failed to retrieve the configuration for %s service" % serviceName)
72 SourceCode.loadHeaderFromUPS(
'larcorealg/Geometry/ChannelMapStandardAlg.h')
73 mapping = ROOT.geo.ChannelMapStandardAlg
74 SourceCode.loadHeaderFromUPS(
"larcorealg/Geometry/StandaloneGeometrySetup.h")
75 SourceCode.loadLibrary(
"larcorealg_Geometry")
76 service = ROOT.lar.standalone.SetupGeometry[mapping](geometryConfig)
77 if registry: registry.register(serviceName, service)
80 for varName
in (
'Point_t',
'Vector_t', ):
81 try: klass = getattr(ROOT.geo, varName)
82 except AttributeError:
continue
83 klass.__str__ = ROOTutils.TVector3ToString
85 for varName
in (
'CryostatID',
'TPCID',
'PlaneID',
'WireID', ):
86 try: klass = getattr(ROOT.geo, varName)
87 except AttributeError:
continue
88 klass.__str__ = klass.toString
90 for varName
in (
'CryostatID',
'TPCsetID',
'ROPID', ):
91 try: klass = getattr(ROOT.readout, varName)
92 except AttributeError:
continue
93 klass.__str__ = klass.toString
96 for varName
in (
'CryostatGeo',
'TPCGeo',
'PlaneGeo',
'WireGeo',
'OpDetGeo',
'AuxDetGeo', ):
97 try: klass = getattr(ROOT.geo, varName)
98 except AttributeError:
continue
99 klass.__str__ = getattr(klass, varName[:-3] +
"Info")
108 """Loads and returns the geometry from the specified configuration file.
110 This is a one-stop procedure recommended only when running interactively.
112 return loadGeometry(config=ConfigurationClass(configFile), mapping=mapping)
118 (serviceClass, config=
None, registry=
None, interfaceClass=
None, args = []):
119 """Loads a service assuming some simple requirements:
120 * no dependency from other services
121 * constructor accepts a FHiCL parameter set
123 If a config object is provided, configurations will be read from there.
124 Otherwise, they will be read from the registry.
125 If a registry is provided, the services will be registered in there.
127 The service configuration is read from an item called as `interfaceClass`,
128 or `serviceClass` itself if `interfaceClass` is None, with "Service" appended.
130 As a first attempt, the test helpers are attempted to load the service, and
131 the arguments are used to construct a `providers_type` object.
132 If there is no test helper for `serviceClass`, then direct construction is
133 attempted using all the specified arguments.
136 serviceName = (interfaceClass
if interfaceClass
else serviceClass).__name__
137 configKey = serviceName +
"Service"
139 if not isinstance(config, ROOT.fhicl.ParameterSet):
140 config = config.service(configKey)
if config
else registry.config(configKey)
142 raise RuntimeError(
"Failed to retrieve the configuration for %s service" % serviceName)
144 TestSetupClass = ROOT.testing.ProviderSetupClass(serviceClass)
146 serviceSetup = TestSetupClass.setup
147 try: providers = [ serviceClass.providers_type(*args), ]
152 service = serviceSetup(config, *providers)
154 service = serviceClass(config, *args)
156 if registry: registry.register(serviceName, service)
170 class SimpleServiceLoader:
171 """Class storing the parameters needed to load a "simple" service.
173 So far a "simple" service is one that can be loaded with `loadSimpleService()`
174 allowing service provider dependencies and simple configuration adaptions.
178 interfaceClass =
None,
185 assert serviceClass
is not None
200 config = registry.config(configKey)
202 except Exception:
pass
209 for key, value
in self.addConfig.items(): config.put(key, str(value))
215 if not isinstance(source, str): source = source.__name__
216 return source.replace(
'::',
'.').split(
'.')[-1]
227 galleryUtils.SourceCode.loadHeaderFromUPS(header)
229 galleryUtils.SourceCode.loadLibrary(library)
237 registry = manager.registry()
250 classOrName = getattr(self, attrName)
251 if isinstance(classOrName, str):
253 setattr(self, attrName, classOrName)
265 def load(self, manager):
return loadGeometry(registry=manager.registry())
270 return self.
load(manager)
280 """The interface of a service manager implementation."""
283 """Returns the service registry."""
284 return NotImplementedError
288 """Returns the service registry."""
289 return NotImplementedError
294 """Returns a list names of service already loaded."""
295 return self.
registry().registeredServiceNames()
300 """Returns a list names of services known to be supported."""
306 """Registers a service provider loader, that can then be invoked to create
309 self.
loaders()[serviceKey] = loader
314 def get(self, serviceName, interfaceClass = None):
315 """Return (and load first when needed) the specified service.
317 The service can be specified by name or by class.
318 In the former case, if the service is not already configured, an exception
321 return NotImplementedError
324 def __call__(self, serviceName, interfaceClass = None):
325 return self.
get(serviceName, interfaceClass=interfaceClass)
333 def __init__(self, config, loadingTable = {}, preload = []):
349 self.
registry().register(
"message",
None)
354 for serviceKey
in preload: self.
get(serviceKey)
363 def get(self, serviceKey, interfaceClass = None):
364 """Return the specified service.
366 The service can be specified by name or by class.
367 In the former case, if the service is not already configured, an exception
369 If the service is specified by class instead, an attempt is made to load it,
370 in which case `interfaceClass` is also passed to
371 `LArSoftUtils.loadSimpleService()`.
377 except KeyError:
pass
385 print(
"Loading service provider: '{}'".
format(serviceKey))
397 """A service manager with a lazy setup.
401 StandardLoadingTable = {
406 "detinfo::LArPropertiesStandard",
407 interfaceClass=
"detinfo::LArProperties",
408 headers =
'lardataalg/DetectorInfo/LArPropertiesStandardTestHelpers.h',
409 libraries =
'lardataalg_DetectorInfo',
413 "detinfo::DetectorClocksStandard",
414 interfaceClass=
"detinfo::DetectorClocks",
415 headers =
'lardataalg/DetectorInfo/DetectorClocksStandardTestHelpers.h',
416 libraries =
'lardataalg_DetectorInfo',
420 "detinfo::DetectorPropertiesStandard",
421 interfaceClass=
"detinfo::DetectorProperties",
422 headers =
'lardataalg/DetectorInfo/DetectorPropertiesStandardTestHelpers.h',
423 libraries =
'lardataalg_DetectorInfo',
424 dependencies = [
'Geometry',
'LArProperties' ],
430 class ConfigurationInfo:
431 __slots__ = [
'configPath',
'serviceTable' ]
432 def __init__(self, configPath = None, serviceTable = None):
436 def isValid(self):
return self.configPath
is not None
451 """Returns the service registry."""
452 return self.manager.registry()
456 """Registers a service provider loader, that can then be invoked to create
459 It returns the service manager.
461 return self.manager.registerLoader(serviceKey, loader)
465 def get(self, serviceKey, interfaceClass = None):
466 """Return (and load first when needed) the specified service.
468 The service can be specified by name or by class.
469 In the former case, if the service is not already configured, an exception
473 return self.
manager(serviceKey)
479 def setConfiguration(self, configFile, serviceTable =
None):
480 """Sets which configuration to use for setup.
482 If `serviceTable` is not `None`, a new configuration is created with the
483 service table as `serviceTable`, and `configPath` is included in that
484 configuration (presumably to define `serviceTable`).
486 If `serviceTable` is `None` instead, the configuration file in
487 `configPath` is included directly, and it is assumed that it already
488 properly defines a `services` table.
490 assert configFile
is not None
496 """Prepares for service provider access in python/Gallery."""
507 assert self.configuration.isValid()
509 if configurationInfo.fullConfig():
510 config = configurationInfo.configPath
513 '#include "{configPath}"'
515 '\nservices: @local::{serviceTable}'
518 configPath=configurationInfo.configPath,
519 serviceTable=configurationInfo.serviceTable
527 self.
manager = ServiceManagerClass \
528 (config, loadingTable=ServiceManagerInstance.StandardLoadingTable)
static std::string format(PyObject *obj, unsigned int pos, unsigned int indent, unsigned int maxlen, unsigned int depth)
do one_file $F done echo for F in find $TOP name CMakeLists txt print
def makeStringList
special known services