Belle II Software development
Calibration Class Reference
Inheritance diagram for Calibration:
CalibrationBase

Public Member Functions

 __init__ (self, name, collector=None, algorithms=None, input_files=None, pre_collector_path=None, database_chain=None, output_patterns=None, max_files_per_collector_job=None, max_collector_jobs=None, backend_args=None)
 
 add_collection (self, name, collection)
 
 is_valid (self)
 
 reset_database (self, apply_to_default_collection=True)
 
 use_central_database (self, global_tag, apply_to_default_collection=True)
 
 use_local_database (self, filename, directory="", apply_to_default_collection=True)
 
 collector (self)
 
 collector (self, collector)
 
 input_files (self)
 
 input_files (self, files)
 
 files_to_iovs (self)
 
 files_to_iovs (self, file_map)
 
 pre_collector_path (self)
 
 pre_collector_path (self, path)
 
 output_patterns (self)
 
 output_patterns (self, patterns)
 
 max_files_per_collector_job (self)
 
 max_files_per_collector_job (self, max_files)
 
 max_collector_jobs (self)
 
 max_collector_jobs (self, max_jobs)
 
 backend_args (self)
 
 backend_args (self, args)
 
 algorithms (self)
 
 algorithms (self, value)
 
 pre_algorithms (self)
 
 pre_algorithms (self, func)
 
 strategies (self)
 
 strategies (self, strategy)
 
 __repr__ (self)
 
 run (self)
 
 state (self)
 
 state (self, state)
 
 iteration (self)
 
 iteration (self, iteration)
 
 depends_on (self, calibration)
 
 dependencies_met (self)
 
 failed_dependencies (self)
 

Public Attributes

dict collections = {}
 Collections stored for this calibration.
 
 algorithms = algorithms
 Algorithm classes that will be run by this Calibration.
 
dict results = {}
 Output results of algorithms for each iteration.
 
 max_iterations = None
 Variable to define the maximum number of iterations for this calibration specifically.
 
 ignored_runs = None
 List of ExpRun that will be ignored by this Calibration.
 
 strategies = strategies.SingleIOV
 The strategy that the algorithm(s) will be run against.
 
list database_chain = database_chain
 The database chain that is applied to the algorithms.
 
 algorithms_runner = runners.SeqAlgorithmsRunner
 The class that runs all the algorithms in this Calibration using their assigned :py:class:caf.strategies.AlgorithmStrategy.
 
 backend = None
 The backend <backends.Backend> we'll use for our collector submission in this calibration.
 
int collector_full_update_interval = 30
 While checking if the collector is finished we don't bother wastefully checking every subjob's status.
 
int heartbeat = 3
 This calibration's sleep time before rechecking to see if it can move state.
 
 machine = None
 The caf.state_machines.CalibrationMachine that we will run to process this calibration start to finish.
 
str state = initial_state
 state
 
 name = name
 Name of calibration object.
 
list future_dependencies = []
 List of calibration objects that depend on this one.
 
list dependencies = []
 List of calibration objects, where each one is a dependency of this one.
 
 iov = None
 IoV which will be calibrated.
 
str output_database_dir = ""
 The directory where we'll store the local database payloads from this calibration.
 
bool save_payloads = True
 Marks this Calibration as one which has payloads that should be copied and uploaded.
 
list jobs_to_submit = []
 A simple list of jobs that this Calibration wants submitted at some point.
 

Static Public Attributes

list moves = ["submit_collector", "complete", "run_algorithms", "iterate", "fail_fully"]
 Allowed transitions that we will use to progress.
 
str alg_output_dir = "algorithm_output"
 Subdirectory name for algorithm output.
 
list checkpoint_states = ["init", "collector_completed", "completed"]
 Checkpoint states which we are allowed to restart from.
 
str default_collection_name = "default"
 Default collection name.
 
str end_state = "completed"
 The name of the successful completion state.
 
str fail_state = "failed"
 The name of the failure state.
 

Protected Member Functions

 _get_default_collection_attribute (self, attr)
 
 _set_default_collection_attribute (self, attr, value)
 
 _ (self, value)
 
 _ (self, values)
 
 _ (self, values)
 
 _poll_collector (self)
 
 _apply_calibration_defaults (self, defaults)
 

Protected Attributes

list _algorithms = []
 Internal calibration algorithms stored for this calibration.
 
 _db_path = None
 Location of a SQLite database that will save the state of the calibration so that it can be restarted from failure.
 

Detailed Description

Every Calibration object must have at least one collector at least one algorithm.
You have the option to add in your collector/algorithm by argument here, or add them
later by changing the properties.

If you plan to use multiple `Collection` objects I recommend that you only set the name here and add the Collections
separately via `add_collection()`.

Parameters:
    name (str): Name of this calibration. It should be unique for use in the `CAF`
Keyword Arguments:
    collector (str, `basf2.Module`): Should be set to a CalibrationCollectorModule() or a string with the module name.
    algorithms (list, ``ROOT.Belle2.CalibrationAlgorithm``): The algorithm(s) to use for this `Calibration`.
    input_files (str, list[str]): Input files for use by this Calibration. May contain wildcards usable by `glob.glob`

A Calibration won't be valid in the `CAF` until it has all of these four attributes set. For example:

>>> cal = Calibration('TestCalibration1')
>>> col1 = register_module('CaTest')
>>> cal.add_collection('TestColl', col1)

or equivalently

>>> cal = Calibration('TestCalibration1', 'CaTest')

