10 from ROOT
import gSystem
11 gSystem.Load(
'libtracking')
12 gSystem.Load(
'libtrackFindingCDC')
14 from ROOT
import Belle2
32 return logging.getLogger(__name__)
35 CONTACT =
"oliver.frost@desy.de"
39 """Generate, postprocess and inspect MC events for track segment-pair validation"""
41 segment_finder_module = basf2.register_module(
"TFCDC_SegmentCreatorMCTruth")
42 segment_finder_module.param({
"MinCDCHits": 4})
45 segment_pair_finder_module = basf2.register_module(
"TFCDC_TrackFinderSegmentPairAutomaton")
46 segment_pair_finder_module.param({
47 "WriteSegmentPairs":
True,
48 "SegmentPairFilter":
"all",
49 "SegmentPairRelationFilter":
"none",
55 output_file_name =
"SegmentPairCreationValidation.root"
58 """Convert command-line arguments to basf2 argument list"""
60 return argument_parser
64 Sets up a path that plays back pregenerated events or generates events
65 based on the properties in the base class.
67 main_path = super(SegmentPairCreationValidationRun, self).
create_path()
70 main_path.add_module(segment_finder_module)
72 main_path.add_module(
"TFCDC_SegmentFitter")
75 main_path.add_module(segment_pair_finder_module)
80 main_path.add_module(metamodules.PyProfilingModule(validation_module))
82 main_path.add_module(validation_module)
89 """Module to collect information about the generated segments and compose validation plots on terminate."""
93 super(SegmentPairCreationValidationModule, self).
__init__(foreach=
"CDCSegmentPairVector",
94 output_file_name=output_file_name)
103 """Receive signal at the start of event processing"""
104 super(SegmentPairCreationValidationModule, self).
initialize()
110 """Initialize the MC-hit lookup method"""
113 def pick(self, segment_pair_relation):
114 """Select segment pairs with 4 or more hit in each segments and a matching primary MC particle"""
116 start_segment = segment_pair_relation.getStartSegment()
117 end_segment = segment_pair_relation.getEndSegment()
118 mc_particle = mc_segment_lookup.getMCParticle(start_segment)
119 return (mc_particle
and
120 is_primary(mc_particle)
and
121 start_segment.size() > 3
and
122 end_segment.size() > 3)
124 def peel(self, segment_pair_relation):
125 """Aggregate the track and MC information for track segment-pair analysis"""
127 crops.update(self.
peel_mc(segment_pair_relation))
128 crops.update(self.
peel_fit(segment_pair_relation))
132 """Create a dictionary of MC-truth (weight,decision) pairs"""
134 mc_decision = np.isfinite(mc_weight)
138 mc_decision=mc_decision,
142 """Create a dictionary of MC-truth (curvature,tanlambda) pairs"""
145 end_segment = segment_pair_relation.getEndSegment()
148 mc_particle = mc_segment_lookup.getMCParticle(end_segment)
149 fit3d_truth = mc_segment_lookup.getTrajectory3D(end_segment)
152 curvature_truth=fit3d_truth.getCurvatureXY(),
153 tan_lambda_truth=fit3d_truth.getTanLambda(),
157 """Create a dictionary of track-segment-fit information"""
158 fitless_crops = self.
peel_fitless(segment_pair_relation)
160 select_fitless = fitless_crops[
"select_fitless"]
163 self.
fit(segment_pair_relation)
164 fit3d = segment_pair_relation.getTrajectory3D()
169 chi2 = fit3d.getChi2()
172 curvature_estimate = fit3d.getCurvatureXY()
173 curvature_variance = fit3d.getLocalVariance(i_curv)
175 tan_lambda_estimate = fit3d.getTanLambda()
176 tan_lambda_variance = fit3d.getLocalVariance(i_tan_lambda)
180 p_value = prob(chi2, ndf)
185 curvature_estimate = nan
186 curvature_variance = nan
188 tan_lambda_estimate = nan
189 tan_lambda_variance = nan
196 curvature_estimate=curvature_estimate,
197 curvature_variance=curvature_variance,
199 tan_lambda_estimate=tan_lambda_estimate,
200 tan_lambda_variance=tan_lambda_variance,
208 crops[
"select"] = self.
select(crops)
210 crops[
"select"] =
False
212 crops.update(fitless_crops)
217 """Create a dictionary of track-segments-without-fit information"""
221 start_segment = segment_pair_relation.getStartSegment()
222 end_segment = segment_pair_relation.getEndSegment()
224 start_fit2d = start_segment.getTrajectory2D()
225 end_fit2d = end_segment.getTrajectory2D()
227 start_superlayer_id = start_segment.getISuperLayer()
228 end_superlayer_id = end_segment.getISuperLayer()
230 sorted_superlayer_ids = sorted([start_superlayer_id, end_superlayer_id])
232 superlayer_id_pair = 10.0 * sorted_superlayer_ids[1] + sorted_superlayer_ids[0]
234 fitless_crops = dict(
235 start_superlayer_id=start_superlayer_id,
236 end_superlayer_id=end_superlayer_id,
237 superlayer_id_pair=superlayer_id_pair,
239 start_size=start_segment.size(),
240 end_size=end_segment.size(),
242 start_curvature_estimate=start_fit2d.getCurvature(),
243 end_curvature_estimate=end_fit2d.getCurvature(),
245 delta_phi=segment_pair_relation.computeDeltaPhiAtSuperLayerBound(),
246 is_coaligned=segment_pair_relation.computeIsCoaligned(),
248 start_is_before_end=segment_pair_relation.computeStartIsBeforeEnd(),
249 end_is_after_start=segment_pair_relation.computeEndIsAfterStart(),
252 fitless_crops[
"select_fitless"] = self.
select_fitless(fitless_crops)
255 def fit(self, segment_pair_relation):
256 """Fit the segment pair"""
260 delta_phi_cut_value = 1.0
262 is_after_cut_value = 1.0
265 """Selection of track-segments-without-fit"""
266 delta_phi = fitless_crops[
"delta_phi"]
267 start_is_before_end = fitless_crops[
"start_is_before_end"]
268 end_is_after_start = fitless_crops[
"end_is_after_start"]
273 """Select every track-segment-pair"""
278 save_histograms = refiners.save_histograms(outlier_z_score=5.0, allow_discrete=
True)
280 save_tree = refiners.save_tree()
284 save_fitless_selection_variables_histograms = refiners.save_histograms(
285 select=[
"mc_decision",
"delta_phi",
"start_is_before_end",
"end_is_after_start",
"is_coaligned"],
288 stackby=
"mc_decision",
289 folder_name=
"fitless_selection_variables",
293 save_view_is_after_cut_histograms = refiners.save_histograms(
294 select=[
"mc_decision",
"start_is_before_end",
"end_is_after_start"],
295 lower_bound=-is_after_cut_value,
296 upper_bound=is_after_cut_value,
297 stackby=
"mc_decision",
298 folder_name=
"view_fitless_cuts",
302 save_view_delta_phi_cut_histograms = refiners.save_histograms(
303 select=[
"mc_decision",
"delta_phi"],
304 lower_bound=-delta_phi_cut_value,
305 upper_bound=delta_phi_cut_value,
306 stackby=
"mc_decision",
307 folder_name=
"view_fitless_cuts",
312 save_selection_variables_after_fitless_selection_histograms = refiners.save_histograms(
313 select=[
"mc_decision",
"chi2",
"ndf",
"p_value"],
316 stackby=
"mc_decision",
317 folder_name=
"selection_variables_after_fitless_selection",
318 filter_on=
"select_fitless",
323 save_p_value_over_curvature_profile = refiners.save_profiles(
324 select={
"p_value":
"p-value",
"curvature_truth":
"true curvature"},
326 folder_name=
"selection_variables_after_fitless_selection",
327 title=
r"$p$-value versus true curvature after fitless selection",
328 filter_on=
"select_fitless",
332 @refiners.context(groupby=[
None,
"superlayer_id_pair"], exclude_groupby=
False)
335 """Print diagnostic information about the track-segment-pair selection"""
336 info = get_logger().info
338 start_superlayer_ids = crops[
"start_superlayer_id"]
339 end_superlayer_ids = crops[
"end_superlayer_id"]
341 superlayer_id_pair = crops[
"superlayer_id_pair"]
342 info(
"Number of pairs in superlayers %s : %s", np.unique(superlayer_id_pair), len(superlayer_id_pair))
344 mc_decisions = crops[
"mc_decision"]
345 n = len(mc_decisions)
346 n_signal = np.sum(mc_decisions)
347 n_background = n - n_signal
348 info(
"#Signal : %s", n_signal)
349 info(
"#Background : %s", n_background)
351 fitless_selections = np.nonzero(crops[
"select_fitless"])
352 info(
"#Signal after precut : %s", np.sum(mc_decisions[fitless_selections]))
353 info(
"#Background after precut : %s", np.sum(1 - mc_decisions[fitless_selections]))
358 run.configure_and_execute_from_commandline()
361 if __name__ ==
"__main__":
362 logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=
'%(levelname)s:%(message)s')