Belle II Software development
RecoTrackQEValidationPlotsTask Class Reference
Inheritance diagram for RecoTrackQEValidationPlotsTask:
PlotsFromHarvestingValidationBaseTask

Public Member Functions

 harvesting_validation_task_instance (self)
 
 output_pdf_file_basename (self)
 Name of the output PDF file containing the validation plots.
 
 requires (self)
 
 output (self)
 
 process (self)
 

Public Attributes

 output_pdf_file_basename
 Name of the output PDF file containing the validation plots.
 

Static Public Attributes

 n_events_testing = b2luigi.IntParameter()
 Number of events to generate for the test data set.
 
 n_events_training = b2luigi.IntParameter()
 Number of events to generate for the training data set.
 
 experiment_number = b2luigi.IntParameter()
 Experiment number of the conditions database, e.g.
 
 process_type
 Define which kind of process shall be used.
 
 exclude_variables
 List of collected variables to not use in the training of the QE MVA classifier.
 
 fast_bdt_option
 Hyperparameter option of the FastBDT algorithm.
 
 primaries_only
 Whether to normalize the track finding efficiencies to primary particles only.
 
str cdc_training_target = "truth"
 Feature/variable to use as truth label for the CDC track quality estimator.
 

Detailed Description

Create a PDF file with validation plots for the reco MVA track quality
estimator produced from the ROOT ntuples produced by a reco track QE
harvesting validation task

Definition at line 2497 of file combined_quality_estimator_teacher.py.

Member Function Documentation

◆ harvesting_validation_task_instance()

harvesting_validation_task_instance ( self)
Harvesting validation task to require, which produces the ROOT files
with variables to produce the final MVA track QE validation plots.

Reimplemented from PlotsFromHarvestingValidationBaseTask.

Definition at line 2507 of file combined_quality_estimator_teacher.py.

2507 def harvesting_validation_task_instance(self):
2508 """
2509 Harvesting validation task to require, which produces the ROOT files
2510 with variables to produce the final MVA track QE validation plots.
2511 """
2512 return RecoTrackQEHarvestingValidationTask(
2513 n_events_testing=self.n_events_testing,
2514 n_events_training=self.n_events_training,
2515 process_type=self.process_type,
2516 experiment_number=self.experiment_number,
2517 cdc_training_target=self.cdc_training_target,
2518 exclude_variables=self.exclude_variables,
2519 num_processes=MasterTask.num_processes,
2520 fast_bdt_option=self.fast_bdt_option,
2521 )
2522
2523

◆ output()

output ( self)
inherited
Generate list of output files that the task should produce.
The task is considered finished if and only if the outputs all exist.

Definition at line 2226 of file combined_quality_estimator_teacher.py.

2226 def output(self):
2227 """
2228 Generate list of output files that the task should produce.
2229 The task is considered finished if and only if the outputs all exist.
2230 """
2231
2232 yield self.add_to_output(self.output_pdf_file_basename)
2233

◆ output_pdf_file_basename()

output_pdf_file_basename ( self)
inherited

Name of the output PDF file containing the validation plots.

Name of the output PDF file containing the validation plots

Definition at line 2213 of file combined_quality_estimator_teacher.py.

2213 def output_pdf_file_basename(self):
2214 """
2215 Name of the output PDF file containing the validation plots
2216 """
2217 validation_harvest_basename = self.harvesting_validation_task_instance.validation_output_file_name
2218 return validation_harvest_basename.replace(".root", "_plots.pdf")
2219

◆ process()

process ( self)
inherited
Use basf2_mva teacher to create MVA weightfile from collected training
data variables.

Main process that is dispatched by the ``run`` method that is inherited
from ``Basf2Task``.

Definition at line 2235 of file combined_quality_estimator_teacher.py.