If you want to run a basf2 :py:class:`path <basf2.Path>` before your collector module when running over data

>>> cal.pre_collector_path = my_basf2_path

You don't have to put a RootInput module in this pre-collection path, but you can if
you need some special parameters. If you want to process sroot files the you have to explicitly add
SeqRootInput to your pre-collection path.
The inputFileNames parameter of (Seq)RootInput will be set by the CAF automatically for you.


You can use optional arguments to pass in some/all during initialisation of the `Calibration` class

>>> cal = Calibration( 'TestCalibration1', 'CaTest', [alg1,alg2], ['/path/to/file.root'])

you can change the input file list later on, before running with `CAF`

>>> cal.input_files = ['path/to/*.root', 'other/path/to/file2.root']

If you have multiple collections from calling `add_collection()` then you should instead set the pre_collector_path,
input_files, database chain etc from there. See `Collection`.

Adding the CalibrationAlgorithm(s) is easy

>>> alg1 = TestAlgo()
>>> cal.algorithms = alg1

Or equivalently

>>> cal.algorithms = [alg1]

Or for multiple algorithms for one collector

>>> alg2 = TestAlgo()
>>> cal.algorithms = [alg1, alg2]

Note that when you set the algorithms, they are automatically wrapped and stored as a Python class
`Algorithm`. To access the C++ algorithm clas underneath directly do:

>>> cal.algorithms[i].algorithm

If you have a setup function that you want to run before each of the algorithms, set that with

>>> cal.pre_algorithms = my_function_object

If you want a different setup for each algorithm use a list with the same number of elements
as your algorithm list.

>>> cal.pre_algorithms = [my_function1, my_function2, ...]

You can also specify the dependencies of the calibration on others

>>> cal.depends_on(cal2)

By doing this, the `CAF` will respect the ordering of the calibrations and will pass the
calibration constants created by earlier completed calibrations to dependent ones.

Definition at line 444 of file framework.py.

Constructor & Destructor Documentation

◆ __init__()

__init__ ( self,
name,
collector = None,
algorithms = None,
input_files = None,
pre_collector_path = None,
database_chain = None,
output_patterns = None,
max_files_per_collector_job = None,
max_collector_jobs = None,
backend_args = None )
 

Definition at line 535 of file framework.py.

546 ):
547 """
548 """
549
550 self.collections = {}
551
552 self._algorithms = []
553
554 # Default collection added, will have None type and requires setting later via `self.collector`, or will take the
555 # CollectorModule/module name directly.
556 self.add_collection(self.default_collection_name,
557 Collection(collector,
558 input_files,
559 pre_collector_path,
560 database_chain,
561 output_patterns,
562 max_files_per_collector_job,
563 max_collector_jobs,
564 backend_args
565 ))
566
567 super().__init__(name, input_files)
568 if algorithms:
569
572 self.algorithms = algorithms
573
574 self.results = {}
575
577 self.max_iterations = None
578
582 self.ignored_runs = None
583 if self.algorithms:
584
587 self.strategies = strategies.SingleIOV
588 if database_chain:
589
591 self.database_chain = database_chain
592 else:
593 self.database_chain = []
594 # This database is already applied to the `Collection` automatically, so don't do it again
595 for tag in reversed(b2conditions.default_globaltags):
596 self.use_central_database(tag, apply_to_default_collection=False)
597
600 self.algorithms_runner = runners.SeqAlgorithmsRunner
601
603 self.backend = None
604
608 self.collector_full_update_interval = 30
609
610 self.heartbeat = 3
611
612 self.machine = None
613
614 self._db_path = None
615

Member Function Documentation

◆ _() [1/3]

_ ( self,
value )
protected
Alternate algorithms setter for lists and tuples of CalibrationAlgorithms.

Definition at line 920 of file framework.py.

920 def _(self, value):
921 """
922 Alternate algorithms setter for lists and tuples of CalibrationAlgorithms.
923 """
924 from ROOT import Belle2 # noqa: make the Belle2 namespace available
925 from ROOT.Belle2 import CalibrationAlgorithm
926 if value:
927 self._algorithms = []
928 for alg in value:
929 if isinstance(alg, CalibrationAlgorithm):
930 self._algorithms.append(Algorithm(alg))
931 else:
932 B2ERROR(f"Something other than CalibrationAlgorithm instance passed in {type(value)}."
933 "Algorithm needs to inherit from Belle2::CalibrationAlgorithm")
934

◆ _() [2/3]

_ ( self,
values )
protected
Alternate pre_algorithms setter for lists and tuples of functions, should be one per algorithm.

Definition at line 955 of file framework.py.

955 def _(self, values):
956 """
957 Alternate pre_algorithms setter for lists and tuples of functions, should be one per algorithm.
958 """
959 if values:
960 if len(values) == len(self.algorithms):
961 for func, alg in zip(values, self.algorithms):
962 alg.pre_algorithm = func
963 else:
964 B2ERROR("Number of functions and number of algorithms doesn't match.")
965 else:
966 B2ERROR("Empty container passed in for pre_algorithm functions")
967

◆ _() [3/3]

_ ( self,
values )
protected
Alternate strategies setter for lists and tuples of functions, should be one per algorithm.

Definition at line 988 of file framework.py.

988 def _(self, values):
989 """
990 Alternate strategies setter for lists and tuples of functions, should be one per algorithm.
991 """
992 if values:
993 if len(values) == len(self.algorithms):
994 for strategy, alg in zip(strategies, self.algorithms):
995 alg.strategy = strategy
996 else:
997 B2ERROR("Number of strategies and number of algorithms doesn't match.")
998 else:
999 B2ERROR("Empty container passed in for strategies list")
1000

