10from basf2 
import B2INFO, B2ERROR
 
   12import modularAnalysis 
as ma
 
   14from variables 
import utils
 
   17def add_default_ks_Selector_aliases():
 
   19    This function is used to set up variables aliases for ks Selector variables. 
   21    B2INFO(
'KsSelector: creating variables alias.')
 
   22    variables.variables.addAlias(
'M_lambda_p', 
'useAlternativeDaughterHypothesis(M, 0:p+)')
 
   23    variables.variables.addAlias(
'M_lambda_antip', 
'useAlternativeDaughterHypothesis(M, 1:anti-p-)')
 
   24    variables.variables.addAlias(
'daughtersDeltaZ', 
'daughterDiffOf(0, 1, dz)')
 
   25    variables.variables.addAlias(
'cosVertexMomentum', 
'cosAngleBetweenMomentumAndVertexVector')
 
   26    variables.variables.addAlias(
'pip_nPXDHits', 
'daughter(0,nPXDHits)')
 
   27    variables.variables.addAlias(
'pin_nPXDHits', 
'daughter(1,nPXDHits)')
 
   28    variables.variables.addAlias(
'pip_nSVDHits', 
'daughter(0,nSVDHits)')
 
   29    variables.variables.addAlias(
'pin_nSVDHits', 
'daughter(1,nSVDHits)')
 
   30    variables.variables.addAlias(
'daughterAngleDiffInMother', 
'useRestFrame(daughterAngle(0, 1))')
 
   31    variables.variables.addAlias(
'pip_p', 
'daughter(0,p)')
 
   32    variables.variables.addAlias(
'pin_p', 
'daughter(1,p)')
 
   33    variables.variables.addAlias(
'pip_dr', 
'daughter(0,dr)')
 
   34    variables.variables.addAlias(
'pin_dr', 
'daughter(1,dr)')
 
   35    variables.variables.addAlias(
'pip_cosTheta', 
'daughter(0,cosTheta)')
 
   36    variables.variables.addAlias(
'pin_cosTheta', 
'daughter(1,cosTheta)')
 
   37    variables.variables.addAlias(
'pip_protonID', 
'daughter(0,protonID)')
 
   38    variables.variables.addAlias(
'pin_protonID', 
'daughter(1,protonID)')
 
   41def add_variable_collection():
 
   43    Call this function to add variable collection for ksSelector. 
   45    add_default_ks_Selector_aliases()
 
   46    inputVariablesList = [
 
   49        'significanceOfDistance',
 
   50        'cosHelicityAngleMomentum',
 
   54        'daughterAngleDiffInMother',
 
   56        'pip_nSVDHits', 
'pip_nPXDHits',
 
   57        'pin_nSVDHits', 
'pin_nPXDHits',
 
   59        'pip_protonID', 
'pin_protonID',
 
   60        'M_lambda_p', 
'M_lambda_antip',
 
   62        'pip_cosTheta', 
'pin_cosTheta',
 
   63        'ArmenterosLongitudinalMomentumAsymmetry',
 
   64        'ArmenterosDaughter1Qt',
 
   65        'ArmenterosDaughter2Qt' 
   67    utils.add_collection(inputVariablesList, 
'ks_selector_info')
 
   70def V0Selector_Training(
 
   73    mva_identifier="MVAFastBDT_V0Selector.root",
 
   74    target_variable="isSignal",
 
   79    Defines the configuration of V0Selector Training. 
   80    The training data should contain K_S0 and misreconstructed K_S0 without Lambda0. 
   82    @param train_data                   Root file containing Ks information to be trained. 
   83    @param tree_name                    Tree name for variables. 
   84    @param mva_identifier               Name for output MVA weight file. 
   85    @param target_variable              Target variable for MVA training. 
   86    @param parameters                   hyperparameter for LGBM 
   87    @param options                      MVA options 
   92        'significanceOfDistance',
 
   93        'cosHelicityAngleMomentum',
 
   97        'daughterAngleDiffInMother',
 
   99        'pip_nSVDHits', 
'pin_nSVDHits',
 
  103    general_options = basf2_mva.GeneralOptions()
 
  104    general_options.m_datafiles = basf2_mva.vector(train_data)
 
  105    general_options.m_treename = tree_name
 
  106    general_options.m_identifier = mva_identifier
 
  107    general_options.m_variables = basf2_mva.vector(*trainVars)
 
  108    general_options.m_target_variable = target_variable
 
  109    general_options.m_max_events = 0 
if 'max_events' not in options 
else options[
'max_events']
 
  111    python_options = basf2_mva.PythonOptions()
 
  112    python_options.m_framework = 
"lightgbm" 
  115    param = {
'num_leaves': 256,
 
  116             'learning_rate': 0.1,
 
  117             'device_type': 
"cpu",
 
  118             'deterministic': 
True,
 
  122             'path': mva_identifier+
'.txt',
 
  125             'trainFraction': 0.8,
 
  126             'min_data_in_leaf': 4000,
 
  128             'objective': 
'cross_entropy',
 
  131    if isinstance(parameters, dict):
 
  132        param.update(parameters)
 
  133    config_string = json.dumps(param)
 
  134    print(
"The json config string", config_string)
 
  135    python_options.m_config = config_string
 
  137    python_options.m_training_fraction = 1
 
  138    python_options.m_normalize = 
False   
  139    python_options.m_nIterations = 1
 
  140    python_options.m_mini_batch_size = 0
 
  142    basf2_mva.teacher(general_options, python_options)
 
  145def LambdaVeto_Training(
 
  148    mva_identifier="MVAFastBDT_LambdaVeto.root",
 
  149    target_variable="isSignal",
 
  154    Defines the configuration of LambdaVeto Training. 
  155    The training data should contain only K_S0 and Lambda0. 
  157    @param train_data                   Root file containing Ks information to be trained. 
  158    @param tree_name                    Tree name for variables. 
  159    @param mva_identifier               Name for output MVA weight file. 
  160    @param target_variable              Target variable for MVA training. 
  161    @param parameters                   hyperparameter for LGBM 
  162    @param options                      MVA options 
  171        'ArmenterosLongitudinalMomentumAsymmetry',
 
  172        'ArmenterosDaughter1Qt',
 
  173        'ArmenterosDaughter2Qt' 
  176    general_options = basf2_mva.GeneralOptions()
 
  177    general_options.m_datafiles = basf2_mva.vector(train_data)
 
  178    general_options.m_treename = tree_name
 
  179    general_options.m_identifier = mva_identifier
 
  180    general_options.m_variables = basf2_mva.vector(*trainVars)
 
  181    general_options.m_target_variable = target_variable
 
  182    general_options.m_max_events = 0 
if 'max_events' not in options 
else options[
'max_events']
 
  184    python_options = basf2_mva.PythonOptions()
 
  185    python_options.m_framework = 
"lightgbm" 
  188    param = {
'num_leaves': 256,
 
  189             'learning_rate': 0.2,
 
  190             'device_type': 
"cpu",
 
  191             'deterministic': 
True,
 
  195             'path': mva_identifier+
'.txt',
 
  198             'trainFraction': 0.8,
 
  199             'min_data_in_leaf': 300,
 
  201             'objective': 
'cross_entropy',
 
  204    if isinstance(parameters, dict):
 
  205        param.update(parameters)
 
  206    config_string = json.dumps(param)
 
  207    print(
"The json config string", config_string)
 
  208    python_options.m_config = config_string
 
  210    python_options.m_training_fraction = 1
 
  211    python_options.m_normalize = 
False   
  212    python_options.m_nIterations = 1
 
  213    python_options.m_mini_batch_size = 0
 
  215    basf2_mva.teacher(general_options, python_options)
 
  224    identifier_Ks="Ks_LGBM_V0Selector",
 
  225    identifier_vLambda="Ks_LGBM_LambdaVeto",
 
  226    output_label_name='',
 
  227    extraInfoName_V0Selector='KsSelector_V0Selector',
 
  228    extraInfoName_LambdaVeto='KsSelector_LambdaVeto',
 
  229    useCustomThreshold=False,
 
  230    threshold_V0Selector=0.90,
 
  231    threshold_LambdaVeto=0.11,
 
  235    This function will apply K_S0 selection MVA on the given particleList. 
  236    By default this function appends MVA output as a extraInfo for the given particleList. 
  237    You can apply preset cut or custom cut by giving parameters. In this case, 
  238    a new particleList is created from the original particleList applying cuts on the MVA output. 
  240    @param particleLists                Reconstructed Ks -> pi+ pi- list. 
  241    @param output_label_name            Label of the returned Ks particleList. 
  242                                        When empty '', no cut is applied and new particleList is not created. 
  243                                        When custom name, the custom threshold is used, and useCustomThreshold 
  245                                        When 'standard', 'tight', or 'loose', a cut with Ks efficiency 
  246                                        90%, 95%, and 85% is applied. 
  247    @param extraInfoName_V0Selector     Variable name for V0Selector MVA output. 
  248    @param extraInfoName_LambdaVeto     Variable name for LambdaVeto MVA output. 
  249    @param identifier_Ks                Identifier name for V0Selector weight file. 
  250    @param identifier_vLambda           Identifier name for LambdaVeto weight file. 
  251    @param useCustomThreshold           Flag whether threshold_V0Selector and threshold_LambdaVeto are used. 
  252    @param threshold_V0Selector         Threshold for V0Selector. 
  253    @param threshold_LambdaVeto         Threshold for LambdaVeto. 
  254    @param path                         Basf2 path to execute. 
  258    add_default_ks_Selector_aliases()
 
  260    path.add_module(
'MVAMultipleExperts',
 
  261                    listNames=[particleListName],
 
  262                    extraInfoNames=[extraInfoName_V0Selector, extraInfoName_LambdaVeto],
 
  263                    identifiers=[identifier_Ks, identifier_vLambda])
 
  265    _effnames = [
'standard', 
'tight', 
'loose']
 
  268    if useCustomThreshold:
 
  269        if output_label_name 
in _effnames:
 
  270            B2ERROR(
'KsSelector: Specify label name except for \'standard\', \'tight\', and \'loose\' ' 
  271                    'when you use custom threshold.')
 
  272        elif output_label_name == 
'':
 
  273            B2ERROR(
'KsSelector: Specify label name when you use custom threshold.')
 
  275            outputListName = particleListName.split(
':')[0] + 
':' + output_label_name
 
  276            B2INFO(
'KsSelector: Custom Cut is applied on '+outputListName+
'.')
 
  277            V0_thr = threshold_V0Selector
 
  278            Lambda_thr = threshold_LambdaVeto
 
  279            B2INFO(
'KsSelector: Threshold is (' + str(V0_thr) + 
', ' + str(Lambda_thr) + 
')')
 
  280            cut_string = 
'extraInfo('+extraInfoName_V0Selector+
')>'+str(V0_thr) + \
 
  281                ' and extraInfo('+extraInfoName_LambdaVeto+
')>'+str(Lambda_thr)
 
  282            ma.cutAndCopyLists(outputListName, particleListName, cut=cut_string, path=path)
 
  284        if output_label_name 
in _effnames:
 
  285            outputListName = particleListName.split(
':')[0] + 
':' + output_label_name
 
  288            if output_label_name == 
'standard':
 
  289                B2INFO(
'KsSelector: Standard Cut is applied on '+outputListName+
'.')
 
  292            elif output_label_name == 
'tight':
 
  293                B2INFO(
'KsSelector: Tight Cut is applied on '+outputListName+
'.')
 
  296            elif output_label_name == 
'loose':
 
  297                B2INFO(
'KsSelector: Loose Cut is applied on '+outputListName+
'.')
 
  300            B2INFO(
'KsSelector: Threshold is (' + str(V0_thr) + 
', ' + str(Lambda_thr) + 
')')
 
  301            cut_string = 
'extraInfo('+extraInfoName_V0Selector+
')>'+str(V0_thr) + \
 
  302                ' and extraInfo('+extraInfoName_LambdaVeto+
')>'+str(Lambda_thr)
 
  303            ma.cutAndCopyLists(outputListName, particleListName, cut=cut_string, path=path)
 
  304        elif output_label_name == 
'':
 
  305            outputListName = particleListName
 
  307            B2ERROR(
'KsSelector: Label should be \'\', \'standard\', \'tight\', or \'loose\' if you do' 
  308                    'not apply custom threshold')
 
  310    B2INFO(
'KsSelector: ParticleList '+outputListName+
' is returned.')