Source code for modeSelector

#!/usr/bin/env python3
##########################################################################
# basf2 (Belle II Analysis Software Framework)                           #
# Author: The Belle II Collaboration                                     #
#                                                                        #
# See git log for contributors and copyright holders.                    #
# This file is licensed under LGPL-3.0, see LICENSE.md.                  #
##########################################################################

"""
ModeSelector - Event-level B meson classification using neural networks.

The FEI assigns a signal probability (sigProb) to each B candidate independently.
ModeSelector uses the full set of FEI B candidates with sigProb > 0.001 simultaneously
to classify the event and produce a refined score (BplusScore).

Main components:

- modeSelector(): main function to add ModeSelector to a basf2 path
- addDstarVeto(): D* veto reconstruction (called automatically by modeSelector)

See ``analysis/doc/ModeSelector.rst`` for usage instructions and
``analysis/scripts/modeSelector/README.md`` for implementation details.
"""

from modeSelector import config
from modeSelector.dstarVeto import addDstarVeto
from modeSelector.generatedDecayWeights import (GeneratedDecayWeightModule,
                                                addGeneratedDecayWeights)
from modeSelector.ModeSelectorModule import ModeSelectorModule

__all__ = [
    'config',
    'addGeneratedDecayWeights',
    'modeSelector',
    'addDstarVeto',
    'GeneratedDecayWeightModule',
    'ModeSelectorModule',
]


[docs] def modeSelector( bp_list, b0_list, payload_cat_model=None, payload_main_model=None, output_variable='BplusScore', cat_model_path=None, main_model_path=None, addDstarVetoReco=True, training_mode=False, skip_nn_evaluation=False, store_fei_calib_weight=False, debug=False, debug_max_events=10, path=None ): """ Add ModeSelector neural network evaluation to a basf2 path. This function applies a two-stage neural network to FEI B meson candidates to compute an improved signal probability score. The network considers information from all B candidates in the event. The main output score is stored in EventExtraInfo using output_variable. Auxiliary category and per-candidate mode outputs are stored with the fixed modeSelector_* names. Parameters: bp_list (str): B+ meson particle list name to process. Example: 'B+:feiHadronic' b0_list (str): B0 meson particle list name to process. Example: 'B0:feiHadronic' payload_cat_model (str): Conditions DB payload name for the category model. Used only when cat_model_path is None. None (default) uses the name derived from the contract version this release implements, and the training is chosen by the performance globaltag. Passing a name always emits a warning that the default payload is not used. A payload built for an older contract version runs with that contract's behaviour if the version is in config.SUPPORTED_CONTRACT_VERSIONS (with a warning); a newer or unsupported version is fatal. payload_main_model (str): Conditions DB payload name for the main model. Used only when main_model_path is None. Same rules as payload_cat_model. output_variable (str): Name of the ExtraInfo variable for the output score. Default: 'BplusScore' cat_model_path (str): Path to the basf2 MVA weightfile for the category network, as produced by convert_to_onnx.py (a .root file, not a raw .onnx file). If None, loads from conditions database. main_model_path (str): Path to the basf2 MVA weightfile for the main network, as produced by convert_to_onnx.py (a .root file, not a raw .onnx file). If None, loads from conditions database. skip_nn_evaluation (bool): If True, skip loading and evaluating the neural networks and fill deterministic placeholder outputs instead. Intended for debugging or timing studies and emits a warning at module initialization. training_mode (bool): If True, skip NN inference and instead expose per-event features and MC truth as EventExtraInfo/ExtraInfo (``modeSelector_feat_XXXX``, ``modeSelector_tr_*``, ``modeSelector_trainSigInputId``) for a variablesToNtuple call in the steering script to dump. See ``analysis/examples/modeSelector/produceTrainingInputs.py``. Default: False. addDstarVetoReco (bool): Whether to add D* veto reconstruction before the NN. Default: True debug (bool): If True, print the feature vector and network outputs for the first few events. Intended for comparing against a reference implementation. Default: False debug_max_events (int): Number of events to print when debug is True. Default: 10 store_fei_calib_weight (bool): If True, compute and store modeSelector_feiCalibWeight in EventExtraInfo using the reco path (truth-compatible tag PDG and DeltaP < DELTA_P_THRESH). Returns NaN when reco conditions are not met. Requires mostcommonBTagPDG and mostcommonBTagDeltaP to be defined. Meaningful only on MC. Default: False. path (basf2.Path): The basf2 path to add the module to. Notes: Candidate-level ``ExtraInfo`` (predicted sector only): - ``modeSelector_eqSigProb``: main-network probability for the candidate's specific decay mode. - ``modeSelector_rank``: sector-local rank. Predicted sector ranked by ``modeSelector_eqSigProb``; non-predicted sector ranked by ``sigProb``. Event-level ``EventExtraInfo``: - ``BplusScore`` (or the name given by ``output_variable``): signed score, positive for B+ prediction, negative for B0. - ``modeSelector_catB0``, ``modeSelector_catBp``, ``modeSelector_catCont``: category network probabilities. The D* veto reconstruction is added automatically (``addDstarVetoReco=True``). Pass ``addDstarVetoReco=False`` to skip it if already added separately. """ import basf2 as b2 if path is None: b2.B2FATAL("Path is required for modeSelector") if not isinstance(bp_list, str) or not bp_list: b2.B2FATAL("ModeSelector: bp_list must be a non-empty string") if not isinstance(b0_list, str) or not b0_list: b2.B2FATAL("ModeSelector: b0_list must be a non-empty string") if not bp_list.startswith('B+:'): b2.B2FATAL(f"ModeSelector: bp_list must start with 'B+:'; got '{bp_list}'") if not b0_list.startswith('B0:'): b2.B2FATAL(f"ModeSelector: b0_list must start with 'B0:'; got '{b0_list}'") particle_lists = [bp_list, b0_list] if addDstarVetoReco: # Add D* veto reconstruction (pi0 list created internally) addDstarVeto(particle_lists, path=path) # Add the ModeSelector module module = ModeSelectorModule( particle_lists=particle_lists, payload_cat_model=payload_cat_model, payload_main_model=payload_main_model, output_variable=output_variable, cat_model_path=cat_model_path, main_model_path=main_model_path, training_mode=training_mode, skip_nn_evaluation=skip_nn_evaluation, store_fei_calib_weight=store_fei_calib_weight, debug=debug, debug_max_events=debug_max_events, ) path.add_module(module) b2.B2INFO(f"ModeSelector: Added to path for particle lists: {particle_lists}") b2.B2INFO(f"ModeSelector: Output variable: extraInfo({output_variable})")