◆ __repr__()

__repr__ ( self)
 

Definition at line 1001 of file framework.py.

1001 def __repr__(self):
1002 """
1003 """
1004 return self.name
1005

◆ _apply_calibration_defaults()

_apply_calibration_defaults ( self,
defaults )
protectedinherited
We pass in default calibration options from the `CAF` instance here if called.
Won't overwrite any options already set.

Definition at line 431 of file framework.py.

431 def _apply_calibration_defaults(self, defaults):
432 """
433 We pass in default calibration options from the `CAF` instance here if called.
434 Won't overwrite any options already set.
435 """
436 for key, value in defaults.items():
437 try:
438 if getattr(self, key) is None:
439 setattr(self, key, value)
440 except AttributeError:
441 print(f"The calibration {self.name} does not support the attribute {key}.")
442
443

◆ _get_default_collection_attribute()

_get_default_collection_attribute ( self,
attr )
protected
 

Definition at line 771 of file framework.py.

771 def _get_default_collection_attribute(self, attr):
772 """
773 """
774 if self.default_collection_name in self.collections:
775 return getattr(self.collections[self.default_collection_name], attr)
776 else:
777 B2WARNING(f"You tried to get the attribute '{attr}' from the Calibration '{self.name}', "
778 "but the default collection doesn't exist."
779 f"You should use the cal.collections['CollectionName'].{attr} to access a custom "
780 "collection's attributes directly.")
781 return None
782

◆ _poll_collector()

_poll_collector ( self)
protected
 

Definition at line 1061 of file framework.py.

1061 def _poll_collector(self):
1062 """
1063 """
1064 while self.state == "running_collector":
1065 try:
1066 self.machine.complete()
1067 # ConditionError is thrown when the conditions for the transition have returned false, it's not serious.
1068 except ConditionError:
1069 try:
1070 B2DEBUG(29, f"Checking if collector jobs for calibration {self.name} have failed.")
1071 self.machine.fail()
1072 except ConditionError:
1073 pass
1074 sleep(self.heartbeat) # Sleep until we want to check again
1075

◆ _set_default_collection_attribute()

_set_default_collection_attribute ( self,
attr,
value )
protected
 

Definition at line 783 of file framework.py.

783 def _set_default_collection_attribute(self, attr, value):
784 """
785 """
786 if self.default_collection_name in self.collections:
787 setattr(self.collections[self.default_collection_name], attr, value)
788 else:
789 B2WARNING(f"You tried to set the attribute '{attr}' from the Calibration '{self.name}', "
790 "but the default collection doesn't exist."
791 f"You should use the cal.collections['CollectionName'].{attr} to access a custom "
792 "collection's attributes directly.")
793

◆ add_collection()

add_collection ( self,
name,
collection )
Parameters:
    name (str): Unique name of this `Collection` in the Calibration.
    collection (`Collection`): `Collection` object to use.

Adds a new `Collection` object to the `Calibration`. Any valid Collection will be used in the Calibration.
A default Collection is automatically added but isn't valid and won't run unless you have assigned a collector
+ input files.
You can ignore the default one and only add your own custom Collections. You can configure the default from the
Calibration(...) arguments or after creating the Calibration object via directly setting the cal.collector, cal.input_files
attributes.

Definition at line 616 of file framework.py.

616 def add_collection(self, name, collection):
617 """
618 Parameters:
619 name (str): Unique name of this `Collection` in the Calibration.
620 collection (`Collection`): `Collection` object to use.
621
622 Adds a new `Collection` object to the `Calibration`. Any valid Collection will be used in the Calibration.
623 A default Collection is automatically added but isn't valid and won't run unless you have assigned a collector
624 + input files.
625 You can ignore the default one and only add your own custom Collections. You can configure the default from the
626 Calibration(...) arguments or after creating the Calibration object via directly setting the cal.collector, cal.input_files
627 attributes.
628 """
629 if name not in self.collections:
630 self.collections[name] = collection
631 else:
632 B2WARNING(f"A Collection with the name '{name}' already exists in this Calibration. It has not been added."
633 "Please use another name.")
634

◆ algorithms() [1/2]

algorithms ( self)
 

Definition at line 900 of file framework.py.

900 def algorithms(self):
901 """
902 """
903 return self._algorithms
904

◆ algorithms() [2/2]

algorithms ( self,
value )
 

Definition at line 907 of file framework.py.

907 def algorithms(self, value):
908 """
909 """
910 from ROOT import Belle2 # noqa: make the Belle2 namespace available
911 from ROOT.Belle2 import CalibrationAlgorithm
912 if isinstance(value, CalibrationAlgorithm):
913 self._algorithms = [Algorithm(value)]
914 else:
915 B2ERROR(f"Something other than CalibrationAlgorithm instance passed in ({type(value)}). "
916 "Algorithm needs to inherit from Belle2::CalibrationAlgorithm")
917

◆ backend_args() [1/2]

backend_args ( self)
 

Definition at line 888 of file framework.py.

888 def backend_args(self):
889 """
890 """
891 return self._get_default_collection_attribute("backend_args")
892

◆ backend_args() [2/2]

backend_args ( self,
args )
 

Definition at line 894 of file framework.py.

894 def backend_args(self, args):
895 """
896 """
897 self._set_default_collection_attribute("backend_args", args)
898