2235 def process(self):
2236 """
2237 Use basf2_mva teacher to create MVA weightfile from collected training
2238 data variables.
2239
2240 Main process that is dispatched by the ``run`` method that is inherited
2241 from ``Basf2Task``.
2242 """
2243 # get the validation "harvest", which is the ROOT file with ntuples for validation
2244 validation_harvest_basename = self.harvesting_validation_task_instance.validation_output_file_name
2245 validation_harvest_path = self.get_input_file_names(validation_harvest_basename)[0]
2246 print('\nThe validation harvest path is:', validation_harvest_path, '\n')
2247
2248 # Load "harvested" validation data from root files into dataframes (requires enough memory to hold data)
2249 pr_columns = [ # Restrict memory usage by only reading in columns that are used in the steering file
2250 'is_fake', 'is_clone', 'is_matched', 'quality_indicator',
2251 'experiment_number', 'run_number', 'event_number', 'pr_store_array_number',
2252 'pt_estimate', 'z0_estimate', 'd0_estimate', 'tan_lambda_estimate',
2253 'phi0_estimate', 'pt_truth', 'z0_truth', 'd0_truth', 'tan_lambda_truth',
2254 'phi0_truth',
2255 ]
2256 # In ``pr_df`` each row corresponds to a track from Pattern Recognition
2257 pr_df = uproot.open(validation_harvest_path)['pr_tree/pr_tree'].arrays(pr_columns, library='pd')
2258 mc_columns = [ # restrict mc_df to these columns
2259 'experiment_number',
2260 'run_number',
2261 'event_number',
2262 'pr_store_array_number',
2263 'is_missing',
2264 'is_primary',
2265 ]
2266 # In ``mc_df`` each row corresponds to an MC track
2267 mc_df = uproot.open(validation_harvest_path)['mc_tree/mc_tree'].arrays(mc_columns, library='pd')
2268 if self.primaries_only:
2269 mc_df = mc_df[mc_df.is_primary.eq(True)]
2270
2271 # Define QI thresholds for the FOM plots and the ROC curves
2272 qi_cuts = np.linspace(0., 1, 20, endpoint=False)
2273 # # Add more points at the very end between the previous maximum and 1
2274 # qi_cuts = np.append(qi_cuts, np.linspace(np.max(qi_cuts), 1, 20, endpoint=False))
2275
2276 # Create plots and append them to single output pdf
2277
2278 output_pdf_file_path = self.get_output_file_name(self.output_pdf_file_basename)
2279 with PdfPages(output_pdf_file_path, keep_empty=False) as pdf:
2280
2281 # Add a title page to validation plot PDF with some metadata
2282 # Remember that most metadata is in the xml file of the weightfile
2283 # and in the b2luigi directory structure
2284 titlepage_fig, titlepage_ax = plt.subplots()
2285 titlepage_ax.axis("off")
2286 title = f"Quality Estimator validation plots from {self.__class__.__name__}"
2287 titlepage_ax.set_title(title)
2288 teacher_task = self.harvesting_validation_task_instance.teacher_task
2289 weightfile_identifier = teacher_task.get_weightfile_identifier(
2290 teacher_task, fast_bdt_option=self.fast_bdt_option) + '.xml'
2291 meta_data = {
2292 "Date": datetime.today().strftime("%Y-%m-%d %H:%M"),
2293 "Created by steering file": os.path.realpath(__file__),
2294 "Created from data in": validation_harvest_path,
2295 "Background directory": MasterTask.bkgfiles_by_exp[self.experiment_number],
2296 "weight file": weightfile_identifier,
2297 }
2298 if hasattr(self, 'exclude_variables'):
2299 meta_data["Excluded variables"] = ", ".join(self.exclude_variables)
2300 meta_data_string = (format_dictionary(meta_data) +
2301 "\n\n(For all MVA training parameters look into the produced weight file)")
2302 luigi_params = get_serialized_parameters(self)
2303 luigi_param_string = (f"\n\nb2luigi parameters for {self.__class__.__name__}\n" +
2304 format_dictionary(luigi_params))
2305 title_page_text = meta_data_string + luigi_param_string
2306 titlepage_ax.text(0, 1, title_page_text, ha="left", va="top", wrap=True, fontsize=8)
2307 pdf.savefig(titlepage_fig)
2308 plt.close(titlepage_fig)
2309
2310 fake_rates = get_uncertain_means_for_qi_cuts(pr_df, "is_fake", qi_cuts)
2311 fake_fig, fake_ax = plt.subplots()
2312 fake_ax.set_title("Fake rate")
2313 plot_with_errobands(fake_rates, ax=fake_ax)
2314 fake_ax.set_ylabel("fake rate")
2315 fake_ax.set_xlabel("quality indicator requirement")
2316 pdf.savefig(fake_fig, bbox_inches="tight")
2317 plt.close(fake_fig)
2318
2319 # Plot clone rates
2320 clone_rates = get_uncertain_means_for_qi_cuts(pr_df, "is_clone", qi_cuts)
2321 clone_fig, clone_ax = plt.subplots()
2322 clone_ax.set_title("Clone rate")
2323 plot_with_errobands(clone_rates, ax=clone_ax)
2324 clone_ax.set_ylabel("clone rate")
2325 clone_ax.set_xlabel("quality indicator requirement")
2326 pdf.savefig(clone_fig, bbox_inches="tight")
2327 plt.close(clone_fig)
2328
2329 # Plot finding efficiency
2330
2331 # The Quality Indicator is only available in pr_tree and thus the
2332 # PR-track dataframe. To get the QI of the related PR track for an MC
2333 # track, merge the PR dataframe into the MC dataframe
2334 pr_track_identifiers = ['experiment_number', 'run_number', 'event_number', 'pr_store_array_number']
2335 mc_df = upd.merge(
2336 left=mc_df, right=pr_df[pr_track_identifiers + ['quality_indicator']],
2337 how='left',
2338 on=pr_track_identifiers
2339 )
2340
2341 missing_fractions = (
2342 _my_uncertain_mean(mc_df[
2343 mc_df.quality_indicator.isnull() | (mc_df.quality_indicator > qi_cut)]['is_missing'])
2344 for qi_cut in qi_cuts
2345 )
2346
2347 findeff_fig, findeff_ax = plt.subplots()
2348 findeff_ax.set_title("Finding efficiency")
2349 finding_efficiencies = 1.0 - upd.Series(data=missing_fractions, index=qi_cuts)
2350 plot_with_errobands(finding_efficiencies, ax=findeff_ax)
2351 findeff_ax.set_ylabel("finding efficiency")
2352 findeff_ax.set_xlabel("quality indicator requirement")
2353 pdf.savefig(findeff_fig, bbox_inches="tight")
2354 plt.close(findeff_fig)
2355
2356 # Plot ROC curves
2357
2358 # Fake rate vs. finding efficiency ROC curve
2359 fake_roc_fig, fake_roc_ax = plt.subplots()
2360 fake_roc_ax.set_title("Fake rate vs. finding efficiency ROC curve")
2361 fake_roc_ax.errorbar(x=finding_efficiencies.nominal_value, y=fake_rates.nominal_value,
2362 xerr=finding_efficiencies.std_dev, yerr=fake_rates.std_dev, elinewidth=0.8)
2363 fake_roc_ax.set_xlabel('finding efficiency')
2364 fake_roc_ax.set_ylabel('fake rate')
2365 pdf.savefig(fake_roc_fig, bbox_inches="tight")
2366 plt.close(fake_roc_fig)
2367
2368 # Clone rate vs. finding efficiency ROC curve
2369 clone_roc_fig, clone_roc_ax = plt.subplots()
2370 clone_roc_ax.set_title("Clone rate vs. finding efficiency ROC curve")
2371 clone_roc_ax.errorbar(x=finding_efficiencies.nominal_value, y=clone_rates.nominal_value,
2372 xerr=finding_efficiencies.std_dev, yerr=clone_rates.std_dev, elinewidth=0.8)
2373 clone_roc_ax.set_xlabel('finding efficiency')
2374 clone_roc_ax.set_ylabel('clone rate')
2375 pdf.savefig(clone_roc_fig, bbox_inches="tight")
2376 plt.close(clone_roc_fig)
2377
2378 # Plot kinematic distributions
2379
2380 # use fewer qi cuts as each cut will be it's own subplot now and not a point
2381 kinematic_qi_cuts = [0, 0.5, 0.9]
2382
2383 # Define kinematic parameters which we want to histogram and define
2384 # dictionaries relating them to latex labels, units and binnings
2385 params = ['d0', 'z0', 'pt', 'tan_lambda', 'phi0']
2386 label_by_param = {
2387 "pt": "$p_T$",
2388 "z0": "$z_0$",
2389 "d0": "$d_0$",
2390 "tan_lambda": r"$\tan{\lambda}$",
2391 "phi0": r"$\phi_0$"
2392 }
2393 unit_by_param = {
2394 "pt": "GeV",
2395 "z0": "cm",
2396 "d0": "cm",
2397 "tan_lambda": "rad",
2398 "phi0": "rad"
2399 }
2400 n_kinematic_bins = 75 # number of bins per kinematic variable
2401 bins_by_param = {
2402 "pt": np.linspace(0, np.percentile(pr_df['pt_truth'].dropna(), 95), n_kinematic_bins),
2403 "z0": np.linspace(-0.1, 0.1, n_kinematic_bins),
2404 "d0": np.linspace(0, 0.01, n_kinematic_bins),
2405 "tan_lambda": np.linspace(-2, 3, n_kinematic_bins),
2406 "phi0": np.linspace(0, 2 * np.pi, n_kinematic_bins)
2407 }
2408
2409 # Iterate over each parameter and for each make stacked histograms for different QI cuts
2410 kinematic_qi_cuts = [0, 0.5, 0.8]
2411 blue, yellow, green = plt.get_cmap("tab10").colors[0:3]
2412 for param in params:
2413 fig, axarr = plt.subplots(ncols=len(kinematic_qi_cuts), sharey=True, sharex=True, figsize=(14, 6))
2414 fig.suptitle(f"{label_by_param[param]} distributions")
2415 for i, qi in enumerate(kinematic_qi_cuts):
2416 ax = axarr[i]
2417 ax.set_title(f"QI > {qi}")
2418 incut = pr_df[(pr_df['quality_indicator'] > qi)]
2419 incut_matched = incut[incut.is_matched.eq(True)]
2420 incut_clones = incut[incut.is_clone.eq(True)]
2421 incut_fake = incut[incut.is_fake.eq(True)]
2422
2423 # if any series is empty, break out of loop and don't draw try to draw a stacked histogram
2424 if any(series.empty for series in (incut, incut_matched, incut_clones, incut_fake)):
2425 ax.text(0.5, 0.5, "Not enough data in bin", ha="center", va="center", transform=ax.transAxes)
2426 continue
2427
2428 bins = bins_by_param[param]
2429 stacked_histogram_series_tuple = (
2430 incut_matched[f'{param}_estimate'],
2431 incut_clones[f'{param}_estimate'],
2432 incut_fake[f'{param}_estimate'],
2433 )
2434 histvals, _, _ = ax.hist(stacked_histogram_series_tuple,
2435 stacked=True,
2436 bins=bins, range=(bins.min(), bins.max()),
2437 color=(blue, green, yellow),
2438 label=("matched", "clones", "fakes"))
2439 ax.set_xlabel(f'{label_by_param[param]} estimate / ({unit_by_param[param]})')
2440 ax.set_ylabel('# tracks')
2441 axarr[0].legend(loc="upper center", bbox_to_anchor=(0, -0.15))
2442 pdf.savefig(fig, bbox_inches="tight")
2443 plt.close(fig)
2444
2445

