10 A set of common purose translators from complex framework objects to flat dictionaries
20 from ROOT
import Belle2
27 Belle2.RecoTrack.getRightLeftInformation[
"Belle2::CDCHit"]
28 ROOT.gSystem.Load(
"libtracking")
30 formatter = TolerateMissingKeyFormatter()
35 def format_crop_keys(peel_func):
36 @functools.wraps(peel_func)
37 def peel_func_formatted_keys(*args, key="{part_name}", **kwargs):
38 crops = peel_func(*args, **kwargs, key=key)
39 if key
and hasattr(crops,
'items'):
40 crops_with_formatted_keys = dict()
41 for part_name, value
in list(crops.items()):
42 formatted_key = formatter.format(key, part_name=part_name)
43 crops_with_formatted_keys[formatted_key] = value
44 return crops_with_formatted_keys
49 return peel_func_formatted_keys
55 def peel_mc_particle(mc_particle, key="{part_name}"):
57 helix = get_helix_from_mc_particle(mc_particle)
58 momentum = mc_particle.getMomentum()
59 vertex = mc_particle.getVertex()
60 charge = mc_particle.getCharge()
61 pdg_code = mc_particle.getPDG()
62 is_primary = bool(mc_particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle))
64 decay_vertex = mc_particle.getDecayVertex()
65 number_of_daughters = mc_particle.getNDaughters()
66 status = mc_particle.getStatus()
70 d0_truth=helix.getD0(),
71 phi0_truth=helix.getPhi0() % (2.0 * math.pi),
72 omega_truth=helix.getOmega(),
73 z0_truth=helix.getZ0(),
74 tan_lambda_truth=helix.getTanLambda(),
77 pt_truth=momentum.Perp(),
78 px_truth=momentum.X(),
79 py_truth=momentum.Y(),
80 pz_truth=momentum.Z(),
85 decay_vertex_radius_truth=decay_vertex.Mag(),
86 decay_vertex_x_truth=decay_vertex.X(),
87 decay_vertex_y_truth=decay_vertex.Y(),
88 decay_vertex_z_truth=decay_vertex.Z(),
89 number_of_daughters_truth=number_of_daughters,
94 pdg_code_truth=pdg_code,
95 is_primary=is_primary,
106 tan_lambda_truth=nan,
117 decay_vertex_radius_truth=nan,
118 decay_vertex_x_truth=nan,
119 decay_vertex_y_truth=nan,
120 decay_vertex_z_truth=nan,
121 number_of_daughters_truth=nan,
135 def peel_reco_track_hit_content(reco_track, key="{part_name}"):
138 first_pxd_layer = nan
140 first_svd_layer = nan
142 first_cdc_layer = nan
151 n_cdc_hits = reco_track.getNumberOfCDCHits()
152 n_svd_hits = reco_track.getNumberOfSVDHits()
153 n_pxd_hits = reco_track.getNumberOfPXDHits()
154 ndf = 2 * n_pxd_hits + n_svd_hits + n_cdc_hits
156 pxd_hits = [hit.getSensorID().getLayerNumber()
for hit
in getObjectList(reco_track.getPXDHitList())]
158 first_pxd_layer = min(pxd_hits)
159 last_pxd_layer = max(pxd_hits)
160 svd_hits = [hit.getSensorID().getLayerNumber()
for hit
in getObjectList(reco_track.getSVDHitList())]
162 first_svd_layer = min(svd_hits)
163 last_svd_layer = max(svd_hits)
164 cdc_hits = [hit.getICLayer()
for hit
in getObjectList(reco_track.getCDCHitList())]
166 first_cdc_layer = min(cdc_hits)
167 last_cdc_layer = max(cdc_hits)
168 for hit_info
in getObjectList(reco_track.getRelationsWith(
"RecoHitInformations")):
169 track_point = reco_track.getCreatedTrackPoint(hit_info)
171 fitted_state = track_point.getFitterInfo()
173 W = max(fitted_state.getWeights())
175 if W > 0.5
and hit_info.getTrackingDetector() == Belle2.RecoHitInformation.c_CDC:
176 layer = hit_info.getRelated(
"CDCHits").getICLayer()
177 if layer > last_fit_layer:
178 last_fit_layer = layer
180 n_pxd_hits=n_pxd_hits,
181 n_svd_hits=n_svd_hits,
182 n_cdc_hits=n_cdc_hits,
183 n_hits=n_pxd_hits + n_svd_hits + n_cdc_hits,
185 first_pxd_layer=first_pxd_layer,
186 last_pxd_layer=last_pxd_layer,
187 first_svd_layer=first_svd_layer,
188 last_svd_layer=last_svd_layer,
189 first_cdc_layer=first_cdc_layer,
190 last_cdc_layer=last_cdc_layer,
191 sum_of_weights=sum_of_weights,
192 last_fit_layer=last_fit_layer
201 first_pxd_layer=first_pxd_layer,
202 last_pxd_layer=last_pxd_layer,
203 first_svd_layer=first_svd_layer,
204 last_svd_layer=last_svd_layer,
205 first_cdc_layer=first_cdc_layer,
206 last_cdc_layer=last_cdc_layer,
207 sum_of_weights=sum_of_weights,
208 last_fit_layer=last_fit_layer
215 def peel_reco_track_seed(reco_track, key="{part_name}"):
217 seed_fit_result = get_seed_track_fit_result(reco_track)
218 return peel_track_fit_result(seed_fit_result, key=
"seed_{part_name}")
221 return peel_track_fit_result(
None, key=
"seed_{part_name}")
227 def peel_event_info(event_meta_data, key="{part_name}"):
229 event_number=event_meta_data.getEvent(),
230 run_number=event_meta_data.getRun(),
231 experiment_number=event_meta_data.getExperiment(),
238 def peel_store_array_info(item, key="{part_name}"):
241 store_array_number=item.getArrayIndex()
245 store_array_number=float(
"nan")
252 def peel_store_array_size(array_name, key="{part_name}"):
254 return {str(array_name) +
"_size": array.getEntries()
if array
else 0}
260 def peel_event_level_tracking_info(event_level_tracking_info, key="{part_name}"):
261 if not event_level_tracking_info:
263 has_vxdtf2_failure_flag=
False,
264 has_svdckf_failure_flag=
False,
265 has_pxdckf_failure_flag=
False,
266 has_unspecified_trackfinding_failure=
False,
268 return dict(has_vxdtf2_failure_flag=event_level_tracking_info.hasVXDTF2AbortionFlag(),
269 has_svdckf_failure_flag=event_level_tracking_info.hasSVDCKFAbortionFlag(),
270 has_pxdckf_failure_flag=event_level_tracking_info.hasPXDCKFAbortionFlag(),
271 has_unspecified_trackfinding_failure=event_level_tracking_info.hasUnspecifiedTrackFindingFailure(),
278 def peel_quality_indicators(reco_track, key="{part_name}"):
286 qi = reco_track.getQualityIndicator()
287 space_point_track_cand = reco_track.getRelated(
'SPTrackCands')
290 if not space_point_track_cand:
291 svd_track_cand = reco_track.getRelated(
'SVDRecoTracks')
292 if not svd_track_cand:
293 svd_cdc_track_cand = reco_track.getRelated(
'SVDCDCRecoTracks')
294 if svd_cdc_track_cand:
295 svd_track_cand = svd_cdc_track_cand.getRelated(
'SVDRecoTracks')
296 if not svd_track_cand:
297 temp_svd_track_cand = svd_cdc_track_cand.getRelated(
'SVDPlusCDCStandaloneRecoTracks')
298 if temp_svd_track_cand:
299 svd_track_cand = temp_svd_track_cand.getRelated(
'SVDRecoTracks')
301 space_point_track_cand = svd_track_cand.getRelated(
'SPTrackCands')
303 if space_point_track_cand:
304 svd_qi = space_point_track_cand.getQualityIndicator()
306 cdc_track_cand = reco_track.getRelated(
'CDCRecoTracks')
307 if not cdc_track_cand:
308 svd_cdc_track_cand = reco_track.getRelated(
'SVDCDCRecoTracks')
309 if svd_cdc_track_cand:
310 cdc_track_cand = svd_cdc_track_cand.getRelated(
'CDCRecoTracks')
311 if not cdc_track_cand:
312 cdc_track_cand = svd_cdc_track_cand.getRelated(
'CKFCDCRecoTracks')
313 if not cdc_track_cand:
314 temp_cdc_track_cand = svd_cdc_track_cand.getRelated(
'SVDPlusCDCStandaloneRecoTracks')
315 if temp_cdc_track_cand:
316 cdc_track_cand = temp_cdc_track_cand.getRelated(
'CDCRecoTracks')
319 cdc_qi = cdc_track_cand.getQualityIndicator()
322 quality_indicator=qi,
323 svd_quality_indicator=svd_qi,
324 cdc_qualityindicator=cdc_qi,
333 def peel_trackfinder(reco_track, key="{part_name}"):
334 used_CDCTrackFinder =
False
335 used_VXDTrackFinder =
False
336 used_SVDtoCDCCKF =
False
337 used_ECLtoCDCCKF =
False
338 used_CDCtoSVDCKF =
False
341 if reco_track.getNumberOfSVDHits() > 0:
342 info = get_reco_hit_information(reco_track, reco_track.getSVDHitList()[0])
343 svd_tf = info.getFoundByTrackFinder()
344 used_VXDTrackFinder = svd_tf == Belle2.RecoHitInformation.c_VXDTrackFinder
345 used_CDCtoSVDCKF = svd_tf == Belle2.RecoHitInformation.c_CDCtoSVDCKF
347 if reco_track.getNumberOfCDCHits() > 0:
348 info = get_reco_hit_information(reco_track, reco_track.getCDCHitList()[0])
349 cdc_tf = info.getFoundByTrackFinder()
350 used_CDCTrackFinder = cdc_tf == Belle2.RecoHitInformation.c_CDCTrackFinder
351 used_SVDtoCDCCKF = cdc_tf == Belle2.RecoHitInformation.c_SVDtoCDCCKF
352 used_ECLtoCDCCKF = cdc_tf == Belle2.RecoHitInformation.c_ECLtoCDCCKF
355 foundby_CDCTrackFinder=used_CDCTrackFinder,
356 foundby_VXDTrackFinder=used_VXDTrackFinder,
357 foundby_SVDtoCDCCKF=used_SVDtoCDCCKF,
358 foundby_CDCtoSVDCKF=used_CDCtoSVDCKF,
359 foundby_ECLtoCDCCKF=used_ECLtoCDCCKF,
368 def peel_fit_status(reco_track, key="{part_name}"):
386 crops[
"is_fitted"] = reco_track.wasFitSuccessful()
388 for rep
in getObjectList(reco_track.getRepresentations()):
389 was_successful = reco_track.wasFitSuccessful(rep)
390 pdg_code = rep.getPDG()
392 for crop
in crops.keys():
393 if crop.startswith(
"fit_"):
394 particle_name = crop.split(
"_")[1]
395 if abs(getattr(
Belle2.Const, particle_name).getPDGCode()) == abs(pdg_code):
396 crops[crop] = was_successful
399 crops[f
"ndf_{particle_name}"] = reco_track.getTrackFitStatus(rep).getNdf()
407 def peel_track_fit_result(track_fit_result, key="{part_name}"):
410 cov6 = track_fit_result.getCovariance6()
411 mom = track_fit_result.getMomentum()
412 pos = track_fit_result.getPosition()
414 pt_estimate = mom.Perp()
416 pt_variance = np.divide(
417 mom.X() ** 2 * cov6(3, 3) + mom.Y() ** 2 * cov6(4, 4) - 2 * mom.X() * mom.Y() * cov6(3, 4),
421 pt_resolution = np.divide(pt_variance, pt_estimate)
424 has_trackFitResult=
True,
425 d0_estimate=track_fit_result.getD0(),
426 d0_variance=track_fit_result.getCov()[0],
427 phi0_estimate=track_fit_result.getPhi() % (2.0 * math.pi),
428 phi0_variance=track_fit_result.getCov()[5],
429 omega_estimate=track_fit_result.getOmega(),
430 omega_variance=track_fit_result.getCov()[9],
431 z0_estimate=track_fit_result.getZ0(),
432 z0_variance=track_fit_result.getCov()[12],
433 tan_lambda_estimate=track_fit_result.getCotTheta(),
434 tan_lambda_variance=track_fit_result.getCov()[14],
437 x_variance=cov6(0, 0),
439 y_variance=cov6(1, 1),
441 z_variance=cov6(2, 2),
443 pt_estimate=pt_estimate,
444 pt_variance=pt_variance,
445 pt_resolution=pt_resolution,
447 track_charge=track_fit_result.getChargeSign(),
451 px_variance=cov6(3, 3),
453 py_variance=cov6(4, 4),
455 pz_variance=cov6(5, 5),
457 p_value=track_fit_result.getPValue(),
462 has_trackFitResult=
False,
471 tan_lambda_estimate=nan,
472 tan_lambda_variance=nan,
503 def get_reco_hit_information(reco_track, hit):
504 """Helper function for getting the correct reco hit info"""
505 for info
in getObjectList(hit.getRelationsFrom(
"RecoHitInformations")):
506 if info.getRelatedFrom(reco_track.getArrayName()) == reco_track:
512 def peel_subdetector_hit_efficiency(mc_reco_track, reco_track, key="{part_name}"):
513 def get_efficiency(detector_string):
514 if not reco_track
or not mc_reco_track:
515 hit_efficiency = float(
"nan")
517 mc_reco_hits = getObjectList(getattr(mc_reco_track,
"get{}HitList".format(detector_string.upper()))())
518 if len(mc_reco_hits) == 0:
519 hit_efficiency = float(
'nan')
523 for mc_reco_hit
in mc_reco_hits:
524 info = get_reco_hit_information(mc_reco_track, mc_reco_hit)
526 if info.getFoundByTrackFinder() == Belle2.RecoHitInformation.c_MCTrackFinderAuxiliaryHit:
529 mc_reco_hit_size += 1
531 for reco_hit
in getObjectList(getattr(reco_track,
"get{}HitList".format(detector_string.upper()))()):
532 if mc_reco_hit.getArrayIndex() == reco_hit.getArrayIndex():
536 if not mc_reco_hit_size:
537 hit_efficiency = float(
'nan')
539 hit_efficiency /= mc_reco_hit_size
541 return {
"{}_hit_efficiency".format(detector_string.lower()): hit_efficiency}
543 return dict(**get_efficiency(
"CDC"), **get_efficiency(
"SVD"), **get_efficiency(
"PXD"))
548 def peel_subdetector_hit_purity(reco_track, mc_reco_track, key="{part_name}"):
549 def get_efficiency(detector_string):
550 if not reco_track
or not mc_reco_track:
551 hit_purity = float(
"nan")
553 reco_hits = getObjectList(getattr(reco_track,
"get{}HitList".format(detector_string.upper()))())
554 reco_hit_size = len(reco_hits)
556 if reco_hit_size == 0:
557 hit_purity = float(
'nan')
560 for reco_hit
in reco_hits:
561 for mc_reco_hit
in getObjectList(getattr(mc_reco_track,
"get{}HitList".format(detector_string.upper()))()):
562 if mc_reco_hit.getArrayIndex() == reco_hit.getArrayIndex():
566 hit_purity /= reco_hit_size
568 return {
"{}_hit_purity".format(detector_string.lower()): hit_purity}
570 return dict(**get_efficiency(
"CDC"), **get_efficiency(
"SVD"), **get_efficiency(
"PXD"))
575 def peel_hit_information(hit_info, reco_track, key="{part_name}"):
576 nan = np.float(
"nan")
578 crops = dict(residual=nan,
583 tracking_detector=hit_info.getTrackingDetector(),
584 use_in_fit=hit_info.useInFit(),
589 if hit_info.useInFit()
and reco_track.hasTrackFitStatus():
590 track_point = reco_track.getCreatedTrackPoint(hit_info)
591 fitted_state = track_point.getFitterInfo()
594 res_state = fitted_state.getResidual().getState()
595 crops[
"residual"] = np.sqrt(res_state.Norm2Sqr())
596 if res_state.GetNoElements() == 2:
597 crops[
"residual_x"] = res_state[0]
598 crops[
"residual_y"] = res_state[1]
599 weights = fitted_state.getWeights()
600 crops[
'weight'] = max(weights)
601 except BaseException:
604 if hit_info.getTrackingDetector() == Belle2.RecoHitInformation.c_SVD:
605 hit = hit_info.getRelated(
"SVDClusters")
606 crops[
"hit_time"] = hit.getClsTime()
607 crops[
"layer_number"] = hit.getSensorID().getLayerNumber()
608 if hit_info.getTrackingDetector() == Belle2.RecoHitInformation.c_PXD:
609 hit = hit_info.getRelated(
"PXDClusters")
610 crops[
"layer_number"] = hit.getSensorID().getLayerNumber()
611 if hit_info.getTrackingDetector() == Belle2.RecoHitInformation.c_CDC:
612 hit = hit_info.getRelated(
"CDCHits")
613 crops[
"layer_number"] = hit.getICLayer()
620 def peel_module_statistics(modules=None, key="{part_name}"):
623 module_stats = dict()
625 for module
in basf2.statistics.modules:
626 if module.name
in modules:
627 module_stats[str(module.name) +
"_mem"] = module.memory_sum(basf2.statistics.EVENT)
628 module_stats[str(module.name) +
"_time"] = module.time_sum(basf2.statistics.EVENT)
629 module_stats[str(module.name) +
"_calls"] = module.calls(basf2.statistics.EVENT)
636 def get_helix_from_mc_particle(mc_particle):
637 position = mc_particle.getVertex()
638 momentum = mc_particle.getMomentum()
639 charge_sign = (-1
if mc_particle.getCharge() < 0
else 1)
642 seed_helix =
Belle2.Helix(position, momentum, charge_sign, b_field)
648 def get_seed_track_fit_result(reco_track):
649 position = reco_track.getPositionSeed()
650 momentum = reco_track.getMomentumSeed()
651 cartesian_covariance = reco_track.getSeedCovariance()
652 charge_sign = (-1
if reco_track.getChargeSeed() < 0
else 1)
654 particle_type = Belle2.Const.pion
655 p_value = float(
'nan')
665 cartesian_covariance,
675 return track_fit_result
680 def is_correct_rl_information(cdc_hit, reco_track, hit_lookup):
681 rl_info = reco_track.getRightLeftInformation[
"const Belle2::CDCHit"](cdc_hit)
682 truth_rl_info = hit_lookup.getRLInfo(cdc_hit)
684 if rl_info == Belle2.RecoHitInformation.c_right
and truth_rl_info == 1:
686 if rl_info == Belle2.RecoHitInformation.c_left
and truth_rl_info == 65535:
This class provides a set of constants for the framework.
a (simplified) python wrapper for StoreArray.
Values of the result of a track fit with a given particle hypothesis.
static void getField(const double *pos, double *field)
return the magnetic field at a given position.