◆ collector() [1/2]

collector ( self)
 

Definition at line 795 of file framework.py.

795 def collector(self):
796 """
797 """
798 return self._get_default_collection_attribute("collector")
799

◆ collector() [2/2]

collector ( self,
collector )
 

Definition at line 801 of file framework.py.

801 def collector(self, collector):
802 """
803 """
804 # check if collector is already a module or if we need to create one
805 # from the name
806 from basf2 import Module
807 if isinstance(collector, str):
808 from basf2 import register_module
809 collector = register_module(collector)
810 if not isinstance(collector, Module):
811 B2ERROR("Collector needs to be either a Module or the name of such a module")
812
813 self._set_default_collection_attribute("collector", collector)
814

◆ dependencies_met()

dependencies_met ( self)
inherited
Checks if all of the Calibrations that this one depends on have reached a successful end state.

Definition at line 415 of file framework.py.

415 def dependencies_met(self):
416 """
417 Checks if all of the Calibrations that this one depends on have reached a successful end state.
418 """
419 return all(map(lambda x: x.state == x.end_state, self.dependencies))
420
STL class.

◆ depends_on()

depends_on ( self,
calibration )
inherited
Parameters:
    calibration (`CalibrationBase`): The Calibration object which will produce constants that this one depends on.

Adds dependency of this calibration on another i.e. This calibration
will not run until the dependency has completed, and the constants produced
will be used via the database chain.

You can define multiple dependencies for a single calibration simply
by calling this multiple times. Be careful when adding the calibration into
the `CAF` not to add a circular/cyclic dependency. If you do the sort will return an
empty order and the `CAF` processing  will fail.

This function appends to the `CalibrationBase.dependencies` and `CalibrationBase.future_dependencies` attributes of this
`CalibrationBase` and the input one respectively. This prevents us having to do too much recalculation later on.

Definition at line 387 of file framework.py.

387 def depends_on(self, calibration):
388 """
389 Parameters:
390 calibration (`CalibrationBase`): The Calibration object which will produce constants that this one depends on.
391
392 Adds dependency of this calibration on another i.e. This calibration
393 will not run until the dependency has completed, and the constants produced
394 will be used via the database chain.
395
396 You can define multiple dependencies for a single calibration simply
397 by calling this multiple times. Be careful when adding the calibration into
398 the `CAF` not to add a circular/cyclic dependency. If you do the sort will return an
399 empty order and the `CAF` processing will fail.
400
401 This function appends to the `CalibrationBase.dependencies` and `CalibrationBase.future_dependencies` attributes of this
402 `CalibrationBase` and the input one respectively. This prevents us having to do too much recalculation later on.
403 """
404 # Check that we don't have two calibration names that are the same
405 if self.name != calibration.name:
406 # Tests if we have the calibrations added as dependencies already and adds if not
407 if calibration not in self.dependencies:
408 self.dependencies.append(calibration)
409 if self not in calibration.dependencies:
410 calibration.future_dependencies.append(self)
411 else:
412 B2WARNING(f"Tried to add {calibration} as a dependency for {self} but they have the same name."
413 "Dependency was not added.")
414

◆ failed_dependencies()

failed_dependencies ( self)
inherited
Returns the list of calibrations in our dependency list that have failed.

Definition at line 421 of file framework.py.

421 def failed_dependencies(self):
422 """
423 Returns the list of calibrations in our dependency list that have failed.
424 """
425 failed = []
426 for calibration in self.dependencies:
427 if calibration.state == self.fail_state:
428 failed.append(calibration)
429 return failed
430

◆ files_to_iovs() [1/2]

files_to_iovs ( self)
 

Reimplemented from CalibrationBase.

Definition at line 828 of file framework.py.

828 def files_to_iovs(self):
829 """
830 """
831 return self._get_default_collection_attribute("files_to_iovs")
832

◆ files_to_iovs() [2/2]

files_to_iovs ( self,
file_map )
 

Reimplemented from CalibrationBase.

Definition at line 834 of file framework.py.

834 def files_to_iovs(self, file_map):
835 """
836 """
837 self._set_default_collection_attribute("files_to_iovs", file_map)
838

◆ input_files() [1/2]

input_files ( self)
 

Reimplemented from CalibrationBase.

Definition at line 816 of file framework.py.

816 def input_files(self):
817 """
818 """
819 return self._get_default_collection_attribute("input_files")
820

◆ input_files() [2/2]

input_files ( self,
files )
 

Reimplemented from CalibrationBase.

Definition at line 822 of file framework.py.

822 def input_files(self, files):
823 """
824 """
825 self._set_default_collection_attribute("input_files", files)
826

◆ is_valid()

is_valid ( self)
A full calibration consists of a collector AND an associated algorithm AND input_files.

Returns False if:
    1) We are missing any of the above.
    2) There are multiple Collections and the Collectors have mis-matched granularities.
    3) Any of our Collectors have granularities that don't match what our Strategy can use.

Reimplemented from CalibrationBase.

Definition at line 635 of file framework.py.