◆ requires()

requires ( self)
inherited
Generate list of luigi Tasks that this Task depends on.

Definition at line 2220 of file combined_quality_estimator_teacher.py.

2220 def requires(self):
2221 """
2222 Generate list of luigi Tasks that this Task depends on.
2223 """
2224 yield self.harvesting_validation_task_instance
2225

Member Data Documentation

◆ cdc_training_target

str cdc_training_target = "truth"
staticinherited

Feature/variable to use as truth label for the CDC track quality estimator.

Definition at line 2201 of file combined_quality_estimator_teacher.py.

◆ exclude_variables

exclude_variables
staticinherited
Initial value:
= b2luigi.ListParameter(
)

List of collected variables to not use in the training of the QE MVA classifier.

In addition to variables containing the "truth" substring, which are excluded by default.

Definition at line 2183 of file combined_quality_estimator_teacher.py.

◆ experiment_number

experiment_number = b2luigi.IntParameter()
staticinherited

Experiment number of the conditions database, e.g.

defines simulation geometry

Definition at line 2172 of file combined_quality_estimator_teacher.py.

◆ fast_bdt_option

fast_bdt_option
staticinherited
Initial value:
= b2luigi.ListParameter(
)

Hyperparameter option of the FastBDT algorithm.

default are the FastBDT default values.

