ATLAS Offline Software
Loading...
Searching...
No Matches
common.py
Go to the documentation of this file.
1# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2
3#
4# File: CaloClusterCorrection/python/common.py
5# Created: Nov 2006, sss
6# Purpose: Common utility code for configuring cluster corrections.
7#
8
9
10from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
11from AthenaConfiguration.ComponentFactory import CompFactory
12from AthenaCommon.Logging import logging
13from fnmatch import fnmatchcase
14
15from CaloClusterCorrection.poolfiles import poolfiles
16
17from CaloClusterCorrection.constants import \
18 CALOCORR_JO, CALOCORR_POOL, CALOCORR_COOL, \
19 CALOCORR_NOPOOL, CALOCORR_TOPOOL, CALOCORR_DEFAULT_KEY, \
20 sampnames
21
22# Used for reporting configuration errors.
23class CaloCorrectionConfigError (Exception):
24 pass
25
26# Keep track of pool files we're already seen.
27_poolfiles_seen = {}
28
29# Keep track of pool folders we've used.
30_folders_used = {}
31
32# Keep track of all tool names, to prevent duplicates.
33# The value is a (folder, tag, sgkey) tuple.
34_alltools = {}
35
36
37
38
120
121
122# Helper: Split up a version specifier SPEC.
123# Returns (FUNC, VERSION, ORDER, EXTRA_ARGS)
125 func = cspec[0]
126 version = ''
127 order = 0
128 ii = 1
129 if ii < len(cspec) and isinstance (cspec[ii], str):
130 version = cspec[ii]
131 ii += 1
132 if ii < len(cspec) and isinstance (cspec[ii], int):
133 order = cspec[ii]
134 ii += 1
135 extra_args = cspec[ii:]
136 return (func, version, order, extra_args)
137
138
139# Given a cool tag (or GLOBAL for the currently-configured global tag),
140# return the version of the correction set to use.
141def _find_version_from_cool_tag (flags, coolTag, corrclass):
142 if coolTag == 'GLOBAL':
143 coolTag = flags.IOVDb.GlobalTag
144
145 if flags.Input.isMC:
146 folderset = "/CALO/Ofl/" + corrclass
147 connstring = 'COOLOFL_CALO/OFLP200'
148 else:
149 folderset = "/CALO/" + corrclass
150 connstring = 'COOLONL_CALO/' + flags.IOVDb.DatabaseInstance
151
152 from CoolConvUtilities import AtlCoolLib
153 db = AtlCoolLib.indirectOpen (connstring, readOnly=True)
154 ff = db.getFolderSet (folderset)
155 t = ff.resolveTag (coolTag)
156 # CaloOflSwClusterCorrections.00-02-12-calhits-v9
157 l = t.split ('-')
158 return '-'.join (l[4:])
159
160
162 # Must be overridden in derived classes. See above for their meaning.
163 # name = XXX
164 # version_override_flag_name = XXX
165 # correction_generation_flag_name = XXX
166 # correction_generation_default = XXX
167 # versions = XXX
168 # geom_versions = XXX
169 # newest_version = XXX
170
171 #
172 # Create and return a CA of correction tools.
173 # FLAGS is the configuration flags.
174 # CORRCLASS is the correction class string, as defined in constants.py.
175 # KEY is a string that specifies the correction type.
176 # SUFFIX is a string to add to the end of each tool name.
177 # VERSION specifies which version of corrections to use.
178 # VERSION may also be of the form `@TAG' to force a specific COOL tag TAG,
179 # or it may be `@GLOBAL' to use to globally-configured COOL tag.
180 # In such cases, if there's no direct match of the version string
181 # in the version table, we look for one with a version of `@'.
182 # If no match for that is found, the last entry in the table
183 # will be used.
184 # CORRLIST can be used to explicitly specify which corrections to run.
185 # CELLS_NAME is the SG key to use to find the calorimeter cells,
186 # for those corrections that require it.
187 # SOURCE specifies the source(s) from which tools are configured.
188 # None means to use the default.
189 #
191 flags,
192 corrclass,
193 key = None,
194 suffix = '',
195 version = None,
196 corrlist = None,
197 cells_name = None,
198 source = None,
199 **kw):
200
201 # Make a logger.
202 log = logging.getLogger ('CaloClusterCorrection')
203
204 tryhier = False
205
206 # First, find the appropriate overall version string to use,
207 # if it wasn't specified explicitly.
208 if version is None:
209 # First see if the flag was set to override the version.
210 # at the top-level.
211 v = getattr (flags.Calo.ClusterCorrection, self.version_override_flag_name)
212 if v:
213 version = v
214
215 if version is None:
216 # No explicitly specified version.
217 # Try to guess it from the data source + geometry string.
218 # Otherwise, use the latest version.
219 geom = flags.GeoModel.AtlasVersion
220 datasource = 'geant4' if flags.Input.isMC else 'data'
221 (version, tryhier) = self.geom_match (datasource, geom)
222
223 # Get the correction generation.
224 generation = self.get_generation(flags)
225
226 # Use the default source if one wasn't specified.
227 if source is None:
228 source = flags.Calo.ClusterCorrection.defaultSource
229
230 if not isinstance (source, list):
231 source = [source]
232 if CALOCORR_COOL not in source:
233 tryhier = False
234
235 if tryhier and version[0] != '@':
236 cl = corrclass
237 if flags.Input.isMC:
238 cl = cl[0:4] + 'Ofl' + cl[4:]
239 version = "@%s-%s%s" % (cl, generation, version)
240
241 # Only use COOL if we're actually trying to resolve a COOL tag.
242 # Otherwise we can run into problems: it looks like `ununsed'
243 # COOL tags are removed in DB replicas.
244 if version[0] != '@' and len(source) > 0:
245 if CALOCORR_COOL in source:
246 source.remove (CALOCORR_COOL)
247
248 (vcorrlist, version) = self.lookup_version (flags, version, corrclass)
249
250 # Default to the standard list if no explicit correction list.
251 if corrlist is None:
252 corrlist = vcorrlist
253
254 log.debug ("%s corrections for %s (%s) using version %s" %
255 (self.name, key, suffix, version))
256
257 # Now, walk through the list of corrections.
258 out = ComponentAccumulator()
259 tools = []
260 for cspec in corrlist:
261 (func, this_version, this_order, extra_args) = \
262 split_version_spec (cspec)
263
264 # If the version or extra args isn't specified here,
265 # look in the internal corrlist to see if we find it there.
266 if this_version == '' or extra_args == []:
267 for vcspec in vcorrlist:
268 if vcspec[0] == func:
269 (vfunc, vversion, vorder, vextra_args) = \
270 split_version_spec (vcspec)
271 if this_version == '':
272 this_version = vversion
273 if extra_args == []:
274 extra_args = vextra_args
275 if this_order == 0:
276 this_order = vorder
277 break
278
279 elif version[0] == '@' and not corrlist:
280 this_version = version #pragma: NO COVER
281
282 if this_version == '@':
283 this_version = version
284
285 # Start building the other variables to use in the call.
286 this_args = dict (extra_args)
287 this_key = key
288 this_suffix = suffix
289 this_cells_name = cells_name
290 this_source = source
291
292 corrname = func.__name__
293
294 # Look for any overriders in our keyword list.
295 for (k, v) in kw.items():
296 if k == corrname + '_suffix':
297 this_suffix = v
298 elif k == corrname + '_key':
299 this_key = v
300 elif k == corrname + '_cells_name':
301 this_cells_name = v
302 elif k == corrname + '_source':
303 this_source = v
304 elif k == corrname + '_version':
305 this_version = v
306 elif k == corrname + '_order':
307 this_order = v
308 elif k.startswith (corrname + '_'):
309 this_args[k[len(corrname)+1:]] = v
310
311 # Make the tool.
312 ca = func (flags,
313 this_cells_name,
314 this_suffix,
315 this_version,
316 this_key,
317 this_source,
318 generation = generation,
319 order = this_order,
320 **this_args)
321 tools.append (out.popToolsAndMerge (ca))
322
323 out.setPrivateTools (tools)
324 return out
325
326
327 # Look up a specific correction version; return the correction
328 # list and the version. Broken out to allow overriding, for
329 # any special version-name handling needed.
330 def lookup_version (self, flags, version, corrclass):
331 vcorrlist = self.versions.get (version)
332 if vcorrlist is None and version.startswith ('@'):
333 findvers = _find_version_from_cool_tag (flags, version[1:], corrclass)
334 vcorrlist = self.versions.get (findvers)
335 if vcorrlist is None:
336 vcorrlist = self.versions.get ('@')
337 if vcorrlist is None:
338 raise CaloCorrectionConfigError\
339 ("Can't find global correction version %s." % version)
340 return (vcorrlist, version)
341
342
343 # Match a data source + geometry string against geom_versions.
344 def _geom_match1 (self, geom):
345 for (pat, v) in self.geom_versions:
346 if fnmatchcase (geom, pat):
347 return v
348 return None
349 def geom_match (self, datasource, geom):
350 if not geom: geom = ''
351 vv = self._geom_match1 (datasource + '-' + geom)
352 if not vv:
353 vv = self._geom_match1 (geom)
354 if not vv:
355 vv = self.newest_version
356 tryhier = True
357 if vv.startswith ('NOHIER#'):
358 tryhier = False
359 vv = vv[7:]
360 return (vv, tryhier)
361
362
363 # Get the correction generation, with a `-' appended if appropriate.
364 @classmethod
365 def get_generation (cls, flags):
366 generation = cls.correction_generation_default
367 gen2 = getattr (flags.Calo.ClusterCorrection, cls.correction_generation_flag_name)
368 if gen2:
369 generation = gen2
370 if generation != '':
371 generation = generation + '-'
372 return generation
373
374
375
378
379 def make_ForPool (self, flags, keys, corrclass):
380 # Map from SG key to a list of tool instances.
381 sgkeys = {}
382
383 # Names of all tools made so far
384 tool_names = set()
385
386 # Map from (func, version) to (order, globversion).
387 # For consistency checking.
388 ordermap = {}
389
390 result = ComponentAccumulator()
391 tools = []
392
393 # Go through each version, and make corrections.
394 for (v,l) in self.versions.items():
395 if v.startswith ('@'): continue
396 last_order = 0
397 last_funcname = '(none)'
398 for c in l:
399 # Consistency check: tool lists should be sorted in order.
400 (func, version, order, extra_args) = split_version_spec (c)
401 if order <= last_order:
402 raise CaloCorrectionConfigError\
403 ("Tools for global version %s are not in order!"
404 " %d(%s) < %d(%s)" % (v, order, func.__name__,
405 last_order, last_funcname))
406 last_order = order
407 last_funcname = func.__name__
408
409 # Consistency check: a given tool func/version should
410 # always have the same order setting.
411 okey = (func, version)
412 if okey not in ordermap:
413 ordermap[okey] = (order, v)
414 elif ordermap[okey][0] != order:
415 raise CaloCorrectionConfigError\
416 ("Tool %s has order %d in %s but order %d in %s!" %
417 (func.__name__, order, v,
418 ordermap[okey][0], ordermap[okey][1]))
419
420 # Find the list of valid keys for this tool.
421 valid_keys = func (flags,
422 None,
423 version = version,
424 key = '@VALID_KEYS')
425 if valid_keys is None:
426 valid_keys = keys
427 for key in valid_keys:
428 ca = self.maybe_make_correction_for_pool (flags,
429 sgkeys,
430 tool_names,
431 key, c,
432 corrclass)
433 if ca:
434 tools.append (ca.popPrivateTools())
435 result.merge (ca)
436
437 result.setPrivateTools (tools)
438
439 return (sgkeys, result)
440
441
443 sgkeys, tool_names, key, cspec,
444 corrclass):
445 (func, version, order, extra_args) = split_version_spec (cspec)
446 name = func.__name__ + '_' + version + '_' + key
447 if name in tool_names:
448 return None
449 ca = func (flags,
450 None, '', version, key, CALOCORR_TOPOOL,
451 generation = self.get_generation (flags),
452 order = order)
453 if ca is None:
454 return None
455 tool = ca.popPrivateTools()
456 if tool is not None and folder(tool).find ('/' + corrclass + '/') >= 0:
457 tool_names.add (name)
458 sgkeys.setdefault (sgkey(tool), []).append (tool)
459 ca.setPrivateTools (tool)
460 return ca
461
462
463 # Add a dummy correction object to each folder.
464 def add_dummies (self, sgkeys, valid_keys, generation):
465 CaloDummyCorrection = CompFactory.CaloDummyCorrection # CaloClusterCorrection
466 toolnames = {}
467 for sgkey in sgkeys.keys():
468 ll = sgkey.split ('-')
469 if len(ll) == 1:
470 name = ll[0]
471 else:
472 (name, ver) = ll
473 toolnames[name] = 1
474 for name in toolnames.keys():
475 (corrclass, basename) = name.split ('.')
476 sgkey = name + '-dummy'
477 tagname = "%s.%s%s-dummy" % (corrclass, generation, basename)
478 folder = '/CALO/%s/%s' % (corrclass, basename)
479 sgkeys[sgkey] = []
480 for key in valid_keys:
481 toolname = basename + key + '-dummy'
482 tool = CaloDummyCorrection (toolname)
483 tool.prefix = key + '.'
484 sgkeys[sgkey].append (tool)
485 _alltools[toolname] = (folder, tagname, sgkey)
486 return
487
488
489 # Configure algorithms for writing to pool.
490 def config_for_pool (self, flags, keys, corrclass):
491 result = ComponentAccumulator()
492
493 corr_output_list = []
494 tag_list = []
495
496 generation = self.get_generation (flags)
497
498 (sgkeys, ca) = self.make_ForPool (flags, keys, corrclass)
499 ca.popPrivateTools()
500 result.merge (ca)
501 self.add_dummies (sgkeys, keys, generation)
502
503 for (sgkey, tools) in sgkeys.items():
504 if len (tools) == 0: continue
505 name = 'write_' + sgkey
506 name = name.replace ('.', '_')
507
508 # In CaloRec
509 alg = CompFactory.CaloClusterCorrDBWriter (name,
510 key = sgkey,
511 ClusterCorrectionTools = tools)
512 result.addEventAlgo (alg)
513
514
515 corr_output_list.append ('CaloRec::ToolConstants#' +
516 sgkey + '#' +
517 folder (tools[0]))
518 tag_list.append (tag (tools[0]))
519
520 print ("Final OutputList:")
521 print (corr_output_list)
522 print (tag_list)
523
524 return (corr_output_list, tag_list, result)
525
526
527
528
529#
530# Create a correction tool.
531# FLAGS is the corrections flag object.
532# VERSIONS is a table listing all the available versions of the corrections.
533# It is a list of 4-element lists. The last row should correspond to the
534# most recent version of the correction.
535# The first column is the version name.
536# The second column is the Configurable class for the class which implements
537# the correction. This may also be a dictionary, to be indexed by
538# a calorimeter sampling.
539# The third column is a list containing the possible sources for this tool.
540# This list may contain any of the following:
541#
542# - A string giving the name of the parameter class used to initialize
543# the correction tool via job options. It should be of the form
544# `MODULE.CLASS'. If MODULE has no dots, we look for it in
545# CaloClusterCorrection.
546#
547# - A string defined in poolfiles, giving the name of a pool file
548# that contains this correction.
549#
550# - The string CALOCORR_COOL, indicating that this correction is available
551# in COOL.
552#
553# - The string CALOCORR_NOPOOL, indicating that this tool is not
554# to be written to pool/cool (always gets initialized via job options).
555#
556# In the case of reading from job options, we look up the specified name.
557# If this is a dictionary, we look up the requested sampling in the dictionary.
558# We should then have a class; the names in this class are the parameter
559# settings to make. If any of them are dictionaries, then we look up the key
560# in the dictionary.
561#
562# In the case of reading from cool, we construct folder and tag names
563# with the following formats:
564#
565# /CALO/<class>/<basename>
566# <class>.<basename>-<version>
567#
568# and a prefix in the format:
569#
570# <key><sampling>.
571#
572# If we've already read a different version of this correction from
573# the folder, then the read from cool fails (but we can fall back
574# on a direct pool read or initialization from job options).
575# Otherwise, we arrange to read this object; the StoreGate key
576# will be the same as the folder name.
577#
578# In the case of reading from pool, the StoreGate key will be the same
579# as the tag name we formed above.
580#
581# The fourth column is a list of cluster type keys that are valid for
582# this correction. When reading from pool, if the key we're given doesn't
583# match one on this list, we replace it with the longest match (first
584# one wins on ties) from this list. Set this to None or omit it
585# to skip this.
586#
587# NAME is the base name for this tool, excluding the suffix. If set to None,
588# a name will be constructed from the name of the correction, the version,
589# the key, and the sampling (if applicable).
590#
591# BASENAME is the base name for the correction: a string like `gap',
592# `etaoff', etc.
593#
594# If SUFFIX is not None, it will be added onto the end of the tool name.
595#
596# VERSION is a string specifying which of several versions of the correction
597# to choose. If set to None, the latest version of the correction is chosen.
598# VERSION may also be of the form `@TAG' to force a specific COOL tag TAG,
599# or it may be `@GLOBAL' to use to globally-configured COOL tag.
600# In such cases, if there's no direct match of the version string
601# in the version table, we look for one with a version of `@'.
602# If no match for that is found, the last entry in the table
603# will be used.
604#
605# KEY is a string to specify the type of cluster to which the correction
606# applies. The convention is to use `ele55' for 5x5 electron clusters,
607# `gam35' for 3x5 photon clusters, and so on.
608# If KEY is the special string `@VALID_KEYS', then we do not create
609# a tool. Instead, we return the list of keys that are declared
610# to be valid for this tool (or None, if none were).
611#
612# Some corrections have different tools for different calorimeter samplings.
613# If this is the case for this correction, SAMPLING should be set to the
614# applicable sampling. Otherwise, set it to None.
615#
616# SOURCE tells from where we should read the calibration constants.
617# CALOCORR_JO means to read the constants from job options.
618# Look in the correction's source list to find the parameter class.
619# CALOCORR_POOL means to read the constants from a pool file.
620# Look in the correction's source list to find the pool file.
621# CALOCORR_COOL means to read from cool.
622# A string of the form `MODULE.NAME' means to use this name
623# as the parameter class.
624# A string that's present in the poolfiles dictionary means to read
625# from this pool file.
626#
627# SOURCE may also be a list of these, to try in order.
628#
629# SOURCE may also be CALOCORR_TOPOOL, meaning to construct a tool
630# from job options appropriate for writing to a pool file.
631#
632# CONFCLASS gives the Configurable class to use to create the tool.
633# If set to None, this is taken from the version table.
634#
635# CORRCLASS is the correction class string, as defined above.
636#
637# GENERATION is the generation string to embed in COOL tags.
638#
639# ORDER specifies the relative order in which this tool should be executed.
640#
641# Additional keyword arguments may be passed to override any tool
642# parameters/constants.
643#
644def makecorr (flags,
645 versions,
646 name,
647 basename,
648 suffix,
649 version,
650 key,
651 sampling,
652 source,
653 confclass,
654 corrclass,
655 generation = '',
656 order = 0,
657 **kw):
658
659 # If no version specified, use the last one in the table.
660 if version is None:
661 version = versions[-1][0]
662
663 # Try to find the requested version.
664 for v in versions:
665 if v[0] == version:
666 break
667 else:
668 if version.startswith ('@'):
669 # A COOL tag is requested.
670 # Look for a table entry of `@'; otherwise, use the last entry.
671 for v in versions:
672 if v[0] == '@':
673 break
674 else:
675 v = versions[-1]
676 else:
677 raise CaloCorrectionConfigError \
678 ("Can't find version `%s' for correction named `%s'." %
679 (version, basename))
680
681 # The valid keys.
682 valid_keys = None
683 if len (v) >= 4:
684 valid_keys = v[3]
685
686 # Handle @VALID_KEYS request.
687 if key == '@VALID_KEYS':
688 return valid_keys
689
690 # Use the default source if one wasn't specified.
691 if source is None:
692 source = flags.Calo.ClusterCorrection.defaultSource
693
694 # Test to see if this correction specifies nopool.
695 nopool = CALOCORR_NOPOOL in v[2]
696
697 # Don't try to write a nopool tool to pool.
698 if nopool and source == CALOCORR_TOPOOL:
699 return None
700
701 # Find the SG key and cool tag.
702 if version.startswith ('@'):
703 sgkey = None
704 if version == '@GLOBAL':
705 fulltag = version
706 else:
707 fulltag = version[1:]
708
709 if not nopool:
710 # Must read from cool in this case.
711 source = CALOCORR_COOL
712 else:
713 # Construct the SG key name.
714 tmp = basename
715 if version != '':
716 tmp = tmp + "-" + version
717 sgkey = "%s.%s" % (corrclass, tmp)
718 fulltag = "%s.%s%s" % (corrclass, generation, tmp)
719 if flags.Input.isMC:
720 fulltag = fulltag[0:4] + 'Ofl' + fulltag[4:]
721
722 # The cool folder name.
723 if not flags.Input.isMC:
724 folder = "/CALO/%s/%s" % (corrclass, basename)
725 else:
726 folder = "/CALO/Ofl/%s/%s" % (corrclass, basename)
727
728 # Prefix to locate constants in the ToolConstants block.
729 prefix = key + sampnames[sampling] + "."
730
731 # Construct a default tool name if one isn't specified.
732 if name is None:
733 name = basename
734 name = name + sampnames[sampling]
735 if version != '':
736 vv = version
737 if vv[0] == '@':
738 vv = vv[1:]
739 vv = vv.split('-')[-1]
740 name = name + "_" + vv
741 if key != '':
742 name = name + "_" + key
743
744 # Add a suffix if given.
745 if suffix is not None:
746 name = name + suffix
747
748 # If this tool was defined earlier, check consistency.
749 if name in _alltools:
750 if _alltools[name] != (folder, fulltag, sgkey):
751 raise CaloCorrectionConfigError ( #pragma: NO COVER
752 "Inconsistent configuration of tool %s. Old (folder,tag,sgkey)=%s; new=%s" % #pragma: NO COVER
753 (name, _alltools[name], (folder, fulltag, sgkey))) #pragma: NO COVER
754 else:
755 _alltools[name] = (folder, fulltag, sgkey)
756
757 # If no class was explicitly specified, take it from the table.
758 if confclass is None:
759 confclass = v[1]
760
761 # It may be sampling-dependent.
762 if isinstance (confclass, dict) and sampling is not None:
763 confclass = confclass[sampling]
764
765 result = ComponentAccumulator()
766
767 # Create the tool!
768 corr = confclass (name)
769
770 # Set the prefix for all pool-capable tools.
771 if not nopool:
772 corr.prefix = prefix
773
774 # Try to find a source from which to configure it.
775 if not isinstance (source, list):
776 source = [source]
777 avail = v[2]
778 wherefrom = None
779 for s in source:
780 if s == CALOCORR_JO or s == CALOCORR_TOPOOL:
781 sel = [x for x in avail if _is_jo_source (x)]
782 if len (sel) > 0 and _config_from_jo(corr, sel[0], key,
783 sampling , valid_keys,
784 order):
785 wherefrom = sel[0]
786 break
787
788 elif s == CALOCORR_POOL:
789 sel = [x for x in avail if _is_pool_source (x)]
790 if len (sel) > 0:
791 ca2 = _config_from_pool (flags, corr, sel[0], sgkey)
792 if ca2:
793 result.merge (ca2)
794 _mung_prefix (corr, key, valid_keys)
795 wherefrom = sel[0]
796 break
797
798 elif s == CALOCORR_COOL:
799 sel = [x for x in avail if _is_cool_source (x)]
800 if len (sel) > 0:
801 ca2 = _config_from_cool (flags, corr, folder, fulltag)
802 if ca2:
803 result.merge (ca2)
804 _mung_prefix (corr, key, valid_keys)
805 wherefrom = 'cool'
806 break
807
808 elif _is_jo_source (s):
809 if _config_from_jo (corr, s, key, sampling, valid_keys, order):
810 wherefrom = s
811 break
812
813 elif _is_pool_source (s):
814 ca2 = _config_from_pool (flags, corr, s, sgkey)
815 if ca2:
816 result.merge (ca2)
817 _mung_prefix (corr, key, valid_keys)
818 wherefrom = s
819 break
820
821 if wherefrom is None:
822 raise CaloCorrectionConfigError \
823 ("Can't find any source to configure tool `%s'. Sources: %s" %
824 (name, source))
825
826 log = logging.getLogger ('CaloClusterCorrection')
827 log.debug (" correction %s (%s, from %s)" % (name, confclass.__name__,
828 wherefrom))
829
830 # If any other keyword arguments were passed, make those assignments.
831 # This will override anything otherwise read from JO/pool.
832 for (k, val) in kw.items():
833 if val is not None:
834 setattr (corr, k, val)
835
836 # Done!
837 result.setPrivateTools (corr)
838 return result
839
840
841# Test to see if S looks like a job options source.
843 if s == CALOCORR_COOL: return 0
844 if s == CALOCORR_POOL: return 0
845 if s in poolfiles: return 0
846 if s.find ('.') > 0: return 1
847 return 0
848
849
850# Test to see if S looks like a pool source.
852 return s in poolfiles
853
854
855# Test to see if S looks like a cool source.
857 return s == CALOCORR_COOL
858
859
860# Configure a correction tool from job options.
861def _config_from_jo (corr, jo, key, sampling, valid_keys, order):
862 # Split off the last dotted field as paramclass.
863 xjo = jo.split ('.')
864 paramclass = xjo[-1]
865 modname = '.'.join (xjo[:-1])
866
867 # If not otherwise specified, try to find the module
868 # in CaloClusterCorrection.
869 if modname.find ('.') < 0:
870 modname = 'CaloClusterCorrection.' + modname
871
872 # Import the module and look up the class.
873 mod = __import__ (modname, globals(), locals(), [paramclass])
874 parms = getattr (mod, paramclass)
875
876 # It may be sampling-dependent.
877 if isinstance (parms, dict) and sampling is not None:
878 parms = parms[sampling]
879
880 if order != 0 and hasattr (corr, 'order'):
881 corr.order = order
882 if hasattr (corr, 'isDummy'):
883 corr.isDummy = 0
884
885 log = logging.getLogger ('CaloClusterCorrection')
886
887 # Go through the names in the class and assign them to the tool.
888 for (k, val) in parms.__dict__.items():
889 # Skip internal names.
890 if k[0] != '_':
891 try:
892 # First try looking up the key.
893 # Note: don't test on val's type here --- it may
894 # be an object instance that implements __getitem__.
895 # We have to try the lookup and catch the error.
896 val = val[key]
897 except KeyError:
898 # We can do a lookup, but didn't find the key.
899 # Use the default key instead.
900 default_keys = parms.__dict__.get ('_default_keys')
901 if default_keys:
902 defkey = _longest_match (key, default_keys)
903 elif valid_keys:
904 defkey = _longest_match (key, valid_keys)
905 else:
906 defkey = CALOCORR_DEFAULT_KEY
907 val = val[defkey]
908
909 log.debug (" correction %s from JO using %s instead of %s" %
910 (corr.getName(), defkey, key))
911
912 except TypeError:
913 # Can't look up a key in val --- just use val as-is.
914 pass
915
916 setattr (corr, k, val)
917 return True
918
919
920# Configure a correction tool from POOL.
921def _config_from_pool (flags, corr, poolfile, sgkey):
922 if not poolfile or not poolfiles[poolfile]:
923 return False
924
925 ca = ComponentAccumulator()
926
927 # If this is the first time we've seen this file,
928 # add it to CondProxyProvider.
929 if poolfile not in _poolfiles_seen:
930 from EventSelectorAthenaPool.CondProxyProviderConfig import CondProxyProviderCfg
931 ca.merge (CondProxyProviderCfg (flags, [poolfiles[poolfile]]))
932
933 # Tell the tool to look in pool for this key.
934 corr.DBHandleKey = sgkey
935
936 # Set up a conditions algorithm to convert from the data in DetectorStore
937 # to a conditions object.
938 ToolConstantsCondAlg = CompFactory.ToolConstantsCondAlg # CaloRec
939
940 name = 'ToolConstantsCondAlg_' + sgkey.replace ('.', '_')
941 alg = ToolConstantsCondAlg (name,
942 DetStoreKey = sgkey,
943 ToolConstantsKey = sgkey)
944 ca.addCondAlgo (alg)
945 return ca
946
947
948# Configure a correction tool from COOL.
949def _config_from_cool (flags, corr, folder, tag):
950 # Folder name has form /CALO/CORRCLASS/NAME
951 # Find the subdetector name string to use.
952 fsplit = folder.split ('/')
953 if fsplit[2] == 'Ofl':
954 corrclass = folder.split ('/')[4]
955 else:
956 corrclass = folder.split ('/')[3]
957 sndict = flags.Calo.ClusterCorrection.dbSubdetName
958 subdetname = sndict.get (corrclass)
959 if not subdetname:
960 subdetname = sndict.get (None)
961
962 corr.DBHandleKey = folder
963
964 # We can't use more than one tag from a folder.
965 oldtag = _folders_used.get (folder)
966 if oldtag is not None and oldtag != tag:
967 return False
968
969 ca = ComponentAccumulator()
970
971 _folders_used[folder] = tag
972 if oldtag is None:
973 from IOVDbSvc.IOVDbSvcConfig import addFolders
974 tagstr = '' if tag =='@GLOBAL' else tag
975 sdsuffix = '_OFL' if 'Ofl' in folder else ''
976 ca.merge (addFolders (flags,
977 folder,
978 detDb = subdetname + sdsuffix,
979 className = 'CaloRec::ToolConstants',
980 tag = tagstr))
981
982 log = logging.getLogger ('CaloClusterCorrection')
983 log.debug ("Adding cool folder `%s' for subdetector name %s" %
984 (folder, subdetname))
985 return ca
986
987
988# When we're reading from pool/cool, the prefix _must_ be one that
989# exists in the file. Here, we see if the key is on the list of known
990# keys. If not, then we substitute.
991def _matchlen (a, b):
992 i = 0
993 while i < len(a) and i < len(b) and a[i] == b[i]:
994 i = i+1
995 return i
996def _longest_match (key, valid_keys):
997 if not isinstance (valid_keys, list):
998 valid_keys = [valid_keys]
999 if valid_keys is None or key in valid_keys:
1000 return key
1001 new_key = valid_keys[0]
1002 for k in valid_keys[1:]:
1003 if _matchlen (key, k) > _matchlen (key, new_key):
1004 new_key = k
1005 return new_key
1006def _mung_prefix (corr, key, valid_keys):
1007 if valid_keys is None or key in valid_keys: return
1008
1009 # Find the best match.
1010 new_key = _longest_match (key, valid_keys)
1011
1012 new_prefix = new_key + corr.prefix[len(key):]
1013 corr.prefix = new_prefix
1014 return
1015
1016# Return the folder for a tool.
1017def folder (tool):
1018 return _alltools[tool.getName()][0]
1019
1020
1021# Return the tag for a tool.
1022def tag (tool):
1023 return _alltools[tool.getName()][1]
1024
1025
1026# Return the SG key for a tool.
1027def sgkey (tool):
1028 return _alltools[tool.getName()][2]
1029
1030
1031
make_corrections(self, flags, corrclass, key=None, suffix='', version=None, corrlist=None, cells_name=None, source=None, **kw)
Definition common.py:199
get_generation(cls, flags)
Definition common.py:365
make_ForPool(self, flags, keys, corrclass)
Code for writing to pool.
Definition common.py:379
geom_match(self, datasource, geom)
Definition common.py:349
maybe_make_correction_for_pool(self, flags, sgkeys, tool_names, key, cspec, corrclass)
Definition common.py:444
config_for_pool(self, flags, keys, corrclass)
Definition common.py:490
lookup_version(self, flags, version, corrclass)
Definition common.py:330
add_dummies(self, sgkeys, valid_keys, generation)
Definition common.py:464
STL class.
tag(tool)
Definition common.py:1022
sgkey(tool)
Definition common.py:1027
_longest_match(key, valid_keys)
Definition common.py:996
_matchlen(a, b)
Definition common.py:991
_config_from_jo(corr, jo, key, sampling, valid_keys, order)
Definition common.py:861
_config_from_pool(flags, corr, poolfile, sgkey)
Definition common.py:921
_find_version_from_cool_tag(flags, coolTag, corrclass)
Definition common.py:141
_is_jo_source(s)
Definition common.py:842
_config_from_cool(flags, corr, folder, tag)
Definition common.py:949
folder(tool)
Definition common.py:1017
_is_cool_source(s)
Definition common.py:856
makecorr(flags, versions, name, basename, suffix, version, key, sampling, source, confclass, corrclass, generation='', order=0, **kw)
Definition common.py:657
split_version_spec(cspec)
Code to handle creating the list of correction tools.
Definition common.py:124
_is_pool_source(s)
Definition common.py:851
_mung_prefix(corr, key, valid_keys)
Definition common.py:1006