635 def is_valid(self):
636 """
637 A full calibration consists of a collector AND an associated algorithm AND input_files.
638
639 Returns False if:
640 1) We are missing any of the above.
641 2) There are multiple Collections and the Collectors have mis-matched granularities.
642 3) Any of our Collectors have granularities that don't match what our Strategy can use.
643 """
644 if not self.algorithms:
645 B2WARNING(f"Empty algorithm list for {self.name}.")
646 return False
647
648 if not any([collection.is_valid() for collection in self.collections.values()]):
649 B2WARNING(f"No valid Collections for {self.name}.")
650 return False
651
652 granularities = []
653 for collection in self.collections.values():
654 if collection.is_valid():
655 collector_params = collection.collector.available_params()
656 for param in collector_params:
657 if param.name == "granularity":
658 granularities.append(param.values)
659 if len(set(granularities)) > 1:
660 B2WARNING("Multiple different granularities set for the Collections in this Calibration.")
661 return False
662
663 for alg in self.algorithms:
664 alg_type = type(alg.algorithm).__name__
665 incorrect_gran = [granularity not in alg.strategy.allowed_granularities for granularity in granularities]
666 if any(incorrect_gran):
667 B2WARNING(f"Selected strategy for {alg_type} does not match a collector's granularity.")
668 return False
669 return True
670

◆ iteration() [1/2]

iteration ( self)
Retrieves the current iteration number in the database file.

Returns:
    int: The current iteration number

Definition at line 1097 of file framework.py.

1097 def iteration(self):
1098 """
1099 Retrieves the current iteration number in the database file.
1100
1101 Returns:
1102 int: The current iteration number
1103 """
1104 with CAFDB(self._db_path, read_only=True) as db:
1105 iteration = db.get_calibration_value(self.name, "iteration")
1106 return iteration
1107

◆ iteration() [2/2]

iteration ( self,
iteration )
 

Definition at line 1109 of file framework.py.

1109 def iteration(self, iteration):
1110 """
1111 """
1112 B2DEBUG(29, f"Setting {self.name} to {iteration}.")
1113 with CAFDB(self._db_path) as db:
1114 db.update_calibration_value(self.name, "iteration", iteration)
1115 B2DEBUG(29, f"{self.name} set to {self.iteration}.")
1116
1117

◆ max_collector_jobs() [1/2]

max_collector_jobs ( self)
 

Definition at line 876 of file framework.py.

876 def max_collector_jobs(self):
877 """
878 """
879 return self._get_default_collection_attribute("max_collector_jobs")
880

◆ max_collector_jobs() [2/2]

max_collector_jobs ( self,
max_jobs )
 

Definition at line 882 of file framework.py.

882 def max_collector_jobs(self, max_jobs):
883 """
884 """
885 self._set_default_collection_attribute("max_collector_jobs", max_jobs)
886

◆ max_files_per_collector_job() [1/2]

max_files_per_collector_job ( self)
 

Definition at line 864 of file framework.py.

864 def max_files_per_collector_job(self):
865 """
866 """
867 return self._get_default_collection_attribute("max_files_per_collector_job")
868

◆ max_files_per_collector_job() [2/2]

max_files_per_collector_job ( self,
max_files )
 

Definition at line 870 of file framework.py.

870 def max_files_per_collector_job(self, max_files):
871 """
872 """
873 self._set_default_collection_attribute("max_files_per_collector_job", max_files)
874

◆ output_patterns() [1/2]

output_patterns ( self)
 

Definition at line 852 of file framework.py.

852 def output_patterns(self):
853 """
854 """
855 return self._get_default_collection_attribute("output_patterns")
856

◆ output_patterns() [2/2]

output_patterns ( self,
patterns )
 

Definition at line 858 of file framework.py.

858 def output_patterns(self, patterns):
859 """
860 """
861 self._set_default_collection_attribute("output_patterns", patterns)
862

◆ pre_algorithms() [1/2]

pre_algorithms ( self)
Callback run prior to each algorithm iteration.

Definition at line 936 of file framework.py.

936 def pre_algorithms(self):
937 """
938 Callback run prior to each algorithm iteration.
939 """
940 return [alg.pre_algorithm for alg in self.algorithms]
941

◆ pre_algorithms() [2/2]

pre_algorithms ( self,
func )
 

Definition at line 944 of file framework.py.

944 def pre_algorithms(self, func):
945 """
946 """
947 if func:
948 for alg in self.algorithms:
949 alg.pre_algorithm = func
950 else:
951 B2ERROR("Something evaluated as False passed in as pre_algorithm function.")
952

◆ pre_collector_path() [1/2]

pre_collector_path ( self)
 

Definition at line 840 of file framework.py.

840 def pre_collector_path(self):
841 """
842 """
843 return self._get_default_collection_attribute("pre_collector_path")
844

◆ pre_collector_path() [2/2]

pre_collector_path ( self,
path )
 

Definition at line 846 of file framework.py.

846 def pre_collector_path(self, path):
847 """
848 """
849 self._set_default_collection_attribute("pre_collector_path", path)
850

◆ reset_database()

reset_database ( self,
apply_to_default_collection = True )
Keyword Arguments:
    apply_to_default_collection (bool): Should we also reset the default collection?

Remove everything in the database_chain of this Calibration, including the default central database tag automatically
included from `basf2.conditions.default_globaltags <ConditionsConfiguration.default_globaltags>`. This will NOT affect the
database chain of any `Collection` other than the default one. You can prevent the default Collection from having its chain
reset by setting 'apply_to_default_collection' to False.

Definition at line 671 of file framework.py.