Definition at line 2189 of file combined_quality_estimator_teacher.py.

◆ n_events_testing

n_events_testing = b2luigi.IntParameter()
staticinherited

Number of events to generate for the test data set.

Definition at line 2168 of file combined_quality_estimator_teacher.py.

◆ n_events_training

n_events_training = b2luigi.IntParameter()
staticinherited

Number of events to generate for the training data set.

Definition at line 2170 of file combined_quality_estimator_teacher.py.

◆ output_pdf_file_basename

output_pdf_file_basename
inherited

Name of the output PDF file containing the validation plots.

Definition at line 2232 of file combined_quality_estimator_teacher.py.

◆ primaries_only

primaries_only
staticinherited
Initial value:
= b2luigi.BoolParameter(
)

Whether to normalize the track finding efficiencies to primary particles only.

Definition at line 2195 of file combined_quality_estimator_teacher.py.

◆ process_type

process_type
staticinherited
Initial value:
= b2luigi.Parameter(
)

Define which kind of process shall be used.

Decide between simulating BBBAR or BHABHA, MUMU, YY, DDBAR, UUBAR, SSBAR, CCBAR, reconstructing DATA or already simulated files (USESIMBB/EE) or running on existing reconstructed files (USERECBB/EE)

Definition at line 2176 of file combined_quality_estimator_teacher.py.


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