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 = []
 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)
 
 _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 447 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 538 of file framework.py.

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

Member Function Documentation

◆ __repr__()

__repr__ ( self)
 

Definition at line 1012 of file framework.py.

1012 def __repr__(self):
1013 """
1014 """
1015 return self.name
1016

◆ _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 434 of file framework.py.

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

◆ _get_default_collection_attribute()

_get_default_collection_attribute ( self,
attr )
protected
 

Definition at line 774 of file framework.py.

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

◆ _poll_collector()

_poll_collector ( self)
protected
 

Definition at line 1072 of file framework.py.

1072 def _poll_collector(self):
1073 """
1074 """
1075 while self.state == "running_collector":
1076 try:
1077 self.machine.complete()
1078 # ConditionError is thrown when the conditions for the transition have returned false, it's not serious.
1079 except ConditionError:
1080 try:
1081 B2DEBUG(29, f"Checking if collector jobs for calibration {self.name} have failed.")
1082 self.machine.fail()
1083 except ConditionError:
1084 pass
1085 sleep(self.heartbeat) # Sleep until we want to check again
1086

◆ _set_default_collection_attribute()

_set_default_collection_attribute ( self,
attr,
value )
protected
 

Definition at line 786 of file framework.py.

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

◆ 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 619 of file framework.py.

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

◆ algorithms() [1/2]

algorithms ( self)
 

Definition at line 903 of file framework.py.

903 def algorithms(self):
904 """
905 """
906 return self._algorithms
907

◆ algorithms() [2/2]

algorithms ( self,
value )
 

Definition at line 910 of file framework.py.

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

◆ backend_args() [1/2]

backend_args ( self)
 

Definition at line 891 of file framework.py.

891 def backend_args(self):
892 """
893 """
894 return self._get_default_collection_attribute("backend_args")
895

◆ backend_args() [2/2]

backend_args ( self,
args )
 

Definition at line 897 of file framework.py.

897 def backend_args(self, args):
898 """
899 """
900 self._set_default_collection_attribute("backend_args", args)
901

◆ collector() [1/2]

collector ( self)
 

Definition at line 798 of file framework.py.

798 def collector(self):
799 """
800 """
801 return self._get_default_collection_attribute("collector")
802

◆ collector() [2/2]

collector ( self,
collector )
 

Definition at line 804 of file framework.py.

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

◆ 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 # Use local variable to avoid doxygen "no uniquely matching class member" warning
427 # (multiple classes in this file define self.dependencies with doc comments)
428 dependencies = self.dependencies
429 for calibration in dependencies:
430 if calibration.state == self.fail_state:
431 failed.append(calibration)
432 return failed
433

◆ files_to_iovs() [1/2]

files_to_iovs ( self)
 

Reimplemented from CalibrationBase.

Definition at line 831 of file framework.py.

831 def files_to_iovs(self):
832 """
833 """
834 return self._get_default_collection_attribute("files_to_iovs")
835

◆ files_to_iovs() [2/2]

files_to_iovs ( self,
file_map )
 

Reimplemented from CalibrationBase.

Definition at line 837 of file framework.py.

837 def files_to_iovs(self, file_map):
838 """
839 """
840 self._set_default_collection_attribute("files_to_iovs", file_map)
841

◆ input_files() [1/2]

input_files ( self)
 

Reimplemented from CalibrationBase.

Definition at line 819 of file framework.py.

819 def input_files(self):
820 """
821 """
822 return self._get_default_collection_attribute("input_files")
823

◆ input_files() [2/2]

input_files ( self,
files )
 

Reimplemented from CalibrationBase.

Definition at line 825 of file framework.py.

825 def input_files(self, files):
826 """
827 """
828 self._set_default_collection_attribute("input_files", files)
829

◆ 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 638 of file framework.py.

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

◆ iteration() [1/2]

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

Returns:
    int: The current iteration number

Definition at line 1108 of file framework.py.

1108 def iteration(self):
1109 """
1110 Retrieves the current iteration number in the database file.
1111
1112 Returns:
1113 int: The current iteration number
1114 """
1115 with CAFDB(self._db_path, read_only=True) as db:
1116 iteration = db.get_calibration_value(self.name, "iteration")
1117 return iteration
1118

◆ iteration() [2/2]

iteration ( self,
iteration )
 

Definition at line 1120 of file framework.py.

1120 def iteration(self, iteration):
1121 """
1122 """
1123 B2DEBUG(29, f"Setting {self.name} to {iteration}.")
1124 with CAFDB(self._db_path) as db:
1125 db.update_calibration_value(self.name, "iteration", iteration)
1126 B2DEBUG(29, f"{self.name} set to {self.iteration}.")
1127
1128

◆ max_collector_jobs() [1/2]

max_collector_jobs ( self)
 

Definition at line 879 of file framework.py.

879 def max_collector_jobs(self):
880 """
881 """
882 return self._get_default_collection_attribute("max_collector_jobs")
883