671 def reset_database(self, apply_to_default_collection=True):
672 """
673 Keyword Arguments:
674 apply_to_default_collection (bool): Should we also reset the default collection?
675
676 Remove everything in the database_chain of this Calibration, including the default central database tag automatically
677 included from `basf2.conditions.default_globaltags <ConditionsConfiguration.default_globaltags>`. This will NOT affect the
678 database chain of any `Collection` other than the default one. You can prevent the default Collection from having its chain
679 reset by setting 'apply_to_default_collection' to False.
680 """
681 self.database_chain = []
682 if self.default_collection_name in self.collections and apply_to_default_collection:
683 self.collections[self.default_collection_name].reset_database()
684

◆ run()

run ( self)
Main logic of the Calibration object.
Will be run in a new Thread by calling the start() method.

Reimplemented from CalibrationBase.

Definition at line 1006 of file framework.py.

1006 def run(self):
1007 """
1008 Main logic of the Calibration object.
1009 Will be run in a new Thread by calling the start() method.
1010 """
1011 with CAFDB(self._db_path, read_only=True) as db:
1012 initial_state = db.get_calibration_value(self.name, "checkpoint")
1013 initial_iteration = db.get_calibration_value(self.name, "iteration")
1014 B2INFO(f"Initial status of {self.name} found to be state={initial_state}, iteration={initial_iteration}")
1015 self.machine = CalibrationMachine(self,
1016 iov_to_calibrate=self.iov,
1017 initial_state=initial_state,
1018 iteration=initial_iteration)
1019
1020 self.state = initial_state
1021 self.machine.root_dir = Path(os.getcwd(), self.name)
1022 self.machine.collector_backend = self.backend
1023
1024 # Before we start running, let's clean up any iteration directories from iterations above our initial one.
1025 # Should prevent confusion between attempts if we fail again.
1026 all_iteration_paths = find_int_dirs(self.machine.root_dir)
1027 for iteration_path in all_iteration_paths:
1028 if int(iteration_path.name) > initial_iteration:
1029 shutil.rmtree(iteration_path)
1030
1031 while self.state != self.end_state and self.state != self.fail_state:
1032 if self.state == "init":
1033 try:
1034 B2INFO(f"Attempting collector submission for calibration {self.name}.")
1035 self.machine.submit_collector()
1036 except Exception as err:
1037 B2FATAL(str(err))
1038
1039 self._poll_collector()
1040
1041 # If we failed take us to the final fail state
1042 if self.state == "collector_failed":
1043 self.machine.fail_fully()
1044 return
1045
1046 # It's possible that we might raise an error while attempting to run due
1047 # to some problems e.g. Missing collector output files
1048 # We catch the error and exit with failed state so the CAF will stop
1049 try:
1050 B2INFO(f"Attempting to run algorithms for calibration {self.name}.")
1051 self.machine.run_algorithms()
1052 except MachineError as err:
1053 B2ERROR(str(err))
1054 self.machine.fail()
1055
1056 # If we failed take us to the final fail state
1057 if self.machine.state == "algorithms_failed":
1058 self.machine.fail_fully()
1059 return
1060

◆ state() [1/2]

state ( self)
The current major state of the calibration in the database file. The machine may have a different state.

Definition at line 1077 of file framework.py.

1077 def state(self):
1078 """
1079 The current major state of the calibration in the database file. The machine may have a different state.
1080 """
1081 with CAFDB(self._db_path, read_only=True) as db:
1082 state = db.get_calibration_value(self.name, "state")
1083 return state
1084

◆ state() [2/2]

state ( self,
state )
 

Definition at line 1086 of file framework.py.

1086 def state(self, state):
1087 """
1088 """
1089 B2DEBUG(29, f"Setting {self.name} to state {state}.")
1090 with CAFDB(self._db_path) as db:
1091 db.update_calibration_value(self.name, "state", str(state))
1092 if state in self.checkpoint_states:
1093 db.update_calibration_value(self.name, "checkpoint", str(state))
1094 B2DEBUG(29, f"{self.name} set to {state}.")
1095

◆ strategies() [1/2]

strategies ( self)
The `caf.strategies.AlgorithmStrategy` or `list` of them used when running the algorithm(s).

Definition at line 969 of file framework.py.

969 def strategies(self):
970 """
971 The `caf.strategies.AlgorithmStrategy` or `list` of them used when running the algorithm(s).
972 """
973 return [alg.strategy for alg in self.algorithms]
974

◆ strategies() [2/2]

strategies ( self,
strategy )
 

Definition at line 977 of file framework.py.

977 def strategies(self, strategy):
978 """
979 """
980 if strategy:
981 for alg in self.algorithms:
982 alg.strategy = strategy
983 else:
984 B2ERROR("Something evaluated as False passed in as a strategy.")
985

◆ use_central_database()

use_central_database ( self,
global_tag,
apply_to_default_collection = True )
Parameters:
    global_tag (str): The central database global tag to use for this calibration.

Keyword Arguments:
    apply_to_default_collection (bool): Should we also call use_central_database on the default collection (if it exists)

Using this allows you to append a central database to the database chain for this calibration.
The default database chain is just the central one from
`basf2.conditions.default_globaltags <ConditionsConfiguration.default_globaltags>`.
To turn off central database completely or use a custom tag as the base, you should call `Calibration.reset_database`
and start adding databases with `Calibration.use_local_database` and `Calibration.use_central_database`.

Note that the database chain attached to the `Calibration` will only affect the default `Collection` (if it exists),
and the algorithm processes. So calling:

>> cal.use_central_database("global_tag")

will modify the database chain used by all the algorithms assigned to this `Calibration`, and modifies the database chain
assigned to

>> cal.collections['default'].database_chain

But calling

>> cal.use_central_database(file_path, payload_dir, False)

