Belle II Software development
constraints_generator.py
1
8
9import basf2 as b2
10
11import os
12import sys
13import pickle
14
15# Needed for pickling of constraints
16from alignment.constraints import * # noqa
17
18
19class ConstraintsGenerator(b2.Module):
20 """
21 basf2 python module to generate a file with a single set of constraints
22
23 (Needed especially for time-dependent constraints)
24 """
25
26 def __init__(self, generator):
27 """
28 Constructor
29
30 Parameters
31 ----------
32 generator : alignment.Constraints
33 Set of constraints to be generated (defines also filename)
34
35 """
36
37 super().__init__()
38
39 self.generator = generator
40
41 self.consts = dict()
42 super().set_name(super().name() + ":" + generator.filename)
43
44 def event(self):
45 """ Event: attempt to add constraints
46 At each event, attempt to generate the constraints and add them
47 to the dict (same cheksum - using only labels - means it gets overriden!)
48 Thus is only works if the time-dependence is set (otherwise you always get the same labels and
49 only the last constraint coefficients will be stored)
50 """
51 consts = self.generator.generate()
52 for const in consts:
53 self.consts[const.get_checksum()] = const.data
54
55 def terminate(self):
56 """ Terminate: write-down collect constraint data to file
57 """
58 if len(self.consts):
59 with open(self.generator.filename, 'w') as f:
60 for checksum, data in self.consts.items():
61 f.write('Constraint 0.\n')
62 for label, coef in data:
63 f.write('{} {}\n'.format(label, coef))
64 print("Finished file: ", self.generator.filename)
65 print("Done: ", self.generator.filename)
66
67
68def save_config(constraint_sets, timedep_config=None, global_tags=None, init_event=None):
69 """
70 Save constraints configuration to a file (using pickle)
71
72 Parameters
73 ----------
74 constraint_sets : list (alignment.Constraints)
75 List of sets of constraints
76 timedep_config : list(tuple(list(int), list(tuple(int, int, int))))
77 Time-depence configuration.
78 Each list item is 2-tuple with list of parameter numbers (use alignment.parameters to get them) and
79 the (event, run, exp) numbers at which values of these parameters can change.
80 global_tags : list (str)
81 List of global tag names and/or (absolute) file paths to local databases
82 init_event : tuple( int, int, int)
83 Event (event, run, exp) at which to initialize time-INdependent constraints
84
85 """
86 a = {'constraint_sets': constraint_sets, 'timedep_config': timedep_config, 'global_tags': global_tags, 'init_event': init_event}
87
88 file_Name = "constraint_config.pickled"
89 # open the file for writing
90 with open(file_Name, 'wb') as fileObject:
91
92 # this writes the object a to the
93 # file named 'testfile'
94 pickle.dump(a, fileObject)
95 print('Saving config to: ', file_Name)
96
97 return file_Name
98
99
100def read_config(filename='constraint_config.pickled'):
101 """ Read the pickled constraint configuration from a file
102
103 filename : str
104 File with pickled constraints' configuration
105 """
106 print('Reading config from: ', filename)
107 with open(filename, 'rb') as fileObject:
108 # load the object from the file into var b
109 b = pickle.load(fileObject)
110 return (b['constraint_sets'], b['timedep_config'], b['global_tags'], b['init_event'])
111
112
113def gen_constraints(constraint_sets, timedep_config=None, global_tags=None, init_event=None):
114 """
115 Generate "event files" from timedep config and run over them to collect constraint data
116 and write it to files.
117
118 This is a bit tricky. I did not found a way to run basf2 over just a specified list of events
119 other than generating the files with metadata for event and then running over the files.
120 This uses unning basf2 multiple times in one script - seems to work despite the warnings - but only
121 for the generation of "event files"
122
123 Parameters
124 ----------
125 constraint_sets : list (alignment.Constraints)
126 List of sets of constraints
127 timedep_config : list(tuple(list(int), list(tuple(int, int, int))))
128 Time-depence configuration.
129 Each list item is 2-tuple with list of parameter numbers (use alignment.parameters to get them) and
130 the (event, run, exp) numbers at which values of these parameters can change.
131 global_tags : list (str)
132 List of global tag names and/or (absolute) file paths to local databases
133 init_event : tuple( int, int, int)
134 Event (event, run, exp) at which to initialize time-INdependent constraints
135
136 """
137 if timedep_config is None:
138 timedep_config = []
139
140 if global_tags is None:
141 global_tags = [tag for tag in b2.conditions.default_globaltags]
142
143 events = []
144 for (labels, events_) in timedep_config:
145 events += [event for event in events_]
146
147 if not len(timedep_config):
148 if init_event is None:
149 init_event = (0, 0, 0)
150 events = [init_event]
151
152 events = [(exp, run, ev) for (ev, run, exp) in events]
153 events = sorted(list(set(events)))
154 events = [(ev_, run_, exp_) for (exp_, run_, ev_) in events]
155
156 fileName = 'TimedepConfigEvent_exp{}run{}ev{}.root'
157 files = []
158
159 print('Global tags:')
160 print(global_tags)
161 print('Global tags reversed (this will be used for b2.conditions.override_globaltags(...)):')
162 print([tag for tag in reversed(global_tags)])
163
164 for tag in [tag for tag in reversed(global_tags)]:
165 if os.path.exists(tag):
166 b2.conditions.append_testing_payloads(os.path.abspath(tag))
167 else:
168 b2.conditions.append_globaltag(tag)
169
170 for index, event in enumerate(events):
171 # conditions.reset()
172
173 ev, run, exp = event
174 path = b2.create_path()
175 path.add_module("EventInfoSetter",
176 skipNEvents=ev,
177 evtNumList=[ev + 1],
178 runList=[run],
179 expList=[exp])
180 path.add_module('Progress')
181 this_filename = fileName.format(exp, run, ev)
182 path.add_module('RootOutput', outputFileName=this_filename, ignoreCommandLineOverride=True)
183 files.append(this_filename)
184 b2.process(path)
185 print(b2.statistics)
186
187 print(files)
188
189 # conditions.override_globaltags(global_tags)
190
191 path = b2.create_path()
192 path.add_module("RootInput", inputFileNames=files, ignoreCommandLineOverride=True)
193 path.add_module('HistoManager')
194 path.add_module('Progress')
195 path.add_module('Gearbox')
196 path.add_module('Geometry')
197
198 collector = path.add_module('MillepedeCollector',
199 timedepConfig=timedep_config)
200
201 constraint_files = []
202 for constraint_set in constraint_sets:
203 constraint_set.configure_collector(collector)
204 constraint_files.append(constraint_set.filename)
205 path.add_module(ConstraintsGenerator(constraint_set))
206
207 b2.process(path)
208 print(b2.statistics)
209
210 return [os.path.abspath(file) for file in constraint_files]
211
212
213def gen_constraints_from_config(filename='constraint_config.pickled'):
214 """
215 Generate constraints from pickled configuration
216 """
217 constraint_sets, timedep_config, global_tags, init_event = read_config(filename)
218 gen_constraints(constraint_sets, timedep_config, global_tags, init_event)
219
220
221if __name__ == '__main__':
222 if len(sys.argv) != 2:
223 print('Usage: basf2 constraints_generator.py config_filename')
224 exit()
225
226
227 filename = sys.argv[1]
228 gen_constraints_from_config(filename)
consts
Generated constraints (key is constraint checksum)