◆ max_collector_jobs() [2/2]

max_collector_jobs ( self,
max_jobs )
 

Definition at line 885 of file framework.py.

885 def max_collector_jobs(self, max_jobs):
886 """
887 """
888 self._set_default_collection_attribute("max_collector_jobs", max_jobs)
889

◆ max_files_per_collector_job() [1/2]

max_files_per_collector_job ( self)
 

Definition at line 867 of file framework.py.

867 def max_files_per_collector_job(self):
868 """
869 """
870 return self._get_default_collection_attribute("max_files_per_collector_job")
871

◆ max_files_per_collector_job() [2/2]

max_files_per_collector_job ( self,
max_files )
 

Definition at line 873 of file framework.py.

873 def max_files_per_collector_job(self, max_files):
874 """
875 """
876 self._set_default_collection_attribute("max_files_per_collector_job", max_files)
877

◆ output_patterns() [1/2]

output_patterns ( self)
 

Definition at line 855 of file framework.py.

855 def output_patterns(self):
856 """
857 """
858 return self._get_default_collection_attribute("output_patterns")
859

◆ output_patterns() [2/2]

output_patterns ( self,
patterns )
 

Definition at line 861 of file framework.py.

861 def output_patterns(self, patterns):
862 """
863 """
864 self._set_default_collection_attribute("output_patterns", patterns)
865

◆ pre_algorithms() [1/2]

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

Definition at line 943 of file framework.py.

943 def pre_algorithms(self):
944 """
945 Callback run prior to each algorithm iteration.
946 """
947 return [alg.pre_algorithm for alg in self.algorithms]
948

◆ pre_algorithms() [2/2]

pre_algorithms ( self,
func )
 

Definition at line 951 of file framework.py.

951 def pre_algorithms(self, func):
952 """
953 """
954 if func:
955 for alg in self.algorithms:
956 alg.pre_algorithm = func
957 else:
958 B2ERROR("Something evaluated as False passed in as pre_algorithm function.")
959

◆ pre_collector_path() [1/2]

pre_collector_path ( self)
 

Definition at line 843 of file framework.py.

843 def pre_collector_path(self):
844 """
845 """
846 return self._get_default_collection_attribute("pre_collector_path")
847

◆ pre_collector_path() [2/2]

pre_collector_path ( self,
path )
 

Definition at line 849 of file framework.py.

849 def pre_collector_path(self, path):
850 """
851 """
852 self._set_default_collection_attribute("pre_collector_path", path)
853

◆ 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 674 of file framework.py.

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

◆ 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 1017 of file framework.py.

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

◆ 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 1088 of file framework.py.

1088 def state(self):
1089 """
1090 The current major state of the calibration in the database file. The machine may have a different state.
1091 """
1092 with CAFDB(self._db_path, read_only=True) as db:
1093 state = db.get_calibration_value(self.name, "state")
1094 return state
1095

◆ state() [2/2]

state ( self,
state )
 

Definition at line 1097 of file framework.py.

1097 def state(self, state):
1098 """
1099 """
1100 B2DEBUG(29, f"Setting {self.name} to state {state}.")
1101 with CAFDB(self._db_path) as db:
1102 db.update_calibration_value(self.name, "state", str(state))
1103 if state in self.checkpoint_states:
1104 db.update_calibration_value(self.name, "checkpoint", str(state))
1105 B2DEBUG(29, f"{self.name} set to {state}.")
1106

◆ strategies() [1/2]

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

Definition at line 978 of file framework.py.

978 def strategies(self):
979 """
980 The `caf.strategies.AlgorithmStrategy` or `list` of them used when running the algorithm(s).
981 """
982 return [alg.strategy for alg in self.algorithms]
983

◆ strategies() [2/2]

strategies ( self,
strategy )
 

Definition at line 986 of file framework.py.

986 def strategies(self, strategy):
987 """
988 """
989 if strategy:
990 for alg in self.algorithms:
991 alg.strategy = strategy
992 else:
993 B2ERROR("Something evaluated as False passed in as a strategy.")
994

◆ 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 688 of file framework.py.

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

◆ 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 727 of file framework.py.

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

Member Data Documentation

◆ _algorithms

list _algorithms = []
protected

Internal calibration algorithms stored for this calibration.

Definition at line 555 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 617 of file framework.py.

◆ alg_output_dir

str alg_output_dir = "algorithm_output"
static

Subdirectory name for algorithm output.

Definition at line 532 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 575 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 603 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 606 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 534 of file framework.py.

◆ collections

dict collections = {}

Collections stored for this calibration.

Definition at line 553 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 611 of file framework.py.

◆ database_chain

list 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 593 of file framework.py.

◆ default_collection_name

default_collection_name = "default"
static

Default collection name.

Definition at line 536 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 613 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 585 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 615 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 580 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 530 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 577 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 1031 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 590 of file framework.py.


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