will add the database to the Algorithm processes, but leave the default Collection database chain untouched.
So if you have multiple Collections in this Calibration *their database chains are separate*.
To specify an additional `CentralDatabase` for a different collection, you will have to call:

>> cal.collections['OtherCollection'].use_central_database("global_tag")

Definition at line 685 of file framework.py.

685 def use_central_database(self, global_tag, apply_to_default_collection=True):
686 """
687 Parameters:
688 global_tag (str): The central database global tag to use for this calibration.
689
690 Keyword Arguments:
691 apply_to_default_collection (bool): Should we also call use_central_database on the default collection (if it exists)
692
693 Using this allows you to append a central database to the database chain for this calibration.
694 The default database chain is just the central one from
695 `basf2.conditions.default_globaltags <ConditionsConfiguration.default_globaltags>`.
696 To turn off central database completely or use a custom tag as the base, you should call `Calibration.reset_database`
697 and start adding databases with `Calibration.use_local_database` and `Calibration.use_central_database`.
698
699 Note that the database chain attached to the `Calibration` will only affect the default `Collection` (if it exists),
700 and the algorithm processes. So calling:
701
702 >> cal.use_central_database("global_tag")
703
704 will modify the database chain used by all the algorithms assigned to this `Calibration`, and modifies the database chain
705 assigned to
706
707 >> cal.collections['default'].database_chain
708
709 But calling
710
711 >> cal.use_central_database(file_path, payload_dir, False)
712
713 will add the database to the Algorithm processes, but leave the default Collection database chain untouched.
714 So if you have multiple Collections in this Calibration *their database chains are separate*.
715 To specify an additional `CentralDatabase` for a different collection, you will have to call:
716
717 >> cal.collections['OtherCollection'].use_central_database("global_tag")
718 """
719 central_db = CentralDatabase(global_tag)
720 self.database_chain.append(central_db)
721 if self.default_collection_name in self.collections and apply_to_default_collection:
722 self.collections[self.default_collection_name].use_central_database(global_tag)
723

◆ use_local_database()

use_local_database ( self,
filename,
directory = "",
apply_to_default_collection = True )
Parameters:
    filename (str): The path to the database.txt of the local database

Keyword Argumemts:
    directory (str): The path to the payloads directory for this local database.
    apply_to_default_collection (bool): Should we also call use_local_database on the default collection (if it exists)

Append a local database to the chain for this calibration.
You can call this function multiple times and each database will be added to the chain IN ORDER.
The databases are applied to this calibration ONLY.
The Local and Central databases applied via these functions are applied to the algorithm processes and optionally
the default `Collection` job as a database chain.
There are other databases applied to the processes later, checked by basf2 in this order:

1) Local Database from previous iteration of this Calibration.
2) Local Database chain from output of previous dependent Calibrations.
3) This chain of Local and Central databases where the last added is checked first.

Note that this function on the `Calibration` object will only affect the default `Collection` if it exists and if
'apply_to_default_collection' remains True. So calling:

>> cal.use_local_database(file_path, payload_dir)

will modify the database chain used by all the algorithms assigned to this `Calibration`, and modifies the database chain
assigned to

>> cal.collections['default'].database_chain

But calling

>> cal.use_local_database(file_path, payload_dir, False)

will add the database to the Algorithm processes, but leave the default Collection database chain untouched.

If you have multiple Collections in this Calibration *their database chains are separate*.
To specify an additional `LocalDatabase` for a different collection, you will have to call:

>> cal.collections['OtherCollection'].use_local_database(file_path, payload_dir)

Definition at line 724 of file framework.py.

724 def use_local_database(self, filename, directory="", apply_to_default_collection=True):
725 """
726 Parameters:
727 filename (str): The path to the database.txt of the local database
728
729 Keyword Argumemts:
730 directory (str): The path to the payloads directory for this local database.
731 apply_to_default_collection (bool): Should we also call use_local_database on the default collection (if it exists)
732
733 Append a local database to the chain for this calibration.
734 You can call this function multiple times and each database will be added to the chain IN ORDER.
735 The databases are applied to this calibration ONLY.
736 The Local and Central databases applied via these functions are applied to the algorithm processes and optionally
737 the default `Collection` job as a database chain.
738 There are other databases applied to the processes later, checked by basf2 in this order:
739
740 1) Local Database from previous iteration of this Calibration.
741 2) Local Database chain from output of previous dependent Calibrations.
742 3) This chain of Local and Central databases where the last added is checked first.
743
744 Note that this function on the `Calibration` object will only affect the default `Collection` if it exists and if
745 'apply_to_default_collection' remains True. So calling:
746
747 >> cal.use_local_database(file_path, payload_dir)
748
749 will modify the database chain used by all the algorithms assigned to this `Calibration`, and modifies the database chain
750 assigned to
751
752 >> cal.collections['default'].database_chain
753
754 But calling
755
756 >> cal.use_local_database(file_path, payload_dir, False)
757
758 will add the database to the Algorithm processes, but leave the default Collection database chain untouched.
759
760 If you have multiple Collections in this Calibration *their database chains are separate*.
761 To specify an additional `LocalDatabase` for a different collection, you will have to call:
762
763 >> cal.collections['OtherCollection'].use_local_database(file_path, payload_dir)
764
765 """
766 local_db = LocalDatabase(filename, directory)
767 self.database_chain.append(local_db)
768 if self.default_collection_name in self.collections and apply_to_default_collection:
769 self.collections[self.default_collection_name].use_local_database(filename, directory)
770

