Source code for tflat.flavorTagger

#!/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.                  #
##########################################################################

import os
from basf2 import B2FATAL
import basf2
from variables import variables as vm
import modularAnalysis as ma
from stdPhotons import stdPhotons
from vertex import kFit
import tflat.utils as utils


def fill_particle_lists(config, maskName='TFLATDefaultMask', path=None):
    """
    Fills the particle lists.
    """

    # create particle list with pions
    trk_cut = config['trk_cut']
    ma.fillParticleList('pi+:tflat', trk_cut, path=path)

    # create particle list with gammas

    # load MVA's for all gamma
    ma.fillParticleList(
        "gamma:all",
        "",
        path=path,
    )
    ma.getBeamBackgroundProbability("gamma:all", config['VersionBeamBackgroundMVA'], path=path)
    ma.getFakePhotonProbability("gamma:all", config['VersionFakePhotonMVA'], path=path)

    stdPhotons(listtype='tight',  path=path)

    gamma_cut = config['gamma_cut']
    ma.cutAndCopyList('gamma:tflat', 'gamma:tight', gamma_cut, path=path)

    ma.reconstructDecay('K_S0:inRoe -> pi+:tflat pi-:tflat', '0.40<=M<=0.60', False, path=path)
    kFit('K_S0:inRoe', 0.01, path=path)


[docs] def flavorTagger(particleLists, mode='Expert', working_dir='', uniqueIdentifier='TFlaT_MC16rd_light_2601_hyperion', target='qrCombined', overwrite=False, sampler_id=0, path=None): """ Interfacing for the Transformer FlavorTagger (TFlat). This function can be used for preparation of training datasets (``Sampler``) and inference (``Expert``). This function requires reconstructed B meson signal particle list and where an RestOfEvent is built. :param particleLists: string or list[string], particle list(s) of the reconstructed signal B meson :param mode: string, valid modes are ``Expert`` (default), ``Sampler`` :param working_dir: string, working directory for the method :param uniqueIdentifier: string, database identifier for the method :param target: string, target variable :param overwrite: bool, overwrite already (locally!) existing training :param sampler_id: identifier of sampled file for parallel sampling :param path: basf2 path obj :return: None """ if isinstance(particleLists, str): particleLists = [particleLists] if mode not in ['Expert', 'Sampler']: B2FATAL(f'Invalid mode {mode}') tree_name = 'tflat_variables' rank_variable = 'p' config = utils.load_config(uniqueIdentifier) # create default ROE-mask TFLAT_mask = config['TFLAT_Mask'] maskName = TFLAT_mask[0] for name in particleLists: ma.appendROEMasks(list_name=name, mask_tuples=[TFLAT_mask], path=path) # create roe specific paths roe_path = basf2.create_path() dead_end_path = basf2.create_path() if mode == 'Sampler': trk_variable_list = config['trk_variable_list'] ecl_variable_list = config['ecl_variable_list'] roe_variable_list = config['roe_variable_list'] # create tagging specific variables features = utils.get_variables('pi+:tflat', rank_variable, trk_variable_list, particleNumber=config['parameters']['num_trk']) features += utils.get_variables('gamma:tflat', rank_variable, ecl_variable_list, particleNumber=config['parameters']['num_ecl']) features += utils.get_variables('pi+:tflat', rank_variable, roe_variable_list, particleNumber=config['parameters']['num_roe']) output_file_name = os.path.join(working_dir, uniqueIdentifier + f'_training_data{sampler_id}.root') if os.path.isfile(output_file_name) and not overwrite: B2FATAL(f'Outputfile {output_file_name} already exists. Aborting writeout.') # filter rest of events only for specific particle list ma.signalSideParticleListsFilter( particleLists, f'nROE_Charged({maskName}, 0) > 0 and abs(qrCombined) == 1', roe_path, dead_end_path) fill_particle_lists(config, maskName, roe_path) ma.rankByHighest('pi+:tflat', rank_variable, path=roe_path) ma.rankByHighest('gamma:tflat', rank_variable, path=roe_path) vm.addAlias('refdx', 'getVariableByRank(pi+:tflat, p, dx, 1)') vm.addAlias('dxdiff', 'formula(dx-refdx)') vm.addAlias('refdy', 'getVariableByRank(pi+:tflat, p, dy, 1)') vm.addAlias('dydiff', 'formula(dy-refdy)') vm.addAlias('refdz', 'getVariableByRank(pi+:tflat, p, dz, 1)') vm.addAlias('dzdiff', 'formula(dz-refdz)') # and add target all_variables = features + [target] # write to ntuples ma.variablesToNtuple('', all_variables, tree_name, output_file_name, roe_path) path.for_each('RestOfEvent', 'RestOfEvents', roe_path) elif mode == 'Expert': # filter rest of events only for specific particle list ma.signalSideParticleListsFilter( particleLists, f'nROE_Charged({maskName}, 0) > 0', roe_path, dead_end_path) path.add_module('FlavorTaggerInfoBuilder') fill_particle_lists(config, maskName, roe_path) ma.rankByHighest('pi+:tflat', rank_variable, path=roe_path) ma.rankByHighest('gamma:tflat', rank_variable, path=roe_path) vm.addAlias('refdx', 'getVariableByRank(pi+:tflat, p, dx, 1)') vm.addAlias('dxdiff', 'formula(dx-refdx)') vm.addAlias('refdy', 'getVariableByRank(pi+:tflat, p, dy, 1)') vm.addAlias('dydiff', 'formula(dy-refdy)') vm.addAlias('refdz', 'getVariableByRank(pi+:tflat, p, dz, 1)') vm.addAlias('dzdiff', 'formula(dz-refdz)') expert_module = basf2.register_module('MVAExpert') expert_module.param('listNames', particleLists) expert_module.param('identifier', uniqueIdentifier) expert_module.param('extraInfoName', 'tflat_output') roe_path.add_module(expert_module) flavorTaggerInfoFiller = basf2.register_module('FlavorTaggerInfoFiller') flavorTaggerInfoFiller.param('TFLATnn', True) roe_path.add_module(flavorTaggerInfoFiller) # Create standard alias for the output of the flavor tagger vm.addAlias('qrTFLAT', 'qrOutput(TFLAT)') path.for_each('RestOfEvent', 'RestOfEvents', roe_path)