24 getHelixFromMCParticle,
25 getSeedTrackFitResult,
28 calc_ndf_from_det_hit_ids
34 from ROOT
import Belle2
37 ROOT.gSystem.Load(
"libtracking")
42 contains all informations necessary for track filters to decide whether
43 track will be included into the processed list of tracks
44 This class is used for both providing information on pattern reco and
92 """Filter that always passes"""
95 """Pattern-reconstructed track always passes"""
99 """MC track always passes"""
105 """Module to collect matching information about the found particles and to
106 generate validation plots and figures of merit on the performance of track finding."""
115 output_file_name=None,
116 track_filter_object=AlwaysPassFilter(),
117 plot_name_postfix=
'',
118 plot_title_postfix=
'',
119 exclude_profile_mc_parameter=
'',
120 exclude_profile_pr_parameter=
'',
121 use_expert_folder=
True,
122 trackCandidatesColumnName=
"RecoTracks",
123 mcTrackCandidatesColumName=
"MCRecoTracks",
124 non_expert_parameters=[
'p_{t}']
128 super(TrackingValidationModule, self).
__init__()
142 +
'TrackingValidation.root'
170 if "DO_NOT_READ_BINNING" not in os.environ:
173 basf2.B2INFO(
"Will read binning from: " + self.
referenceFileNamereferenceFileName)
174 basf2.B2INFO(
"If this is not wanted set the environment variable DO_NOT_READ_BINNING or remove reference files.")
176 basf2.B2INFO(
"Will not read binning from reference files.")
179 """Receive signal at the start of event processing"""
266 """Looks at the individual pattern reconstructed tracks and store information about them"""
276 for trackCand
in trackCands:
277 is_matched = trackMatchLookUp.isAnyChargeMatchedPRRecoTrack(trackCand)
278 is_clone = trackMatchLookUp.isAnyChargeClonePRRecoTrack(trackCand)
280 pt_truth = float(
'nan')
281 omega_truth = float(
'nan')
282 tan_lambda_truth = float(
'nan')
283 d0_truth = float(
'nan')
284 z0_truth = float(
'nan')
287 if is_matched
or is_clone:
289 mcParticle = trackMatchLookUp.getRelatedMCParticle(trackCand)
290 mcHelix = getHelixFromMCParticle(mcParticle)
291 omega_truth = mcHelix.getOmega()
292 tan_lambda_truth = mcHelix.getTanLambda()
293 pt_truth = mcParticle.getMomentum().Rho()
294 d0_truth = mcHelix.getD0()
295 z0_truth = mcHelix.getZ0()
300 mcParticle=mcParticle, mcParticles=mcParticles)
304 trackMatchLookUp.getRelatedTrackFitResult(trackCand)
305 filterProperties.wasFitted = prTrackFitResult
is not None
306 filterProperties.fitResult = prTrackFitResult
308 prTrackFitResult = getSeedTrackFitResult(trackCand)
309 filterProperties.seedResult = prTrackFitResult
315 omega_estimate = float(
'nan')
316 omega_variance = float(
'nan')
317 tan_lambda_estimate = float(
'nan')
318 tan_lambda_variance = float(
'nan')
319 d0_estimate = float(
'nan')
320 d0_variance = float(
'nan')
321 z0_estimate = float(
'nan')
322 pt_estimate = float(
'nan')
324 momentum = float(
'nan')
329 seed_momentum = trackCand.getMomentumSeed()
331 seed_tan_lambda = np.divide(1.0, math.tan(seed_momentum.Theta()))
332 seed_phi = seed_momentum.Phi()
333 seed_pt = seed_momentum.Rho()
336 omega_estimate = prTrackFitResult.getOmega()
337 omega_variance = prTrackFitResult.getCov()[9]
339 tan_lambda_estimate = prTrackFitResult.getCotTheta()
340 tan_lambda_variance = prTrackFitResult.getCov()[14]
342 d0_estimate = prTrackFitResult.getD0()
343 d0_variance = prTrackFitResult.getCov()[0]
345 z0_estimate = prTrackFitResult.getZ0()
347 momentum = prTrackFitResult.getMomentum()
348 pt_estimate = momentum.Rho()
358 isMatchedOrIsClone = is_matched
or is_clone
362 self.
pr_fakespr_fakes.append(
not isMatchedOrIsClone)
383 """Looks at the individual Monte Carlo tracks and store information about them"""
393 multiplicity = mcTrackCands.getEntries()
394 multiplicity_primaries = multiplicity
400 for mcTrackCand
in mcTrackCands:
401 is_matched = trackMatchLookUp.isAnyChargeMatchedMCRecoTrack(mcTrackCand)
403 relatedPRtrackCand = trackMatchLookUp.getRelatedPRRecoTrack(mcTrackCand)
404 if relatedPRtrackCand:
405 is_chargeMatched = trackMatchLookUp.isChargeMatched(relatedPRtrackCand)
407 is_chargeMatched =
False
410 if mcTrackCand.getChargeSeed() > 0:
415 hit_efficiency = trackMatchLookUp.getRelatedEfficiency(mcTrackCand)
416 if math.isnan(hit_efficiency):
419 mcParticle = trackMatchLookUp.getRelatedMCParticle(mcTrackCand)
420 mcHelix = getHelixFromMCParticle(mcParticle)
425 mcParticles=mcParticles)
430 momentum = mcParticle.getMomentum()
432 tan_lambda = np.divide(1.0, math.tan(momentum.Theta()))
434 det_hit_ids = get_det_hit_ids(mcTrackCand)
435 ndf = calc_ndf_from_det_hit_ids(det_hit_ids)
439 self.
mc_primariesmc_primaries.append(is_primary(mcParticle))
441 self.
mc_ptsmc_pts.append(pt)
442 self.
mc_d0smc_d0s.append(d0)
445 self.
mc_phimc_phi.append(momentum.Phi())
446 self.
mc_ndfmc_ndf.append(ndf)
447 if not is_primary(mcParticle):
448 multiplicity_primaries -= 1
450 charge_asymmetry = (n_matched_plus - n_matched_minus)/(n_matched_plus +
451 n_matched_minus)
if (n_matched_plus + n_matched_minus) != 0
else 0
452 for mcTrackCand
in mcTrackCands:
453 if is_primary(mcParticle):
461 """Receive signal at the end of event processing"""
471 if len(mc_matched_primaries) > 0
and sum(mc_matched_primaries) > 0:
472 charge_efficiency = np.average(self.
mc_charge_matchesmc_charge_matches, weights=mc_matched_primaries)
473 hit_efficiency = np.average(self.
mc_hit_efficienciesmc_hit_efficiencies, weights=mc_matched_primaries)
475 charge_efficiency = float(
'nan')
476 hit_efficiency = float(
'nan')
482 clone_rate = 1.0 - np.average(self.
pr_matchespr_matches,
485 clone_rate = float(
'nan')
489 figures_of_merit[
'finding_charge_efficiency'] = finding_charge_efficiency
490 figures_of_merit[
'finding_efficiency'] = finding_efficiency
491 figures_of_merit[
'charge_efficiency'] = charge_efficiency
492 figures_of_merit[
'charge_asymmetry'] = charge_asymmetry
493 figures_of_merit[
'fake_rate'] = fake_rate
494 figures_of_merit[
'clone_rate'] = clone_rate
495 figures_of_merit[
'hit_efficiency'] = hit_efficiency
497 figures_of_merit.description = \
499 finding_efficiency - the ratio of matched Monte Carlo tracks to all primary Monte Carlo tracks <br/>
500 charge_efficiency - the ratio of matched Monte Carlo tracks with correct charge to matched primary Monte Carlo tracks <br/>
501 finding_charge_efficiency - the ratio of matched Monte Carlo tracks with correct charge to all primary Monte Carlo tracks <br/>
502 fake_rate - ratio of pattern recognition tracks that are not related to a particle
503 (background, ghost) to all pattern recognition tracks <br/>
504 clone_rate - ratio of clones divided the number of tracks that are related to a particle (clones and matches) <br/>
507 figures_of_merit.check =
'Compare for degradations with respect to the reference'
508 figures_of_merit.contact = contact
509 print(figures_of_merit)
513 validation_plots = []
519 'finding efficiency',
523 validation_plots.extend(plots)
529 print(
'fake list: ' + str(self.
pr_fakespr_fakes.count(1)))
533 validation_plots.extend(plots)
538 'charge efficiency for matched primary tracks',
539 weights=mc_matched_primaries)
541 validation_plots.extend(plots)
546 'finding and charge efficiency for primary tracks',
549 validation_plots.extend(plots)
554 'charge asymmetry for primary tracks',
558 validation_plots.extend(plots)
563 'hit efficiency with matched tracks',
564 weights=mc_matched_primaries)
566 validation_plots.extend(plots)
571 all_but_diagonal_plots = list(PullAnalysis.default_which_plots)
572 all_but_diagonal_plots.remove(
"diag_profile")
573 all_but_diagonal_plots.remove(
"diag_scatter")
577 plot_name_prefix +=
'_seed'
584 curvature_pull_analysis =
PullAnalysis(
'#omega', unit=
'1/cm',
585 plot_name_prefix=plot_name_prefix +
'_omega',
589 curvature_pull_analysis.analyse(pr_omega_truths,
592 which_plots=all_but_diagonal_plots)
594 curvature_pull_analysis.contact = contact
595 pull_analyses.append(curvature_pull_analysis)
603 plot_name_prefix=plot_name_prefix +
'_tan_lambda',
607 curvature_pull_analysis.analyse(pr_tan_lambda_truths,
608 pr_tan_lambda_estimates,
609 pr_tan_lambda_variances,
610 which_plots=all_but_diagonal_plots)
612 curvature_pull_analysis.contact = contact
613 pull_analyses.append(curvature_pull_analysis)
617 plot_name_prefix=plot_name_prefix +
'_d0',
621 curvature_pull_analysis.analyse(np.array(self.
pr_d0_truthspr_d0_truths),
624 which_plots=all_but_diagonal_plots)
626 curvature_pull_analysis.contact = contact
627 pull_analyses.append(curvature_pull_analysis)
636 plot_name_prefix=plot_name_prefix +
'_d0_res',
639 d0_resolution_analysis.analyse(np.array(self.
pr_bining_ptpr_bining_pt),
642 d0_resolution_analysis.contact = contact
643 pull_analyses.append(d0_resolution_analysis)
649 plot_name_prefix=plot_name_prefix +
'_z0_res',
652 z0_resolution_analysis.analyse(np.array(self.
pr_bining_ptpr_bining_pt),
655 z0_resolution_analysis.contact = contact
656 pull_analyses.append(z0_resolution_analysis)
662 plot_name_prefix=plot_name_prefix +
'_omega_res',
665 omega_resolution_analysis.analyse(np.array(self.
pr_bining_ptpr_bining_pt),
668 omega_resolution_analysis.contact = contact
669 pull_analyses.append(omega_resolution_analysis)
675 plot_name_prefix=plot_name_prefix +
'_pt_res',
678 pt_resolution_analysis.analyse(np.array(self.
pr_bining_ptpr_bining_pt),
681 pt_resolution_analysis.contact = contact
682 pull_analyses.append(pt_resolution_analysis)
688 output_tfile = ROOT.TFile(self.
output_file_nameoutput_file_name,
'recreate')
693 ROOT.gStyle.SetOptFit(opt_fit)
695 figures_of_merit.write()
697 for validation_plot
in validation_plots:
698 validation_plot.write()
701 expert_tdirectory = output_tfile.mkdir(
'expert',
'Expert')
702 expert_tdirectory.cd()
703 ROOT.gStyle.SetOptFit(opt_fit)
705 for pull_analysis
in pull_analyses:
706 pull_analysis.write()
727 """Create profile histograms by MC-track parameters"""
730 new_parameter_names = [item
for item
in parameter_names
if item
734 profile_parameters = {
735 'd_{0}': self.
mc_d0smc_d0s,
736 'p_{t}': self.
mc_ptsmc_pts,
738 '#phi': self.
mc_phimc_phi,
751 is_asymmetry=is_asymmetry
759 parameter_names=['Seed_p_t', 'Seed tan
762 """Create profile histograms by PR-track parameters"""
765 new_parameter_names = [item
for item
in parameter_names
if item
769 profile_parameters = {
'Seed p_{t}': self.
pr_seed_ptpr_seed_pt,
793 """Create profile histograms for generic parameters"""
797 validation_plots = []
798 plot_name_prefix = self.
validation_namevalidation_name +
'_' + root_save_name(quantity_name) \
804 histogram.hist(xs, weights=weights)
806 histogram.xlabel = quantity_name
807 histogram.description =
'Not a serious plot yet.'
809 histogram.contact = contact
812 validation_plots.append(histogram)
814 for (parameter_name, parameter_values)
in list(profile_parameters.items()):
815 if parameter_name
in parameter_names \
816 or root_save_name(parameter_name)
in parameter_names:
820 parameter_root_name = root_save_name(parameter_name)
824 if 'tan_lambda' in parameter_root_name:
832 elif 'ndf' in parameter_root_name:
834 upper_bound = min(200, np.max(parameter_values))
835 elif 'p_t' in parameter_root_name:
842 elif 'd_0' in parameter_root_name:
854 profile_plot_name = plot_name_prefix +
'_by_' \
855 + root_save_name(parameter_name)
857 profile_plot.profile(parameter_values,
860 outlier_z_score=10.0,
861 lower_bound=lower_bound,
862 upper_bound=upper_bound,
865 is_asymmetry=is_asymmetry)
867 profile_plot.xlabel = compose_axis_label(parameter_name)
868 profile_plot.ylabel = compose_axis_label(quantity_name, unit)
869 profile_plot.title = quantity_name +
' by ' + parameter_name \
872 profile_plot.description = \
873 'Dependence of %s of the track over the true %s' \
874 % (quantity_name, parameter_name)
875 profile_plot.check =
'Variations should be low'
876 profile_plot.contact = contact
877 validation_plots.append(profile_plot)
879 return validation_plots
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
A (simplified) python wrapper for StoreArray.
Class to provide convenient methods to look up matching information between pattern recognition and M...
def doesPrPass(self, filterProperties)
def doesMcPass(self, filterProperties)
mcParticle
cached value of the MC particle
wasFitted
cached value of the fitted flag
def __init__(self, trackCand=None, mcParticle=None, mcParticles=None, wasFitted=False, fitResult=None, seedResult=None)
trackCand
cached value of the track candidate
seedResult
cached value of the seed result
fitResult
cached value of the fit result
mcParticles
cached value of the MCParticles StoreArray
mc_d0s
list of MC-track d0 values
pr_omega_variances
list of PR-track seed omega-variance values
exclude_profile_mc_parameter
cached list of perigee parameters excluded from MC side plots
track_filter_object
cached value of the track-filter object
pr_seed_tan_lambdas
list of PR-track seed tan(lambda) values
pr_tan_lambda_estimates
list of PR-track seed tan(lambda)-estimate values
pr_fakes
list of PR-track fakes
contact
cached value of the contact person name
fit
cached value of the track fit
pr_matches
list of PR-track matches
pr_bining_pt
list of PR-track binning values
def examine_pr_tracks(self)
pr_tan_lambda_variances
list of PR-track seed tan(lambda)-variance values
pr_pt_estimates
list of PR-track seed pt-estimate values
trackCandidatesColumnName
cached name of the RecoTracks StoreArray
pr_pt_truths
list of PR-track seed pt-truth values
pulls
cached values of the track-fit pulls
mc_ndf
list of MC-track number of degrees of freedom
pr_omega_truths
list of PR-track seed omega-truth values
pr_seed_phi
list of PR-track seed phi values
output_file_name
cached value of the output ROOT TFile
plot_name_postfix
cached value of the suffix appended to the plot names
trackMatchLookUp
Track-match object that examines relation information from MCMatcherTracksModule.
pr_omega_estimates
list of PR-track seed omega-estimate values
plot_title_postfix
cached value of the suffix appended to the plot titles
pr_z0_estimates
list of PR-track seed z0-estimate values
pr_d0_variances
list of PR-track seed d0-variance values
def profiles_by_pr_parameters(self, xs, quantity_name, unit=None, parameter_names=['Seed_p_t', 'Seed tan #lambda', 'Seed #phi'], make_hist=True)
mc_pts
list of MC-track pt values
resolution_pt_binning
default binning used for resolution plots over pt
mc_multiplicities
list of MC-track multiplicities
mc_matches
list of MC-track matches
def examine_mc_tracks(self)
pr_clones_and_matches
Use deques in favour of lists to prevent repeated memory allocation of cost O(n)
mc_primaries
list of MC-track primaries
non_expert_parameters
list of parameters that determines which plots (all with corresponding x-axis) are marked as shifter ...
def __init__(self, name, contact, fit=False, pulls=False, resolution=False, output_file_name=None, track_filter_object=AlwaysPassFilter(), plot_name_postfix='', plot_title_postfix='', exclude_profile_mc_parameter='', exclude_profile_pr_parameter='', use_expert_folder=True, trackCandidatesColumnName="RecoTracks", mcTrackCandidatesColumName="MCRecoTracks", non_expert_parameters=['p_{t}'])
resolution
cached value of the resolution
referenceFileName
If this variable is set the code will open the file with same name as the file created here and will ...
use_expert_folder
cached flag to use the "expert" folder for the pull and residual plots
def profiles_by_mc_parameters(self, xs, quantity_name, unit=None, parameter_names=['d_0', 'p_t', 'tan_lambda', 'multiplicity', 'phi', 'ndf',], make_hist=True, weights=None, is_asymmetry=False)
pr_seed_pt
list of PR-track seed pt values
pr_z0_truths
list of PR-track seed z0-truth values
mc_phi
direction of the track in phi
mcTrackCandidatesColumnName
cached name of the MCRecoTracks StoreArray
pr_tan_lambda_truths
list of PR-track seed tan(lambda)-truth values
pr_d0_estimates
list of PR-track seed d0-estimate values
validation_name
cached value of the tracking-validation name
mc_charge_asymmetry_weights
list of MC-track matches charge asymmetry weights
mc_tan_lambdas
list of MC-track tan(lambda) values
mc_hit_efficiencies
list of MC-track hit efficiencies
pr_d0_truths
list of PR-track seed d0-truth values
mc_charge_matches
list of MC-track matches, including matched charge
mc_charge_asymmetry
list of MC-track matches charge asymmetry
exclude_profile_pr_parameter
cached list of perigee parameters excluded from PR side plots
def profiles_by_parameters_base(self, xs, quantity_name, parameter_names, profile_parameters, unit, make_hist, weights=None, is_asymmetry=False)