13 from caf.framework
import Calibration, CentralDatabase, Collection, LocalDatabase
14 from caf
import strategies
25 def limit_file_events(calibration, collection_limits):
26 for colname, max_events
in collection_limits.items():
27 basf2.set_module_parameters(
28 calibration.collections[colname].pre_collector_path,
30 entrySequences=[f
'0:{max_events}'])
33 def collect(calibration, collection, input_files, output_file='CollectorOutput.root', basf2_args=None, bsub=False):
35 Standalone collection for calibration (without CAF)
38 Pickles the reprocessing path and collector of given collection and runs it in separate process
39 to collect calibration data in output_file from input_files.
43 calibration : caf.framework.Calibration
44 The configured Millepede calibration (see create(...)) to use for collection
46 Collection name which should be collected (which re-processing path and collector to use)
47 input_files : list(str)
48 List of input files for this collection job
50 Name of output collector file with data/histograms (produced by HistoManager)
52 Additional arguments to pass to basf2 job
54 if basf2_args
is None:
60 main = calibration.collections[collection].pre_collector_path
63 for m
in main.modules():
64 if m.name() ==
'RootInput':
65 m.param(
'inputFileNames', input_files)
66 tmp.add_module(
'HistoManager', histoFileName=output_file)
69 main.add_module(calibration.collections[collection].collector)
71 path_file_name = calibration.name +
'.' + collection +
'.' + output_file +
'.path'
72 with open(path_file_name,
'bw')
as serialized_path_file:
76 subprocess.call([
"bsub",
"-o", output_file +
".txt",
"basf2",
"--execute-path", path_file_name] + basf2_args)
78 subprocess.call([
"basf2",
"--execute-path", path_file_name] + basf2_args)
80 return os.path.abspath(output_file)
83 def calibrate(calibration, input_files=None, iteration=0):
85 Execute the algorithm from configured Millepede calibration over collected
86 files in input_files. The pre_algorithm function is run before the algorithm.
90 calibration : caf.framework.Calibration
91 Configured Millepede calibration (see create(...))
92 input_files : list(str)
93 List of input collected files
95 Iteration number to pass to pre_algorithm function
97 if input_files
is None:
98 input_files = [
'CollectorOutput.root']
100 Execute algorithm of the Millepede calibration over
102 for algo
in calibration.algorithms:
103 algo.algorithm.setInputFileNames(input_files)
104 algo.pre_algorithm(algo.algorithm, iteration)
105 algo.algorithm.execute()
106 algo.algorithm.commit()
109 def create_algorithm(dbobjects, min_entries=10, ignore_undetermined=True):
111 Create Belle2.MillepedeAlgorithm
115 dbobjects : list(str)
116 List of DB objects to calibrate - has to match collector settings
118 Minimum number of collected entries for calibration. Algorithm will return
119 NotEnoughData is less entries collected.
120 ignore_undetermined : bool
121 Whether undetermined parameters should be ignored or the calibration should fail if any
124 from ROOT.Belle2
import MillepedeAlgorithm
125 algorithm = MillepedeAlgorithm()
127 std_components = ROOT.vector(
'string')()
128 for component
in dbobjects:
129 std_components.push_back(component)
130 algorithm.setComponents(std_components)
132 algorithm.ignoreUndeterminedParams(ignore_undetermined)
133 algorithm.setMinEntries(min_entries)
135 algorithm.invertSign(
True)
140 def create_commands():
142 Create default list of commands for Pede
145 cmds.append(
'method inversion 3 0.1')
146 cmds.append(
'skipemptycons')
148 import multiprocessing
149 ncpus = multiprocessing.cpu_count()
151 cmds.append(f
'threads {ncpus} {ncpus}')
152 cmds.append(
'printcounts 2')
153 cmds.append(
'closeandreopen')
155 cmds.append(
'hugecut 50.')
156 cmds.append(
'chiscut 30. 6.')
157 cmds.append(
'outlierdownweighting 3')
158 cmds.append(
'dwfractioncut 0.1')
163 def create_collector(dbobjects, **argk):
165 Create MillepedeCollector module with default configuration
170 List of database objects to be calibrated (global derivatives of others
171 will be disabled) - has to match algorithm settings
173 Dictionary of additional module parameters (can override defaults)
177 MillepedeCollectorModule (configured)
180 m = basf2.register_module(
'MillepedeCollector')
182 m.param(
'granularity',
'all')
184 m.param(
'calibrateVertex',
True)
186 m.param(
'calibrateKinematics',
False)
187 m.param(
'minUsedCDCHitFraction', 0.8)
188 m.param(
'minPValue', 0.0)
189 m.param(
'externalIterations', 0)
190 m.param(
'tracks', [])
191 m.param(
'fitTrackT0',
True)
192 m.param(
'components', dbobjects)
193 m.param(
'useGblTree',
False)
194 m.param(
'absFilePaths',
True)
198 m.param(
'hierarchyType', 0)
218 Create the Millepede Calibration, fully configured in one call
225 dbobjects : list(str)
226 List of database objects to calibrate, e.g. ['BeamSpot', 'VXDAlignment']
227 Note that by default all parameters of the db object are free (exceptions
228 depend on some constraint and collector configuration) and you might need to fix
229 the unwanted ones (typically higher order sensor deformations) using the 'fixed' parameter.
231 collections : list(namedtuple('MillepedeCollection', ['name', 'files', 'path', 'params']))
232 List of collection definitions.
234 Collection name has to math entry in 'files' dictionary.
235 - files : list(str) | None
236 Optional list of files. Can (should if not set here) be overriden by 'files' parameter
238 The reprocessing path
239 - dict(...) : additional dictionary of parameters passed to the collector.
240 This has to contain the input data sample (tracks / particles / primaryVertices ...) configuration for the collector.
241 Optionally additional arguments can be specified for the collector specific for this collection.
242 (Default arguments for all collections can be set using the 'params' parameter)
243 Use make_collection(str, path=basf2.Path, **argk) for more convenient creation of custom collections.
244 For standard collections to use, see alignment.collections
246 files : dict( str -> list(str) )
247 Dictionary of lists of input file paths, key is collection name, value is list of input files.
248 NOTE: This overrides possible list of files assigned during creation of collections (if set)
250 List of input global tags. Can include absolute file paths to local databases (added to the chain).
252 timedep : list(tuple(list(int), list(tuple(int, int, int))))
253 Time-depence configuration.
254 Each list item is 2-tuple with list of parameter numbers (use alignment.parameters to get them) and
255 the (event, run, exp) numbers at which values of these parameters can change.
256 Use with caution. Namely the first event of the lowest run in input data has to be included in (some of the)
259 commands : list(str | tuple(str, None))
260 List of commands for Millepede. Default commands can be overriden be specifing different values for them.
261 A command can be erased completely from the default commands if instead a ('command_name', None) is passed.
262 constraints : list(alignment.Constraints)
263 List of constraints from alignment.constraints to be used.
264 Constraints are generated by the pre-algorithm function by CAF.
266 List of fixed parameters (use alignment.parameters to get them)
269 Dictionary of common parameters to set for collectors of all collections.
271 Minimum entries to required by the algorithm. Returns NotEnoughData if less entries is collected.
275 caf.framework.Calibration object, fully configured and ready to run.
276 You might want to set/override some options to custom values, like 'max_iterations' etc.
279 print(
"----------------------------")
280 print(
" Calibration: ", name,
"")
281 print(
"----------------------------")
283 print(
"- DB Objects:")
284 for objname
in dbobjects:
287 cmds = create_commands()
291 def set_command(command):
293 if isinstance(command, tuple):
294 if not len(command) == 2:
295 raise AttributeError(
"Commands has to be strings or tuple ('command name', None) to remove the command")
298 words = command.split(
" ")
305 _commands[cmd_name] = spec
306 elif cmd_name
in _commands:
307 del _commands[cmd_name]
318 algo = create_algorithm(dbobjects, min_entries=min_entries)
321 for cmd_name, cmd
in _commands.items():
323 algo.steering().command(cmd)
325 if constraints
is None:
328 print(
"- Constraints:")
331 algo.steering().command(
'FortranFiles')
333 print(
" ", const.filename)
334 algo.steering().command(const.filename)
339 def gen_constraints(algorithm, iteration):
343 data_iov = algorithm.getRunRangeFromAllData().getIntervalOfValidity()
344 init_event = (0, data_iov.getRunLow(), data_iov.getExperimentLow())
353 constraint_tags = [tag
for tag
in reversed(basf2.conditions.globaltags)]
356 generate_constraints(consts, timedep, constraint_tags, init_event)
358 algo.steering().command(
'Parameters')
362 algo.steering().command(
'{} 0.0 -1.'.format(str(label)))
367 print(
"- Fixed parameters:", len(fixed))
370 algo.setTimedepConfig(timedep)
374 def make_database_chain(tags):
378 if os.path.exists(tag):
379 print(
" Local:", os.path.abspath(tag))
380 chain.append(LocalDatabase(os.path.abspath(tag)))
382 print(
" Global:", tag)
383 chain.append(CentralDatabase(tag))
386 dbchain = make_database_chain(tags)
if tags
is not None else None
394 pre_collector_path=
None,
395 database_chain=dbchain,
396 output_patterns=
None,
403 print(
"- Overriden common collector parameters:")
404 for parname, parval
in params.items():
405 print(
" ", parname,
":", parval)
410 print(
"- Collections:")
411 for col
in collections:
420 filelist = files[colname]
422 print(f
" - {colname} ({len(filelist)} files)")
424 collector = create_collector(dbobjects)
425 if params
is not None:
426 collector.param(params)
429 const.configure_collector(collector)
431 collector.param(
'timedepConfig', timedep)
433 for argname, argval
in args.items():
434 print(
" ", argname,
" : ", argval)
436 collector.param(args)
439 input_files=filelist,
440 pre_collector_path=path,
441 database_chain=dbchain)
443 calibration.add_collection(colname, collection)
445 calibration.strategies = strategies.SingleIOV
446 calibration.max_iterations = 1
448 calibration.pre_algorithms = gen_constraints
450 print(
"----------------------------")