Member Data Documentation

◆ _algorithms

list _algorithms = []
protected

Internal calibration algorithms stored for this calibration.

Definition at line 552 of file framework.py.

◆ _db_path

_db_path = None
protected

Location of a SQLite database that will save the state of the calibration so that it can be restarted from failure.

Definition at line 614 of file framework.py.

◆ alg_output_dir

str alg_output_dir = "algorithm_output"
static

Subdirectory name for algorithm output.

Definition at line 529 of file framework.py.

◆ algorithms

algorithms = algorithms

Algorithm classes that will be run by this Calibration.

You should set this attribute to either a single CalibrationAlgorithm C++ class, or a list of them if you want to run multiple CalibrationAlgorithms using one CalibrationCollectorModule.

Definition at line 572 of file framework.py.

◆ algorithms_runner

algorithms_runner = runners.SeqAlgorithmsRunner

The class that runs all the algorithms in this Calibration using their assigned :py:class:caf.strategies.AlgorithmStrategy.

Plugin your own runner class to change how your calibration will run the list of algorithms.

Definition at line 600 of file framework.py.

◆ backend

backend = None

The backend <backends.Backend> we'll use for our collector submission in this calibration.

If None it will be set by the CAF used to run this Calibration (recommended!).

Definition at line 603 of file framework.py.

◆ checkpoint_states

list checkpoint_states = ["init", "collector_completed", "completed"]
static

Checkpoint states which we are allowed to restart from.

Definition at line 531 of file framework.py.

◆ collections

dict collections = {}

Collections stored for this calibration.

Definition at line 550 of file framework.py.

◆ collector_full_update_interval

int collector_full_update_interval = 30

While checking if the collector is finished we don't bother wastefully checking every subjob's status.

We exit once we find the first subjob that isn't ready. But after this interval has elapsed we do a full :py:meth:caf.backends.Job.update_status call and print the fraction of SubJobs completed.

Definition at line 608 of file framework.py.

◆ database_chain

list database_chain = database_chain

The database chain that is applied to the algorithms.

This is often updated at the same time as the database chain for the default Collection.

Definition at line 591 of file framework.py.

◆ default_collection_name

default_collection_name = "default"
static

Default collection name.

Definition at line 533 of file framework.py.

◆ dependencies

list dependencies = []
inherited

List of calibration objects, where each one is a dependency of this one.

Definition at line 349 of file framework.py.

◆ end_state

str end_state = "completed"
staticinherited

The name of the successful completion state.

The :py:class:CAF will use this as the state to decide when the Calibration is completed.

Definition at line 335 of file framework.py.

◆ fail_state

str fail_state = "failed"
staticinherited

The name of the failure state.

The :py:class:CAF will use this as the state to decide when the Calibration failed.

Definition at line 338 of file framework.py.

◆ future_dependencies

list future_dependencies = []
inherited

List of calibration objects that depend on this one.

Definition at line 347 of file framework.py.

◆ heartbeat

heartbeat = 3

This calibration's sleep time before rechecking to see if it can move state.

Definition at line 610 of file framework.py.

◆ ignored_runs

ignored_runs = None

List of ExpRun that will be ignored by this Calibration.

This runs will not have Collector jobs run on them (if possible). And the algorithm execution will exclude them from a ExpRun list. However, the algorithm execution may merge IoVs of final payloads to cover the 'gaps' caused by these runs. You should pay attention to what the AlgorithmStrategy you choose will do in these cases.

Definition at line 582 of file framework.py.

◆ iov

iov = None
inherited

IoV which will be calibrated.

This is set by the CAF itself when calling CAF.run()

Definition at line 364 of file framework.py.

◆ jobs_to_submit

list jobs_to_submit = []
inherited

A simple list of jobs that this Calibration wants submitted at some point.

Definition at line 371 of file framework.py.

◆ machine

machine = None

The caf.state_machines.CalibrationMachine that we will run to process this calibration start to finish.

Definition at line 612 of file framework.py.

◆ max_iterations

max_iterations = None

Variable to define the maximum number of iterations for this calibration specifically.

It overrides the CAF calibration_defaults value if set.

Definition at line 577 of file framework.py.

◆ moves

list moves = ["submit_collector", "complete", "run_algorithms", "iterate", "fail_fully"]
static

Allowed transitions that we will use to progress.

Definition at line 527 of file framework.py.

◆ name

name = name
inherited

Name of calibration object.

This must be unique when adding into the py:class:CAF.

Definition at line 345 of file framework.py.

◆ output_database_dir

str output_database_dir = ""
inherited

The directory where we'll store the local database payloads from this calibration.

Definition at line 366 of file framework.py.

◆ results

dict results = {}

Output results of algorithms for each iteration.

Definition at line 574 of file framework.py.

◆ save_payloads

bool save_payloads = True
inherited

Marks this Calibration as one which has payloads that should be copied and uploaded.

Defaults to True, and should only be False if this is an intermediate Calibration who's payloads are never needed.

Definition at line 369 of file framework.py.

◆ state

str state = initial_state

state

Definition at line 1020 of file framework.py.

◆ strategies

strategies = strategies.SingleIOV

The strategy that the algorithm(s) will be run against.

Assign a list of strategies the same length as the number of algorithms, or assign a single strategy to apply it to all algorithms in this Calibration. You can see the choices in :py:mod:caf.strategies.

Definition at line 587 of file framework.py.


The documentation for this class was generated from the following file: