diff --git a/rd_ap_2024/README.md b/rd_ap_2024/README.md new file mode 100644 index 0000000000000000000000000000000000000000..fcd927fd6a0535a0c79aa2066e49bdd49b0a4ba3 --- /dev/null +++ b/rd_ap_2024/README.md @@ -0,0 +1,436 @@ +### AP example for RD , to be used/expanded integrated, feel free to ping and share + + + +- info.yaml is used to run APs on 2024-early data and simulation samples + + +Few information on the AP configuration here: + +### Working principle of the framework for Simulation +First the HLT1 and HLT2 has to be executed. This is driven by the entry in ```info.yaml``` defining the job names with ```MC_{{_SAMPLEID_}}_XXX_HLT1{HLT2,Tupling}``` which are connected together by the ```input``` field setup. + +The ```entrypoint:``` defines the script used for the step and ```extra_args``` is used to steer the function of the entrypoint. The script used for the recnstruction in HLT1 and HLT2 are : +- ```rd_ap_2024/mc/hlt1.py``` +- ```rd_ap_2024/mc/hlt2.py``` + +Those 2 options are used to run the HLT1 and HLT2 as in data. One has to be careful on the Moore version used and configuration of the sequence. Typically those information will need to be provided by RTA. So in doubt ask the RD-RTA liason. For more advanced configurations [ with UT/no UT etc.. contact the experts on the actual configruation to use ] + +Then, in order to determine for a given EventType which HLT2/Turcal Line to tuple foor a given MC we have a bi-directional mapping defined in ```Config.py```: + +- ```rd_ap_2024/tupling/Config.py``` has the function ```KNOWN_EVENT_TYPES_CONFIG_TO_LINES()``` which returns a dictionary that for each sampleID in info.yaml specify the list of lines to tuple. Example: +```python + _known_event_types_config_lines_ = OrderedDict({ + #EWP MM/EE modes K* ee/mm + "Bd_JPsiKst_MM": set([ +"Hlt2RD_B0ToKpPimMuMu", +"Hlt2RD_BuToHpMuMu_Incl", +"Hlt2RD_BuToKpJpsi_JpsiToMuMu", +"Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", +"Hlt2RD_B0ToKpKmMuMu", +"Hlt2RD_LbToPKJpsi_JpsiToMuMu", +"Hlt2PID_JpsiToMuMumTagged_Detached", +"Hlt2PID_JpsiToMuMupTagged_Detached", +"Hlt2PID_BToJpsiK_JpsiToMuMumTagged_Detached", +"Hlt2PID_BToJpsiK_JpsiToMuMupTagged_Detached", +"Hlt2RD_B0ToPipPimMuMu", +"Hlt2Topo3Body", +"Hlt2TopoMu3Body" + ]), +``` + +- i.e ```"Bd_JPsiKst_MM"``` will tuple in simulation the output of all the lines specified. +- The line names specified must be found in the ```tupling/hlt2{turcal}/``` content + + +#### Step 1: +``` +lhcb-proxy-init +``` + +#### Step 2: +Look up in the BKK the event type of interest and keep note of the BKK path to use. +This has to end up in the info.yaml in some form for simulation steps. Each EventType has a unique 'name' which is then used inside the code to steer what lines to run over it. +See ```KNOWN_EVENT_TYPES_CONFIG_TO_LINES()``` in ```rd_ap_2024/tupling/Config.py```. + +> For MC: The logic is that a given EventType gets a chain of HLT1->HLT2 step only [Spruce not done, waiting for input] and then a tupling is executed + +> Example for this AP: a given event type is mapped to a specific 'name' of the mode , this mapping is forwarded around to simplify. Different Streams for the processing are defined. +The list provided just determine a list of MC-samples to go through different processing chain +``` +{%- set candidate_datasets = { + 'Turbo' : [ + ("Bu_JPsiK_EE" , '12153001'), + ("Bu_JPsiK_MM" , '12143001'), + ('MinBias' , '30000000') + ], + 'TurCal': [ + ("Bu_JPsiK_EE" , '12153001'), + ("Bu_JPsiK_MM" , '12143001'), + ('MinBias' , '30000000') + ] +}%} +{%- set mc_cond_path = '/MC/expected-2024.Q1.2/Beam6800GeV-expected-2024.Q1.2-' + polarity + '-Nu7.6-25ns-Pythia8/Sim10c' %} + +{%- set polarity_variables = [ + ('MagDown', 'sim-20231017-vc-md100','dddb-20240311' ), + ('MagUp' , 'sim-20231017-vc-mu100','dddb-20240311' ) +] +%} +``` + +> We need to run HLT1->HLT2 on DIGI file first to actually be able to read a DST to make tuples of executed HLT2-lines +> Job names relations created to create a workflow. +> ```bk_query``` defines the path to get the input DIGI file. +> ```output_manifest_file``` needed to run local tests and chain dependency needed as well + +``` +MC{{mc_cond}}_{{polarity}}_{{eventtype}}_{{stream}}_HLT1: + application: 'Moore/{{hlt1_v}}@{{detdesc_platform}}' + input: + bk_query: '{{mc_cond_path}}/{{eventcode}}/DIGI' + n_test_lfns: 1 + output: Hlt1.dst + options: + entrypoint: rd_ap_2024.mc.hlt1:main + extra_options: + input_raw_format: 0.5 + conddb_tag: {{conddb_tag}} + dddb_tag: {{dddb_tag}} + input_type: "ROOT" + output_type: "ROOT" + simulation: True + data_type: "Upgrade" + output_manifest_file: "HLT1.tck.json" +``` + +> Run HLT2 step : here you need to be carefull. +> The entry point is the option file in rd_ap_2024/mc/hlt2.py where the list of lines included to run for HLT2 is currently +``` +MC{{mc_cond}}_{{polarity}}_{{eventtype}}_{{stream}}_HLT2: + application: "Moore/{{hlt2_v}}@{{detdesc_platform}}" + input: + job_name: MC{{mc_cond}}_{{polarity}}_{{eventtype}}_{{stream}}_HLT1 + output: Hlt2.dst + options: + entrypoint: rd_ap_2024.mc.hlt2:main + extra_options: + conddb_tag: {{conddb_tag}} + dddb_tag: {{dddb_tag}} + input_type: "ROOT" + output_type: "ROOT" + input_manifest_file : "HLT1.tck.json" + output_manifest_file: "HLT2.tck.json" + simulation: True + data_type: "Upgrade" +``` + +``` +MC{{mc_cond}}_{{polarity}}_{{eventtype}}_{{stream}}_TUPLING: + application: "DaVinci/{{tuple_v}}@{{detdesc_platform}}" + input: + job_name: MC{{mc_cond}}_{{polarity}}_{{eventtype}}_{{stream}}_HLT2 + output: Tuple.root + options: + entrypoint: rd_ap_2024.tupling.main:Run + extra_options: + input_manifest_file: "HLT2.tck.json" + input_raw_format: 0.5 + input_type: ROOT + simulation: True + data_type: "Upgrade" + conddb_tag: {{conddb_tag}} + dddb_tag: {{dddb_tag}} + input_process: {{dv_input_process}} + geometry_version: run3/2024.Q1.2-v00.00 + extra_args : + - {{eventtype}} + - {{stream}} + - {{isMC}} + {%- endfor %} + {%- endfor %} +{%- endfor %} +``` + + + + + + + + + + + +For Turcal : + ++ Check here : https://gitlab.cern.ch/lhcb/Moore/-/blob/master/Hlt/Hlt2Conf/python/Hlt2Conf/sprucing_settings/Sprucing_production_PP_24c1.py?ref_type=heads#L182 + +FOLDER TURCAL : +- ```/LHCb/Collision24/Beam6800GeV-VeloClosed-MagDown-Excl-UT/Real Data/Sprucing24c1/95100000/``` + + +## ***TURCAL_MDST.DST*** +```python +nominal_lines = [ + "Hlt2PID_BToJpsiK_JpsiToMuMumTagged_Detached", + "Hlt2PID_BToJpsiK_JpsiToMuMupTagged_Detached", + "Hlt2PID_BToJpsiK_JpsiToPpPmTagged", + "Hlt2PID_BToJpsiK_JpsiToPmPpTagged", + "Hlt2PID_DsToPhiPi_PhiToMuMupTagged_Detached", + "Hlt2PID_DsToPhiPi_PhiToMuMumTagged_Detached", + "Hlt2PID_DstToD0Pi_D0ToKPiPiPi", + "Hlt2PID_KsToPiPi_LL", + "Hlt2PID_LbToLcMuNu_LcToPKPi", + "Hlt2PID_LbToLcPi_LcToPKPi", + "Hlt2PID_LcToPKPi", + "Hlt2PID_OmegaToL0K_L0ToPPi_LLL", + "Hlt2PID_PhiToKK_Unbiased_Detached", + "Hlt2PID_PhiToKmKpTagged_Detached", + "Hlt2PID_KsToPiPi_DD", + "Hlt2PID_L0ToPPi_DD_LowPT", + "Hlt2PID_L0ToPPi_DD_MidPT", + "Hlt2PID_OmegaToL0K_L0ToPPi_DDD", + "Hlt2PID_L0ToPPi_DD_HighPT", + "Hlt2PID_PhiToKpKmTagged_Detached", + "Hlt2PID_L0ToPPi_DD_VeryHighPT", + ] +``` +## ***TURCAL_PERSISTRECO.DST*** +```python +persist_reco_lines = [ + "Hlt2PID_BdToKstG", + "Hlt2PID_Bs2PhiG", + "Hlt2PID_EtaMuMuG", + "Hlt2PID_Dsst2DsG", + "Hlt2PID_D2EtapPi", + "Hlt2PID_DstToD0Pi_D0ToKPiPi0Resolved", + "Hlt2PID_DstToD0Pi_D0ToKPiPi0Merged", +] +``` + + +## ***TURCAL_PERSISTRECORAWBANKS.DST*** +```python +persist_reco_rawbank_lines = [ + "Hlt2TrackEff_ZToMuMu_SeedMuon_mup_Tag", + "Hlt2TrackEff_ZToMuMu_SeedMuon_mum_Tag", + "Hlt2TrackEff_ZToMuMu_SeedMuon_mum_Match", + "Hlt2TrackEff_ZToMuMu_SeedMuon_mup_Match", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mup_Tag", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mum_Tag", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mum_Match", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mup_Match", + "Hlt2TrackEff_Velo2Long_B2JpsiK_MuonProbe_VELO", + "Hlt2TrackEff_Velo2Long_B2JpsiK_ElectronProbe_VELO", + "Hlt2TurCalVelo2Long_KshortVSoft", + "Hlt2TurCalVelo2Long_KshortHard", + "Hlt2TurCalVelo2Long_Kshort", + "Hlt2TurCalVelo2Long_KshortSoft", + "Hlt2TurCalVelo2Long_KshortVHard", +] +``` + +## ***TURCAL_RAWBANKS.DST*** +```python +rawbank_lines = [ + "Hlt2PID_JpsiToMuMumTagged_Detached", + "Hlt2PID_JpsiToMuMupTagged_Detached", + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged_noPIDe", + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged_noPIDe", + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged", + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged", + "Hlt2PID_DstToD0Pi_D0ToKPi", + "Hlt2PID_L0ToPPi_LL_LowPT", + "Hlt2PID_L0ToPPi_LL_MidPT", + "Hlt2PID_L0ToPPi_LL_HighPT", + "Hlt2PID_L0ToPPi_LL_VeryHighPT", + "Hlt2TrackEff_DiMuon_SeedMuon_mup_Tag", + "Hlt2TrackEff_DiMuon_SeedMuon_mum_Tag", + "Hlt2TrackEff_DiMuon_SeedMuon_mum_Match", + "Hlt2TrackEff_DiMuon_SeedMuon_mup_Match", + "Hlt2TrackEff_DiMuon_VeloMuon_mup_Tag", + "Hlt2TrackEff_DiMuon_VeloMuon_mum_Tag", + "Hlt2TrackEff_DiMuon_VeloMuon_mum_Match", + "Hlt2TrackEff_DiMuon_VeloMuon_mup_Match", +] + +``` +- Selected of interest here for PID are : + + "Hlt2PID_JpsiToMuMumTagged_Detached", + + "Hlt2PID_JpsiToMuMupTagged_Detached", + + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged_noPIDe", + + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged_noPIDe", + + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged", + + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged", + + "Hlt2PID_DstToD0Pi_D0ToKPi", # for mis-ID +``` + +## debugging +Obtained list from check [here](https://gitlab.cern.ch/lhcb/Moore/-/blob/master/Hlt/Hlt2Conf/python/Hlt2Conf/sprucing_settings/Sprucing_production_PP_24c1.py?ref_type=heads#L182) + +```python +def make_turcal_spruce_prod_streams(): + streams = [ + Stream( + "Turcal_mDST", + lines=[make_turcal_spruceline(line) for line in nominal_lines], + detectors=[]), + Stream( + "Turcal_persistreco", + lines=[ + make_turcal_spruceline(line, persist_reco=True) + for line in persist_reco_lines + ], + detectors=[]), + Stream( + "Turcal_rawbanks", + lines=[make_turcal_spruceline(line) for line in rawbank_lines], + detectors=DETECTORS), + Stream( + "Turcal_persistrecorawbanks", + lines=[ + make_turcal_spruceline(line, persist_reco=True) + for line in persist_reco_rawbank_lines + ], + detectors=DETECTORS) + ] + print(streams) + return Streams(streams=streams) +### with +nominal_lines = [ + "Hlt2PID_BToJpsiK_JpsiToMuMumTagged_Detached", + "Hlt2PID_BToJpsiK_JpsiToMuMupTagged_Detached", + "Hlt2PID_BToJpsiK_JpsiToPpPmTagged", + "Hlt2PID_BToJpsiK_JpsiToPmPpTagged", + "Hlt2PID_DsToPhiPi_PhiToMuMupTagged_Detached", + "Hlt2PID_DsToPhiPi_PhiToMuMumTagged_Detached", + "Hlt2PID_DstToD0Pi_D0ToKPiPiPi", + "Hlt2PID_KsToPiPi_LL", + "Hlt2PID_LbToLcMuNu_LcToPKPi", + "Hlt2PID_LbToLcPi_LcToPKPi", + "Hlt2PID_LcToPKPi", + "Hlt2PID_OmegaToL0K_L0ToPPi_LLL", + "Hlt2PID_PhiToKK_Unbiased_Detached", + "Hlt2PID_PhiToKmKpTagged_Detached", + "Hlt2PID_KsToPiPi_DD", + "Hlt2PID_L0ToPPi_DD_LowPT", + "Hlt2PID_L0ToPPi_DD_MidPT", + "Hlt2PID_OmegaToL0K_L0ToPPi_DDD", + "Hlt2PID_L0ToPPi_DD_HighPT", + "Hlt2PID_PhiToKpKmTagged_Detached", + "Hlt2PID_L0ToPPi_DD_VeryHighPT", +] + +persist_reco_lines = [ + "Hlt2PID_BdToKstG", + "Hlt2PID_Bs2PhiG", + "Hlt2PID_EtaMuMuG", + "Hlt2PID_Dsst2DsG", + "Hlt2PID_D2EtapPi", + "Hlt2PID_DstToD0Pi_D0ToKPiPi0Resolved", + "Hlt2PID_DstToD0Pi_D0ToKPiPi0Merged", +] + + + +### check all lines which can be run/import +``` +lb-run DaVinci/v64r6 python rd_ap_2024/print_all_tupling_debug.py +``` + + +rawbank_lines = [ + "Hlt2PID_JpsiToMuMumTagged_Detached", + "Hlt2PID_JpsiToMuMupTagged_Detached", + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged_noPIDe", + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged_noPIDe", + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged", + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged", + "Hlt2PID_DstToD0Pi_D0ToKPi", + "Hlt2PID_L0ToPPi_LL_LowPT", + "Hlt2PID_L0ToPPi_LL_MidPT", + "Hlt2PID_L0ToPPi_LL_HighPT", + "Hlt2PID_L0ToPPi_LL_VeryHighPT", + "Hlt2TrackEff_DiMuon_SeedMuon_mup_Tag", + "Hlt2TrackEff_DiMuon_SeedMuon_mum_Tag", + "Hlt2TrackEff_DiMuon_SeedMuon_mum_Match", + "Hlt2TrackEff_DiMuon_SeedMuon_mup_Match", + "Hlt2TrackEff_DiMuon_VeloMuon_mup_Tag", + "Hlt2TrackEff_DiMuon_VeloMuon_mum_Tag", + "Hlt2TrackEff_DiMuon_VeloMuon_mum_Match", + "Hlt2TrackEff_DiMuon_VeloMuon_mup_Match", +] + +persist_reco_rawbank_lines = [ + "Hlt2TrackEff_ZToMuMu_SeedMuon_mup_Tag", + "Hlt2TrackEff_ZToMuMu_SeedMuon_mum_Tag", + "Hlt2TrackEff_ZToMuMu_SeedMuon_mum_Match", + "Hlt2TrackEff_ZToMuMu_SeedMuon_mup_Match", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mup_Tag", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mum_Tag", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mum_Match", + "Hlt2TrackEff_ZToMuMu_VeloMuon_mup_Match", + "Hlt2TrackEff_Velo2Long_B2JpsiK_MuonProbe_VELO", + "Hlt2TrackEff_Velo2Long_B2JpsiK_ElectronProbe_VELO", + "Hlt2TurCalVelo2Long_KshortVSoft", + "Hlt2TurCalVelo2Long_KshortHard", + "Hlt2TurCalVelo2Long_Kshort", + "Hlt2TurCalVelo2Long_KshortSoft", + "Hlt2TurCalVelo2Long_KshortVHard", +] + +``` + + + + +### For RD interest in turcal [e->e, mu->mu] + +- TURCAL_RAWBANKS.DST + + "Hlt2PID_JpsiToMuMumTagged_Detached", + + "Hlt2PID_JpsiToMuMupTagged_Detached", + + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged_noPIDe", + + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged_noPIDe", + + "Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged", + + "Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged", + +- TURCAL_PERSISTRECORAWBANKS.DST + + "Hlt2TrackEff_Velo2Long_B2JpsiK_MuonProbe_VELO", + + "Hlt2TrackEff_Velo2Long_B2JpsiK_ElectronProbe_VELO", + +- TURCAL_PERSISTRECO.DST [ for gamma/pi0 ] + + "Hlt2PID_BdToKstG", + + "Hlt2PID_Bs2PhiG", + + "Hlt2PID_EtaMuMuG", + + "Hlt2PID_Dsst2DsG", + + "Hlt2PID_D2EtapPi", + + "Hlt2PID_DstToD0Pi_D0ToKPiPi0Resolved", + + "Hlt2PID_DstToD0Pi_D0ToKPiPi0Merged", + +- TURCAL_MDST.DST + + "Hlt2PID_BToJpsiK_JpsiToMuMumTagged_Detached", + + "Hlt2PID_BToJpsiK_JpsiToMuMupTagged_Detached", + + "Hlt2PID_BToJpsiK_JpsiToPpPmTagged", + + "Hlt2PID_BToJpsiK_JpsiToPmPpTagged", + <!-- + "Hlt2PID_DsToPhiPi_PhiToMuMupTagged_Detached", + + "Hlt2PID_DsToPhiPi_PhiToMuMumTagged_Detached", + + "Hlt2PID_DstToD0Pi_D0ToKPiPiPi", + + "Hlt2PID_KsToPiPi_LL", + + "Hlt2PID_LbToLcMuNu_LcToPKPi", + + "Hlt2PID_LbToLcPi_LcToPKPi", + + "Hlt2PID_LcToPKPi", + + "Hlt2PID_OmegaToL0K_L0ToPPi_LLL", + + "Hlt2PID_PhiToKK_Unbiased_Detached", + + "Hlt2PID_PhiToKmKpTagged_Detached", + + "Hlt2PID_KsToPiPi_DD", + + "Hlt2PID_L0ToPPi_DD_LowPT", + + "Hlt2PID_L0ToPPi_DD_MidPT", + + "Hlt2PID_OmegaToL0K_L0ToPPi_DDD", + + "Hlt2PID_L0ToPPi_DD_HighPT", + + "Hlt2PID_PhiToKpKmTagged_Detached", + + "Hlt2PID_L0ToPPi_DD_VeryHighPT", --> + + + +The trick is to set CMAKE_PREFIX_PATH and run lb-prod-run on the json file \ No newline at end of file diff --git a/rd_ap_2024/info.yaml b/rd_ap_2024/info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cbcecac11af22d40a654afac1ef101c3f8fa9578 --- /dev/null +++ b/rd_ap_2024/info.yaml @@ -0,0 +1,98 @@ +defaults: + inform: + - acampove@cern.ch + wg: RD + + +##################################################################################################################### +# Post-TS processing (24c2 + UT data) (W31.34 MC production MagUp only) +##################################################################################################################### +{%- set davinci_version = 'v64r12' %} # DV latest as of 09-Apr +{%- set dv_detdesc_platform = 'x86_64_v2-el9-gcc13+detdesc-opt' %} # a `v2` detdesc platform compatible with latest Moore release. +{%- set isMC = True %} +{%- set Sprucing = "Sprucing24c2"%} +{%- set _DEV_PATH_ = "2024"%} +{%- set _MCPATH_ = "2024.W31.34"%} +{%- set nu_path = "Nu6.3"%} +{%- set nu_name = "Nu6p3"%} +{%- set generator = "Pythia8"%} +{%- set sim_version = "Sim10d"%} + + +########################################## +# List of samples to run over +# In presence of a 'Comment: ' the line is skipped but it helps to categorise parts in this file +########################################## +{%- set candidates_datasets = [ +('Bu_JPsiK_MM' , '12143001' , '2024.W31.34', 'MagUp' , 'sim10-2024.Q3.4-v1.3-mu100', 'dddb-20240427', "Nu6.3", "Nu6p3", "Sim10d", "Pythia8" ), +('Bu_JPsiPi_MM' , '12143010' , '2024.W31.34', 'MagUp' , 'sim10-2024.Q3.4-v1.3-mu100', 'dddb-20240427', "Nu6.3", "Nu6p3", "Sim10d", "Pythia8" ), +('Bd_JPsiKst_MM' , '11144001' , '2024.W31.34', 'MagUp' , 'sim10-2024.Q3.4-v1.3-mu100', 'dddb-20240427', "Nu6.3", "Nu6p3", "Sim10d", "Pythia8" ), +('Bd_JPsiX_MM' , '11442001' , '2024.W31.34', 'MagUp' , 'sim10-2024.Q3.4-v1.3-mu100', 'dddb-20240427', "Nu6.3", "Nu6p3", "Sim10d", "Pythia8" ), +('Bu_JPsiK_EE' , '12153001' , '2024.W31.34', 'MagUp' , 'sim10-2024.Q3.4-v1.3-mu100', 'dddb-20240427', "Nu6.3", "Nu6p3", "Sim10d", "Pythia8" ), +('Bd_JPsiKst_EE' , '11154001' , '2024.W31.34', 'MagUp' , 'sim10-2024.Q3.4-v1.3-mu100', 'dddb-20240427', "Nu6.3", "Nu6p3", "Sim10d", "Pythia8" ), +] +%} + +########################################## +# List of samples ID naming known to run over. This is a bit fragile, but it helps to keep track of records +########################################## +{%- set known_mcs = [ +'Bu_KMM', +'Bu_JPsiK_MM', +'Bu_JPsiPi_MM', +'Bd_JPsiKst_MM', +'Bd_JPsiX_MM', +'Bu_JPsiK_EE', +'Bd_JPsiKst_EE', +'Bu_JPsiX_MM', +'Bd_JPsiX_EE', +'Bu_JPsiX_EE', +'Bu_JPsiPi_EE', +] +%} +############################################################################################################## +# a very crappy routine to catch errors and tell users to include samples in known_mcs to create job chain +############################################################################################################## +{%-set FailedSamples=[]%} +{%- for _SAMPLEID_, _EVTTYPE_, _MCPATH_, _POLARITY_, conddb_tag, dddb_tag, nu_path, nuval, sim_version , generator in candidates_datasets if 'Comment' not in _SAMPLEID_ %} + {%- if _SAMPLEID_ not in known_mcs and _SAMPLEID_ not in FailedSamples %} + {%- set _ = FailedSamples.append(_SAMPLEID_)%} + {%- endif %} +{%- endfor %} + +{%- set message=["Please enable the element in known_mcs_variable and inform the main.py about what lines to use for it"]%} +{%- for failed in FailedSamples %} + {{message}} + {{FailedSamples}} +{%- endfor %} + +{%- for _SAMPLEID_, _EVTTYPE_, _MCPATH_, _POLARITY_, conddb_tag, dddb_tag, nu_path, nuval, sim_version, generator in candidates_datasets if 'Comment' not in _SAMPLEID_%} +MC_2024_W31_34_{{_POLARITY_}}_{{nuval}}_{{sim_version}}_{{generator}}_{{_EVTTYPE_}}_{{_SAMPLEID_}}_TUPLE: + application: 'DaVinci/{{davinci_version}}@{{dv_detdesc_platform}}' + input: + bk_query: '/MC/{{_DEV_PATH_}}/Beam6800GeV-{{_MCPATH_}}-{{_POLARITY_}}-{{nu_path}}-25ns-{{generator}}/{{sim_version}}/HLT2-2024.W31.34/{{_EVTTYPE_}}/DST' + n_test_lfns: 1 + keep_running: true + output: Tuple.root + options: + entrypoint: rd_ap_2024.tupling.main:Run + extra_options: + input_raw_format: 0.5 + input_type: ROOT + simulation: True + data_type: 'Upgrade' + conddb_tag: {{conddb_tag}} + dddb_tag: {{dddb_tag}} + input_process: 'Hlt2' + input_stream : '' + geometry_version: run3/2024.Q1.2-v00.00 + compression: + algorithm: ZSTD + level: 1 + max_buffer_size: 131072 + extra_args : + - {{_SAMPLEID_}} + - 'Turbo' + - {{isMC}} + - 'Sprucing24c2' +{%- endfor %} diff --git a/rd_ap_2024/tupling/Config.py b/rd_ap_2024/tupling/Config.py new file mode 100644 index 0000000000000000000000000000000000000000..63b14af028bc0e169a8dbf024fbea11d6a0308aa --- /dev/null +++ b/rd_ap_2024/tupling/Config.py @@ -0,0 +1,370 @@ +__author__ = "Renato Quagliani, Jan Peter Wagner , Michele Atzeni" +import os +import copy +import yaml + +from rd_ap_2024.utils.log_store import LogStore + +log=LogStore.add_logger('rd_ap_2024:Config') +# ----------------------------------------- +def get_all_binds_tupling_algs(hlt2_include=True, spruce_include=True, turcal_include=True): + from rd_ap_2024.tupling.hlt2 import TUPLES_ALG_BINDING as TUPLE_ALG_BIND_hlt2 + from rd_ap_2024.tupling.hlt2 import merge_dicts_list + all_binds = [] + if hlt2_include: + all_binds += [TUPLE_ALG_BIND_hlt2] + + return merge_dicts_list(all_binds) +# ----------------------------------------- +def KNOWN_EVENT_TYPES_CONFIG_TO_LINES() -> dict[str, set[str]]: + ''' + You must have entries for each name provided in info.yaml here and existing lines defined by algorithms + ''' + d_evt_line : dict[str, set[str]]= { + #EWP MM/EE modes K* ee/mm + "Bd_KstMM" : { + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_LbToPKJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToPipPimMuMu", + }, + "Bd_JPsiKst_MM": { + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_LbToPKJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToPipPimMuMu", + }, + "Bd_Psi2SKst_MM" : { + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_LbToPKJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToPipPimMuMu", + }, + #EWP MM/EE modes K* ee/mm + "Bd_KstEE" : { + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + "Hlt2RD_LbToPKJpsi_JpsiToEE", + # + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToPipPimEE" + }, + "Bd_JPsiKst_EE": { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_LbToPKJpsi_JpsiToEE", + # + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToPipPimEE", + }, + "Bd_JPsiX_EE": { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_LbToPKJpsi_JpsiToEE", + # + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToPipPimEE", + }, + "Bd_Psi2SKst_EE" : { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_LbToPKJpsi_JpsiToEE", + # + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToPipPimEE" + "Hlt2RD_BuToKpEE", + }, + #EWP MM/EE modes K ee/mm + "Bu_KMM" : { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToKpKmMuMu", + }, + "Bu_JPsiK_MM": { + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + # + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + }, + "Bu_JPsiPi_MM" : { + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + # + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToKpKmMuMu", + }, + "Bu_Psi2SK_MM" : { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToKpKmMuMu", + }, + #EWP MM/EE modes K ee/mm + "Bu_KEE" : { + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToPipPimEE" + }, + "Bu_JPsiX_EE" : { + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToPipPimEE" + }, + "Bu_JPsiK_EE": { + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToPipPimEE", + }, + "Bu_Psi2SK_EE" : { + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToPipPimEE" + }, + #EWP MM/EE modes K ee/mm + "Bd_JPsiX_MM": { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_LbToPKJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToPipPimMuMu", + }, + "Bu_JPsiX_MM": { + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + }, + "Bu_JPsiPi_EE": { + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToPipPimEE", + }, + "Bu_JPsiKPiPi_EE": { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + "Hlt2RD_BuToKpJpsi_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToPipPimEE" + }, + "Bu_JPsiKPiPi_MM": { + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToPipPimMuMu", + }, + "Bs_JPsiPhi_MM": { + "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + # + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToPipPimMuMu", + }, + "Bs_JPsiPhi_EE": { + "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE" + "Hlt2RD_BuToKpJpsi_JpsiToEE", + # + "Hlt2RD_BuToKpEE", + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpPimEE", + }, + "Lb_JPsiPK_MM": { + "Hlt2RD_LbToPKJpsi_JpsiToMuMu", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu" + }, + "Lb_JPsiPK_EE": { + "Hlt2RD_LbToPKJpsi_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE" + }, + "Lb_JPsiLz_MM": { + "Hlt2RD_BdToKSMuMu_LL", + "Hlt2RD_BdToKSMuMu_DD", + "Hlt2RD_LbToLMuMu_LL", + "Hlt2RD_LbToLMuMu_DD", + }, + "Lb_JPsiLz_EE": { + "Hlt2RD_BdToKSEE_LL", + "Hlt2RD_BdToKSEE_DD", + "Hlt2RD_LbToLEE_LL", + "Hlt2RD_LbToLEE_DD", + }, + "Data" : None} + + d_evt_line = _update_with_btoxll_mva_lines(d_evt_line) + + return d_evt_line +# ----------------------------------------- +def _get_xll_mva_config() -> dict: + ap_base = os.environ['ANALYSIS_PRODUCTIONS_BASE'] + yaml_path = f'{ap_base}/rd_ap_2024/tupling/config/b_to_xll_mva.yaml' + with open(yaml_path, encoding='utf-8') as ifile: + cfg = yaml.safe_load(ifile) + + return cfg +# ----------------------------------------- +def _update_with_btoxll_mva_lines(d_evt_line : dict[str, set[str]]) -> dict[str,set[str]]: + cfg = _get_xll_mva_config() + + d_copy = copy.deepcopy(d_evt_line) + + log.info(30 * '-') + log.info('Adding lines for b_to_xll_mva ntupling') + log.info(30 * '-') + for proc, s_line in d_evt_line.items(): + if proc not in cfg['processes']: + log.debug(f'Not adding {proc} lines for b_to_xll MC') + continue + + log.info(f'{"":<4}{proc:<70}') + l_mva_line = _get_xll_mva_lines(cfg, proc) + s_mva_line = set(l_mva_line) + for mva_line in s_mva_line: + log.info(f'{"":<8}{mva_line:<70}') + + d_copy[proc] = s_line | s_mva_line + + log.info(30 * '-') + + return d_copy +# ----------------------------------------- +def _get_xll_mva_lines(cfg : dict, proc : str) -> list[str]: + l_line_org : list[str] = cfg['processes'][proc] + l_line_new : list[str] = list(l_line_org) + + for line in l_line_org: + d_line = cfg[line] + if 'custom' not in d_line: + continue + + l_line_new += list( d_line['custom'] ) + + return l_line_new +# ----------------------------------------- +def KNOWN_EVENT_TYPES_CONFIG_TO_LINES_NAMES() -> set[str]: + d_val = KNOWN_EVENT_TYPES_CONFIG_TO_LINES() + return set(d_val) +# ----------------------------------------- +def KNOWN_STREAMS(): + _known_streams_ = [ + "Turbo", + "Full", + "TurCal", + "TurCal_RawBanks", + "TurCal_MDST", + "TurCal_PersistReco", + "TurCal_PersistRecoRawBanks", + "MCDTONLY" + ] + return _known_streams_ +# ----------------------------------------- +class Config: + ''' + Class used to store configurations + ''' + def __init__(self, etype: str, stream: str, isMC: bool , DataPeriod : str = "" ): + print("##############################################") + print(f"Config.etype = {etype}") + print(f"Config.stream = {stream}") + print(f"Config.isMC = {isMC}") + print(f"Config.dPeriod= {DataPeriod}") + print("##############################################") + if etype not in KNOWN_EVENT_TYPES_CONFIG_TO_LINES_NAMES(): + raise ValueError(f'Invalid event type {etype} not found among line names') + + if stream not in KNOWN_STREAMS(): + raise ValueError(f'Invalid stream: {stream}') + + self.mcflag = isMC + self.etypename = etype + self.streamconf = stream + """ + Different Sprucing used different Moore releases where decay descriptors + were bug-fixed. You need to check Moore Versions used and line-descriptors to make + checks and adapt the hlt2.py lines used around. + """ + assert( DataPeriod in [ "Sprucing24c1", "Sprucing24c2", "Sprucing24c3", "Sprucing24c4"]) + self.dPeriod = DataPeriod + + def __str__(self): + return f"# etypename = {self.etypename} , streamconf = {self.streamconf} , mcflag = {self.mcflag} , dperiod = {self.dPeriod}" + + def __repr__(self): + return f"# etypename = {self.etypename} , streamconf = {self.streamconf} , mcflag = {self.mcflag} , dperiod = {self.dPeriod}" + + def dataPeriod(self) -> str : + return self.dPeriod + + def isTurbo(self) -> bool: + return self.streamconf == "Turbo" + + def isFull(self) -> bool: + return self.streamconf == "Full" + + def isTurCal(self) -> bool: + return "TurCal" in self.streamconf + + def TurCalType(self) -> str: + return self.streamconf + def isTurCalRawBanks(self) -> bool : + #TODO : should we enforce "data" ? + return self.isTurCal() and self.TurCalType() == "TurCal_RawBanks" + + def isMC(self) -> bool: + return self.mcflag + + def isData(self) -> bool: + return not self.mcflag + + def SampleNameID(self) -> str : + return self.etypename + + def MCDTONLY(self) -> bool : + return "MCDTONLY" in self.streamconf and self.isMC() diff --git a/rd_ap_2024/tupling/MCDecayTree.py b/rd_ap_2024/tupling/MCDecayTree.py new file mode 100644 index 0000000000000000000000000000000000000000..26789de39faf6c81796e73d7217919af13984230 --- /dev/null +++ b/rd_ap_2024/tupling/MCDecayTree.py @@ -0,0 +1,3137 @@ +from rd_ap_2024.utils.log_store import LogStore + +from PyConf.reading import (get_particles, + get_pvs, + get_rec_summary, + get_mc_particles, + get_mc_track_info, + get_mc_header, + get_mc_vertices) +from RecoConf.event_filters import require_pvs +from DaVinci import make_config, Options +from DaVinci.algorithms import create_lines_filter +from FunTuple import FunTuple_Particles as Funtuple +from FunTuple import FunTuple_MCParticles as MCFuntuple +from FunTuple import FunTuple_Event as EventFuntuple +from FunTuple import FunctorCollection +import FunTuple.functorcollections as FC +import Functors as F +from rd_ap_2024.tupling.Config import Config, KNOWN_EVENT_TYPES_CONFIG_TO_LINES +from DaVinciMCTools import MCReconstructible as MCRectible +from DaVinciMCTools import MCReconstructed as MCRected +from PyConf.reading import get_mc_particles, get_pp2mcp_relations + +from rd_ap_2024.tupling.variables.rd_stream_tupling_functions import Hlt1_decisions as HLT1_LINES + + +logger=LogStore.add_logger('rd_ap_2024:MCDecayTree') + +def get_collections_mcevent( config :Config ) -> FunctorCollection : + mc_header = get_mc_header() + mc_evt_vars = FunctorCollection() + mc_evt_collections = [ + FC.EventInfo(), + FC.MCPrimaries(mc_header=mc_header), + ] + + hlt1_lines_run_on_MC = HLT1_LINES + all_hlt2_lines_for_mcs = KNOWN_EVENT_TYPES_CONFIG_TO_LINES() + hlt2_lines_run_on_KnownMCs = [] + for dec_mode in all_hlt2_lines_for_mcs : + if all_hlt2_lines_for_mcs[dec_mode] is None : continue + hlt2_lines_run_on_KnownMCs += [ _ for _ in all_hlt2_lines_for_mcs[dec_mode] ] + + dec_variables = FC.SelectionInfo(selection_type="Hlt1", trigger_lines=hlt1_lines_run_on_MC) + dec_variables += FC.SelectionInfo(selection_type="Hlt2", trigger_lines=hlt2_lines_run_on_KnownMCs) + + + for coll in mc_evt_collections: + mc_evt_vars += coll + mc_evt_vars += dec_variables + return mc_evt_vars + +def get_collections_mcparticle( config : Config ) -> FunctorCollection: + + # mc_data = get_mc_particles("/Event/HLT2/MC/Particles") + mc_data = get_mc_particles("/Event/HLT2/MC/Particles") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + mcrtible = MCRectible( input_mctrackinfo=get_mc_track_info()) + # TODO : add those + # mcrted_all = MCRected(input_mcparticles=mc_data, use_best_mcmatch=True) + # tes location of MC + # Get variables related to reconstructed information. + # relations_charged = get_pp2mcp_relations("/Event/HLT2/Relations/ChargedPP2MCP") + # relations_neutral = get_pp2mcp_relations("/Event/HLT2/Relations/NeutralPP2MCP") + # mcrted_v2 = MCRected(input_mcparticles=mc_data, use_best_mcmatch=False, + # relations_charged=relations_charged, + # relations_neutral=relations_neutral) + # # TODO : review + # mcrted_all= FC.MCReconstructed( mcreconstructed_alg=mcrted_all, extra_info=True) + # vars_rted = FC.MCReconstructed( mcreconstructed_alg=mcrted_all, extra_info=True) + # vars_rted['EXTRA_TRACK_TYPE[TRACK_INDX]'] = mcrted_all.TrackType + # vars_rted['EXTRA_TRACK_HASUT[TRACK_INDX]'] = mcrted_all.HasUT + + mc_collections = [ + FC.MCReconstructible(mcreconstructible_alg=mcrtible, extra_info=True), + # FC.MCReconstructed( mcreconstructed_alg=mcrted_all, extra_info=True), + # FC.MCReconstructed( mcreconstructed_alg=mcrted_all, extra_info=True), + # FC.MCReconstructed( mcreconstructed_alg=mcrted_v2, extra_info=True), + FC.MCHierarchy(), + FC.MCVertexInfo(), + FC.MCPrimaryVertexInfo(), + FC.MCPromptDecay() + ] + if not config.MCDTONLY() : + relations_charged = get_pp2mcp_relations("/Event/HLT2/Relations/ChargedPP2MCP") + relations_neutral = get_pp2mcp_relations("/Event/HLT2/Relations/NeutralPP2MCP") + # mcrted_all= FC.MCReconstructed( mcreconstructed_alg=mcrted_all, extra_info=True) + mcrted_v2 = MCRected(input_mcparticles=mc_data, use_best_mcmatch=False, + relations_charged=relations_charged, + relations_neutral=relations_neutral) + vars_rted = FC.MCReconstructed( mcreconstructed_alg=mcrted_v2, extra_info=True) + vars_rted['EXTRA_TRACK_TYPE[TRACK_INDX]'] = mcrted_v2.TrackType + vars_rted['EXTRA_TRACK_HASUT[TRACK_INDX]'] = mcrted_v2.HasUT + mc_collections.append( vars_rted) + + mc_field_vars = FunctorCollection() + for coll in mc_collections: + mc_field_vars += coll + + return mc_field_vars + + +""" +def main(options: Options): + line_name = "Hlt2Charm_D0ToKmPip_Line" + mc_data = get_mc_particles("/Event/HLT2/MC/Particles") + mc_header = get_mc_header() + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + # Get variables related to reconstructible information. + mcrtible = MCRectible( + input_mctrackinfo=get_mc_track_info() + ) # tes location of MC track info + + # Get variables related to reconstructed information. + mcrted_all = MCRected(input_mcparticles=mc_data, use_best_mcmatch=True) + + mc_collections = [ + FC.MCReconstructible(mcreconstructible_alg=mcrtible, extra_info=True), + # FC.MCReconstructed(mcreconstructed_alg=mcrted_all, extra_info=False), + FC.MCHierarchy(), + FC.MCVertexInfo(), + FC.MCPromptDecay(), + ] + + + mc_field_vars = FunctorCollection() + for coll in mc_collections: + mc_field_vars += coll + + evt_vars = FunctorCollection() + for coll in evt_collections: + evt_vars += coll + + mc_evt_vars = FunctorCollection() + for coll in mc_evt_collections: + mc_evt_vars += coll + + fields = { + "D0": "[D0 -> K- pi+]CC", + "Kminus": "[D0 -> ^K- pi+]CC", + "piplus": "[D0 -> K- ^pi+]CC", + } + + variables = { + "D0": field_vars, + "Kminus": field_vars, + "piplus": field_vars, + } + + mc_variables = { + "D0": mc_field_vars, + "Kminus": mc_field_vars, + "piplus": mc_field_vars, + } + + my_tuple = Funtuple( + name="Tuple", + tuple_name="DecayTree", + fields=fields, + variables=variables, + event_variables=evt_vars, + inputs=d02kpi_data, + ) + + my_filter = create_lines_filter( + name="HDRFilter_D0Kpi", lines=[f"{line_name}Decision"] + ) + + mc_tuple = MCFuntuple( + name="MCTuple", + tuple_name="DecayTree", + fields=fields, + variables=mc_variables, + event_variables=mc_evt_vars, + inputs=mc_data, + ) + return make_config(options, [my_filter, my_tuple, mc_tuple]) +""" + +#https://gitlab.cern.ch/lhcb-datapkg/AnalysisProductions/-/merge_requests/1288/diffs#2c2e5468393f693dde1c1f049a563b8ed54d19a6_0_66 +### to define this one has to check the associated evt type number of the decay in info.yaml +### NOT a requirement for all modes, just for the ones where we want it + +#https://gitlab.cern.ch/lhcb/DaVinci/-/blob/master/DaVinciExamples/python/DaVinciExamples/tupling/option_davinci_tupling_from_xgen.py + +def bind_sampleID(name): + def decorator(func): + func.sampleID = name + return func + return decorator + + +########## +# B-> JPsi (mumu) K*0 +# B-> Psi2S(mumu) K*0 +# B-> mu mu K*0 +########## +@bind_sampleID("Bd_JPsiKst_MM") +def Bd_JPsiKst_MM_MCDT(options: Options, config : Config): + modename = "Bd_JPsiKst_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[[B0]CC => (J/psi(1S) => mu+ mu-) ([K*(892)0]CC => K+ pi-)]CC", + "Jpsi": "[[B0]CC => ^(J/psi(1S) => mu+ mu-) ([K*(892)0]CC => K+ pi-)]CC", + "M1" : "[[B0]CC => (J/psi(1S) => ^mu+ mu-) ([K*(892)0]CC => K+ pi-)]CC", + "M2" : "[[B0]CC => (J/psi(1S) => mu+ ^mu-) ([K*(892)0]CC => K+ pi-)]CC", + "Kst" : "[[B0]CC => (J/psi(1S) => mu+ mu-) ^([K*(892)0]CC => K+ pi-)]CC", + "K" : "[[B0]CC => (J/psi(1S) => mu+ mu-) ([K*(892)0]CC => ^K+ pi-)]CC", + "Pi" : "[[B0]CC => (J/psi(1S) => mu+ mu-) ([K*(892)0]CC => K+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "Kst" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bd_Psi2SKst_MM") +def Bd_Psi2SKst_MM_MCDT(options: Options, config : Config): + modename = "Bd_Psi2SKst_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[[B0]CC => (psi(2S) => mu+ mu-) ([K*(892)0]CC => K+ pi-)]CC", + "Psi" : "[[B0]CC => ^(psi(2S) => mu+ mu-) ([K*(892)0]CC => K+ pi-)]CC", + "M1" : "[[B0]CC => (psi(2S) => ^mu+ mu-) ([K*(892)0]CC => K+ pi-)]CC", + "M2" : "[[B0]CC => (psi(2S) => mu+ ^mu-) ([K*(892)0]CC => K+ pi-)]CC", + "Kst" : "[[B0]CC => (psi(2S) => mu+ mu-) ^([K*(892)0]CC => K+ pi-)]CC", + "K" : "[[B0]CC => (psi(2S) => mu+ mu-) ([K*(892)0]CC => ^K+ pi-)]CC", + "Pi" : "[[B0]CC => (psi(2S) => mu+ mu-) ([K*(892)0]CC => K+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Psi" : vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "Kst" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bd_KstMM") +def Bd_KstMM_MCDT(options: Options, config : Config): + modename = "Bd_KstMM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[[B0]CC => mu+ mu- ([K*(892)0]CC => K+ pi-)]CC", + "M1" : "[[B0]CC => ^mu+ mu- ([K*(892)0]CC => K+ pi-)]CC", + "M2" : "[[B0]CC => mu+ ^mu- ([K*(892)0]CC => K+ pi-)]CC", + "Kst" : "[[B0]CC => mu+ mu- ^([K*(892)0]CC => K+ pi-)]CC", + "K" : "[[B0]CC => mu+ mu- ([K*(892)0]CC => ^K+ pi-)]CC", + "Pi" : "[[B0]CC => mu+ mu- ([K*(892)0]CC => K+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "Kst" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bd_KstMM_FlatQ2") +def Bd_KstMM_FlatQ2(options: Options, config : Config): + return Bd_KstMM_MCDT(options, config) + + +########## + + + +########## +# B-> JPsi (ee) K*0 +# B-> Psi2S(ee) K*0 +# B-> ee K*0 +########## +@bind_sampleID("Bd_JPsiKst_EE") +def Bd_JPsiKst_EE_MCDT(options: Options, config : Config): + modename = "Bd_JPsiKst_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[[B0]CC => (J/psi(1S) => e+ e-) ([K*(892)0]CC => K+ pi-)]CC", + "Jpsi": "[[B0]CC => ^(J/psi(1S) => e+ e-) ([K*(892)0]CC => K+ pi-)]CC", + "E1" : "[[B0]CC => (J/psi(1S) => ^e+ e-) ([K*(892)0]CC => K+ pi-)]CC", + "E2" : "[[B0]CC => (J/psi(1S) => e+ ^e-) ([K*(892)0]CC => K+ pi-)]CC", + "Kst" : "[[B0]CC => (J/psi(1S) => e+ e-) ^([K*(892)0]CC => K+ pi-)]CC", + "K" : "[[B0]CC => (J/psi(1S) => e+ e-) ([K*(892)0]CC => ^K+ pi-)]CC", + "Pi" : "[[B0]CC => (J/psi(1S) => e+ e-) ([K*(892)0]CC => K+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "Kst": vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bd_Psi2SKst_EE") +def Bd_Psi2SKst_EE_MCDT(options: Options, config : Config): + modename = "Bd_Psi2SKst_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[[B0]CC => (psi(2S) => e+ e-) ([K*(892)0]CC => K+ pi-)]CC", + "Psi": "[[B0]CC => ^(psi(2S) => e+ e-) ([K*(892)0]CC => K+ pi-)]CC", + "E1" : "[[B0]CC => (psi(2S) => ^e+ e-) ([K*(892)0]CC => K+ pi-)]CC", + "E2" : "[[B0]CC => (psi(2S) => e+ ^e-) ([K*(892)0]CC => K+ pi-)]CC", + "Kst" : "[[B0]CC => (psi(2S) => e+ e-) ^([K*(892)0]CC => K+ pi-)]CC", + "K" : "[[B0]CC => (psi(2S) => e+ e-) ([K*(892)0]CC => ^K+ pi-)]CC", + "Pi" : "[[B0]CC => (psi(2S) => e+ e-) ([K*(892)0]CC => K+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Psi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "Kst": vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bd_KstEE") +def Bd_KstEE_MCDT(options: Options, config : Config): + modename = "Bd_KstEE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[[B0]CC => e+ e- ([K*(892)0]CC => K+ pi-)]CC", + "E1" : "[[B0]CC => ^e+ e- ([K*(892)0]CC => K+ pi-)]CC", + "E2" : "[[B0]CC => e+ ^e- ([K*(892)0]CC => K+ pi-)]CC", + "Kst" : "[[B0]CC => e+ e- ^([K*(892)0]CC => K+ pi-)]CC", + "K" : "[[B0]CC => e+ e- ([K*(892)0]CC => ^K+ pi-)]CC", + "Pi" : "[[B0]CC => e+ e- ([K*(892)0]CC => K+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "Kst": vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +########## +# B-> JPsi (ee) K+ +# B-> Psi2S(ee) K+ +# B-> ee K+ +########## +@bind_sampleID("Bu_JPsiK_EE") +def Bu_JPsiK_EE_MCDT(options: Options, config : Config): + modename = "Bu_JPsiK_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => (J/psi(1S) => e+ e-) K+ ]CC", + "Jpsi": "[B+ => ^(J/psi(1S) => e+ e-) K+ ]CC", + "E1" : "[B+ => (J/psi(1S) => ^e+ e-) K+ ]CC", + "E2" : "[B+ => (J/psi(1S) => e+ ^e-) K+ ]CC", + "K" : "[B+ => (J/psi(1S) => e+ e-) ^K+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_Psi2SK_EE") +def Bu_Psi2SK_EE_MCDT(options: Options, config : Config): + modename = "Bu_Psi2SK_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => (psi(2S) => e+ e-) K+ ]CC", + "Psi" : "[B+ => ^(psi(2S) => e+ e-) K+ ]CC", + "E1" : "[B+ => (psi(2S) => ^e+ e-) K+ ]CC", + "E2" : "[B+ => (psi(2S) => e+ ^e-) K+ ]CC", + "K" : "[B+ => (psi(2S) => e+ e-) ^K+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Psi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_KEE") +def Bu_KEE_MCDT(options: Options, config : Config): + modename = "Bu_KEE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => e+ e- K+ ]CC", + "E1" : "[B+ => ^e+ e- K+ ]CC", + "E2" : "[B+ => e+ ^e- K+ ]CC", + "K" : "[B+ => e+ e- ^K+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_JPsiPi_EE") +def Bu_JPsiPi_EE_MCDT(options: Options, config : Config): + modename = "Bu_JPsiPi_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => (J/psi(1S) => e+ e-) K+ ]CC", + "Jpsi": "[B+ => ^(J/psi(1S) => e+ e-) K+ ]CC", + "E1" : "[B+ => (J/psi(1S) => ^e+ e-) K+ ]CC", + "E2" : "[B+ => (J/psi(1S) => e+ ^e-) K+ ]CC", + "Pi" : "[B+ => (J/psi(1S) => e+ e-) ^pi+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +########## +# B-> JPsi (mu mu) K+ +# B-> Psi2S(mu mu) K+ +# B-> mu mu K+ +########## +@bind_sampleID("Bu_JPsiK_MM") +def Bu_JPsiK_MM_MCDT(options: Options, config : Config): + modename = "Bu_JPsiK_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => (J/psi(1S) => mu+ mu-) K+ ]CC", + "Jpsi": "[B+ => ^(J/psi(1S) => mu+ mu-) K+ ]CC", + "M1" : "[B+ => (J/psi(1S) => ^mu+ mu-) K+ ]CC", + "M2" : "[B+ => (J/psi(1S) => mu+ ^mu-) K+ ]CC", + "K" : "[B+ => (J/psi(1S) => mu+ mu-) ^K+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("Bu_JPsiPi_MM") +def Bu_JPsiPi_MM_MCDT(options: Options, config : Config): + modename = "Bu_JPsiPi_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => (J/psi(1S) => mu+ mu-) pi+ ]CC", + "Jpsi": "[B+ => ^(J/psi(1S) => mu+ mu-) pi+ ]CC", + "M1" : "[B+ => (J/psi(1S) => ^mu+ mu-) pi+ ]CC", + "M2" : "[B+ => (J/psi(1S) => mu+ ^mu-) pi+ ]CC", + "Pi" : "[B+ => (J/psi(1S) => mu+ mu-) ^pi+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_Psi2SK_MM") +def Bu_Psi2SK_MM_MCDT(options: Options, config : Config): + modename = "Bu_Psi2SK_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B+ => (psi(2S) => mu+ mu-) K+ ]CC", + "Psi": "[B+ => ^(psi(2S) => mu+ mu-) K+ ]CC", + "M1" : "[B+ => (psi(2S) => ^mu+ mu-) K+ ]CC", + "M2" : "[B+ => (psi(2S) => mu+ ^mu-) K+ ]CC", + "K" : "[B+ => (psi(2S) => mu+ mu-) ^K+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Psi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_KMM") +def Bu_KMM_MCDT(options: Options, config : Config): + modename = "Bu_KMM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B+ => mu+ mu- K+ ]CC", + "M1" : "[B+ => ^mu+ mu- K+ ]CC", + "M2" : "[B+ => mu+ ^mu- K+ ]CC", + "K" : "[B+ => mu+ mu- ^K+ ]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_KMM_PHSP") +def Bu_KMM_PHSP(options: Options, config : Config): + return Bu_KMM_MCDT(options, config ) + + +########## +# B0 -> JPsi (mu mu) KS +# B0 -> JPsi (e e) KS +########## +@bind_sampleID("Bd_JPsiKS_MM") +def Bd_JPsiKS_MM_MCDT(options: Options, config : Config): + modename = "Bd_JPsiKS_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B0]CC => (J/psi(1S) => mu+ mu-) (KS0 => pi+ pi-)", + "Jpsi": "[B0]CC => ^(J/psi(1S) => mu+ mu-) (KS0 => pi+ pi-)", + "M1" : "[B0]CC => (J/psi(1S) => ^mu+ mu-) (KS0 => pi+ pi-)", + "M2" : "[B0]CC => (J/psi(1S) => mu+ ^mu-) (KS0 => pi+ pi-)", + "KS" : "[B0]CC => (J/psi(1S) => mu+ mu-) ^(KS0 => pi+ pi-)", + "Pi1" : "[B0]CC => (J/psi(1S) => mu+ mu-) (KS0 => ^pi+ pi-)", + "Pi2" : "[B0]CC => (J/psi(1S) => mu+ mu-) (KS0 => pi+ ^pi-)", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "KS": vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("Bd_JPsiKS_EE") +def Bd_JPsiKS_EE_MCDT(options: Options, config : Config): + modename = "Bd_JPsiKS_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + + FIELDS = { + "B" : "[B0]CC => (J/psi(1S) => e+ e-) (KS0 => pi+ pi-)", + "Jpsi": "[B0]CC => ^(J/psi(1S) => e+ e-) (KS0 => pi+ pi-)", + "E1" : "[B0]CC => (J/psi(1S) => ^e+ e-) (KS0 => pi+ pi-)", + "E2" : "[B0]CC => (J/psi(1S) => e+ ^e-) (KS0 => pi+ pi-)", + "KS" : "[B0]CC => (J/psi(1S) => e+ e-) ^(KS0 => pi+ pi-)", + "Pi1" : "[B0]CC => (J/psi(1S) => e+ e-) (KS0 => ^pi+ pi-)", + "Pi2" : "[B0]CC => (J/psi(1S) => e+ e-) (KS0 => pi+ ^pi-)", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "KS": vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +########## +# Bs_0 -> JPsi (mumu) Phi(KK) +# Bs_0 -> JPsi (ee) Phi(KK) +########## +@bind_sampleID("Bs_JPsiPhi_MM") +def Bs_JPsiPhi_MM_MCDT( options: Options, config : Config): + modename = "Bs_JPsiPhi_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B_s0]CC => (J/psi(1S) => mu+ mu-) (phi(1020) => K+ K-)", + "Jpsi": "[B_s0]CC => ^(J/psi(1S) => mu+ mu-) (phi(1020) => K+ K-)", + "Phi" : "[B_s0]CC => (J/psi(1S) => mu+ mu-) ^(phi(1020) => K+ K-)", + "M1" : "[B_s0]CC => (J/psi(1S) => ^mu+ mu-) (phi(1020) => K+ K-)", + "M2" : "[B_s0]CC => (J/psi(1S) => mu+ ^mu-) (phi(1020) => K+ K-)", + "K1" : "[B_s0]CC => (J/psi(1S) => mu+ mu-) (phi(1020) => ^K+ K-)", + "K2" : "[B_s0]CC => (J/psi(1S) => mu+ mu-) (phi(1020) => K+ ^K-)", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "Phi" : vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "K1" : vars + get_collections_mcparticle( config ), + "K2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bs_JPsiPhi_MM_CPV_Update2016_DG0") +def Bs_JPsiPhi_MM_MCDT( options: Options, config : Config): + return Bs_JPsiPhi_MM_MCDT( options, config) +@bind_sampleID("Bs_JPsiPhi_MM_CPV_Update2016") +def Bs_JPsiPhi_MM_CPV_Update2016( options: Options, config : Config): + return Bs_JPsiPhi_MM_MCDT( options, config) + + +@bind_sampleID("Bs_JPsiPhi_EE") +def Bs_JPsiPhi_EE_MCDT( options: Options, config : Config): + modename = "Bs_JPsiPhi_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B_s0]CC => (J/psi(1S) => e+ e-) (phi(1020) => K+ K-)", + "Jpsi": "[B_s0]CC => ^(J/psi(1S) => e+ e-) (phi(1020) => K+ K-)", + "Phi" : "[B_s0]CC => (J/psi(1S) => e+ e-) ^(phi(1020) => K+ K-)", + "E1" : "[B_s0]CC => (J/psi(1S) => ^e+ e-) (phi(1020) => K+ K-)", + "E2" : "[B_s0]CC => (J/psi(1S) => e+ ^e-) (phi(1020) => K+ K-)", + "K1" : "[B_s0]CC => (J/psi(1S) => e+ e-) (phi(1020) => ^K+ K-)", + "K2" : "[B_s0]CC => (J/psi(1S) => e+ e-) (phi(1020) => K+ ^K-)", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "Phi" : vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "K1" : vars + get_collections_mcparticle( config ), + "K2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +########## +# B+ -> JPsi (mumu) K pi pi +# B+ -> JPsi (ee) K pi pi +########## +@bind_sampleID("Bu_JPsiKPiPi_MM") +def Bu_JPsiKPiPi_MM_MCDT( options: Options, config : Config): + modename = "Bu_JPsiKPiPi_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B+ => (J/psi(1S) => mu+ mu-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "Jpsi": "[B+ => ^(J/psi(1S) => mu+ mu-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "M1" : "[B+ => (J/psi(1S) => ^mu+ mu-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "M2" : "[B+ => (J/psi(1S) => mu+ ^mu-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "K1270" : "[B+ => (J/psi(1S) => mu+ mu-) ^(K_1(1270)+ => K+ pi+ pi-)]CC", + "K" : "[B+ => (J/psi(1S) => mu+ mu-) (K_1(1270)+ => ^K+ pi+ pi-)]CC", + "Pi1" : "[B+ => (J/psi(1S) => mu+ mu-) (K_1(1270)+ => K+ ^pi+ pi-)]CC", + "Pi2" : "[B+ => (J/psi(1S) => mu+ mu-) (K_1(1270)+ => K+ pi+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "K1270" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bu_JPsiKPiPi_EE") +def Bu_JPsiKPiPi_EE_MCDT( options : Options, config:Config): + modename = "Bu_JPsiKPiPi_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B+ => (J/psi(1S) => e+ e-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "Jpsi": "[B+ => ^(J/psi(1S) => e+ e-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "E1" : "[B+ => (J/psi(1S) => ^e+ e-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "E2" : "[B+ => (J/psi(1S) => e+ ^e-) (K_1(1270)+ => K+ pi+ pi-)]CC", + "K1270" : "[B+ => (J/psi(1S) => e+ e-) ^(K_1(1270)+ => K+ pi+ pi-)]CC", + "K" : "[B+ => (J/psi(1S) => e+ e-) (K_1(1270)+ => ^K+ pi+ pi-)]CC", + "Pi1" : "[B+ => (J/psi(1S) => e+ e-) (K_1(1270)+ => K+ ^pi+ pi-)]CC", + "Pi2" : "[B+ => (J/psi(1S) => e+ e-) (K_1(1270)+ => K+ pi+ ^pi-)]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "K1270" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +########## +# Lb -> JPsi(mumu) p K +# Lb -> JPsi(ee) p K +########## +@bind_sampleID("Lb_JPsiPK_MM") +def Lb_JPsiPK_MM_MCDT( options: Options, config : Config): + modename = "Lb_JPsiPK_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lb" :"[ [Lambda_b0]CC => (J/psi(1S) => mu+ mu-) p+ K- ]CC", + "Jpsi": "[ [Lambda_b0]CC => ^(J/psi(1S) => mu+ mu-) p+ K- ]CC", + "M1" : "[ [Lambda_b0]CC => (J/psi(1S) => ^mu+ mu-) p+ K- ]CC", + "M2" : "[ [Lambda_b0]CC => (J/psi(1S) => mu+ ^mu-) p+ K- ]CC", + "P" : "[ [Lambda_b0]CC => (J/psi(1S) => mu+ mu-) ^p+ K- ]CC", + "K" : "[ [Lambda_b0]CC => (J/psi(1S) => mu+ mu-) p+ ^K- ]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lb" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "M1" : vars + get_collections_mcparticle( config ), + "M2" : vars + get_collections_mcparticle( config ), + "P" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("Lb_JPsiPK_EE") +def Lb_JPsiPK_EE_MCDT( options: Options, config : Config): + modename = "Lb_JPsiPK_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lb" : "[ [Lambda_b0]CC => (J/psi(1S) => e+ e-) p+ K- ]CC", + "Jpsi": "[ [Lambda_b0]CC => ^(J/psi(1S) => e+ e-) p+ K- ]CC", + "E1" : "[ [Lambda_b0]CC => (J/psi(1S) => ^e+ e-) p+ K- ]CC", + "E2" : "[ [Lambda_b0]CC => (J/psi(1S) => e+ ^e-) p+ K- ]CC", + "P" : "[ [Lambda_b0]CC => (J/psi(1S) => e+ e-) ^p+ K- ]CC", + "K" : "[ [Lambda_b0]CC => (J/psi(1S) => e+ e-) p+ ^K- ]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lb" : vars + get_collections_mcparticle( config ), + "Jpsi": vars + get_collections_mcparticle( config ), + "E1" : vars + get_collections_mcparticle( config ), + "E2" : vars + get_collections_mcparticle( config ), + "P" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +########## +# Lb -> JPsi(mumu) Lambda +# Lb -> JPsi(ee) Lambda +########## +@bind_sampleID("Lb_JPsiLz_MM") +def Lb_JPsiLz_MM_MCDT(options: Options, config: Config): + modename = "Lb_JPsiLz_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lb" :"[Lambda_b0]CC => (J/psi(1S) => mu+ mu-) ([Lambda0]CC => p+ pi-)", + "Jpsi": "[Lambda_b0]CC => ^(J/psi(1S) => mu+ mu-) ([Lambda0]CC => p+ pi-)", + "M1" : "[Lambda_b0]CC => (J/psi(1S) => ^mu+ mu-) ([Lambda0]CC => p+ pi-)", + "M2" : "[Lambda_b0]CC => (J/psi(1S) => mu+ ^mu-) ([Lambda0]CC => p+ pi-)", + "Lz" : "[Lambda_b0]CC => (J/psi(1S) => mu+ mu-) ^([Lambda0]CC => p+ pi-)", + "P" : "[Lambda_b0]CC => (J/psi(1S) => mu+ mu-) ([Lambda0]CC => ^p+ pi-)", + "Pi" : "[Lambda_b0]CC => (J/psi(1S) => mu+ mu-) ([Lambda0]CC => p+ ^pi-)" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lb" : vars + get_collections_mcparticle( config ) , + "Jpsi" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + "Lz" : vars + get_collections_mcparticle( config ) , + "P" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Lb_JPsiLz_EE") +def Lb_JPsiLz_EE_MCDT(options: Options, config: Config): + modename = "Lb_JPsiLz_EE" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lb" :"[Lambda_b0]CC => (J/psi(1S) => e+ e-) ([Lambda0]CC => p+ pi-)", + "Jpsi": "[Lambda_b0]CC => ^(J/psi(1S) => e+ e-) ([Lambda0]CC => p+ pi-)", + "E1" : "[Lambda_b0]CC => (J/psi(1S) => ^e+ e-) ([Lambda0]CC => p+ pi-)", + "E2" : "[Lambda_b0]CC => (J/psi(1S) => e+ ^e-) ([Lambda0]CC => p+ pi-)", + "Lz" : "[Lambda_b0]CC => (J/psi(1S) => e+ e-) ^([Lambda0]CC => p+ pi-)", + "P" : "[Lambda_b0]CC => (J/psi(1S) => e+ e-) ([Lambda0]CC => ^p+ pi-)", + "Pi" : "[Lambda_b0]CC => (J/psi(1S) => e+ e-) ([Lambda0]CC => p+ ^pi-)" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lb" : vars + get_collections_mcparticle( config ) , + "Jpsi" : vars + get_collections_mcparticle( config ) , + "E1" : vars + get_collections_mcparticle( config ) , + "E2" : vars + get_collections_mcparticle( config ) , + "Lz" : vars + get_collections_mcparticle( config ) , + "P" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +########## +# Upsilon(1S) -> mu mu +# Upsilon(2S) -> mu mu +# Upsilon(3S) -> mu mu +########## +@bind_sampleID("incl_Upsilon1S_MM") +def incl_Upsilon1S_MM_MCDT(options: Options, config: Config): + modename = "incl_Upsilon1S_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Upsilon1s" :"Upsilon(1S) => mu+ mu-", + "M1" :"Upsilon(1S) => ^mu+ mu-", + "M2" :"Upsilon(1S) => mu+ ^mu-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Upsilon1s" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("incl_Upsilon2S_MM") +def incl_Upsilon2S_MM_MCDT(options: Options, config: Config): + modename = "incl_Upsilon2S_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Upsilon" :"Upsilon(2S) => mu+ mu-", + "M1" :"Upsilon(2S) => ^mu+ mu-", + "M2" :"Upsilon(2S) => mu+ ^mu-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Upsilon" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("incl_Upsilon3S_MM") +def incl_Upsilon3S_MM_MCDT(options: Options, config: Config): + modename = "incl_Upsilon3S_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Upsilon" :"Upsilon(3S) => mu+ mu-", + "M1" :"Upsilon(3S) => ^mu+ mu-", + "M2" :"Upsilon(3S) => mu+ ^mu-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Upsilon" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +########## +# Jpsi -> mu mu +######### +@bind_sampleID("incl_JPsi_MM") +def incl_JPsi_MM_MCDT(options: Options, config: Config, mode_name : str = None ): + modename = "incl_JPsi_MM" if mode_name is None else mode_name + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Jpsi" :"J/psi(1S) => mu+ mu-", + "M1" :"J/psi(1S) => ^mu+ mu-", + "M2" :"J/psi(1S) => mu+ ^mu-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Jpsi" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("incl_JPsiPrompt_MM") +def incl_JPsiPrompt_MM_MCDT(options: Options, config: Config, mode_name : str = None ): + return incl_JPsi_MM_MCDT( options, config, "incl_JPsiPrompt_MM") + +########## +# Psi -> mu mu +########## +@bind_sampleID("incl_Psi2S_MM") +def incl_Psi2S_MM_MCDT(options: Options, config: Config): + modename = "incl_Psi2S_MM" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Psi2S" :"psi(2S) => mu+ mu-", + "M1" :"psi(2S) => ^mu+ mu-", + "M2" :"psi(2S) => mu+ ^mu-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Psi2S" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + + +@bind_sampleID("Lz_PPi") +def Lz_PPi_MCDT(options: Options, conig: Config, mode_name :str = None ): + modename = "Lz_PPi" if mode_name is None else mode_name + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lz" :"[Lambda0 => pi- p+]CC", + "P" :"[Lambda0 => pi- ^p+]CC", + "Pi" :"[Lambda0 => ^pi- p+]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lz" : vars + get_collections_mcparticle( config ) , + "P" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Lz_PPi_PHSP") +def Lz_PPi_PHSP_MCDT(options: Options, config: Config): + modename = "Lz_PPi_PHSP" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lz" :"[Lambda0 => p+ pi-]CC", + "P" :"[Lambda0 => ^p+ pi-]CC", + "Pi" :"[Lambda0 => p+ ^pi-]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lz" : vars + get_collections_mcparticle( config ) , + "P" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Lz_PPi") +def Lz_PPi_MCDT( options : Options, config: Config): + modename = "Lz_PPi" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lz" :"[Lambda0 => p+ pi-]CC", + "P" :"[Lambda0 => ^p+ pi-]CC", + "Pi" :"[Lambda0 => p+ ^pi-]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lz" : vars + get_collections_mcparticle( config ) , + "P" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) , + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Omega_LambdaK") +def Omega_LambdaK_MCDT( options : Options , config: Config): + modename= "Omega_LambdaK" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Omega" :"[Omega- => (Lambda0 => p+ pi-) K+ ]CC", + "Lz" :"[Omega- => ^(Lambda0 => p+ pi-) K+ ]CC", + "P" :"[Omega- => (Lambda0 => ^p+ pi-) K+ ]CC", + "Pi" :"[Omega- => (Lambda0 => p+ ^pi-) K+ ]CC", + "K" :"[Omega- => (Lambda0 => p+ pi-) ^K+ ]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Omega": vars + get_collections_mcparticle( config ), + "Lz": vars + get_collections_mcparticle( config ), + "P" : vars + get_collections_mcparticle( config ), + "Pi": vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Ks_pipi") +def Ks_pipi_MCDT( options : Options , config: Config): + modename= "Ks_pipi" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "KS" :"KS0 => pi+ pi-", + "Pi1" :"KS0 => ^pi+ pi-", + "Pi2" :"KS0 => pi+ ^pi-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "KS": vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2": vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Dst_D0pi_KPi") +def Dst_D0pi_KPi_MCDT(options: Options, config: Config): + modename = "Dst_D0pi_KPi" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Dst" : "[D*(2010)+ => ([D0]CC => K- pi+) pi+]CC", + "Pis" : "[D*(2010)+ => ([D0]CC => K- pi+) ^pi+]CC", + "D0" : "[D*(2010)+ => ^([D0]CC => K- pi+) pi+]CC", + "K" : "[D*(2010)+ => ([D0]CC => ^K- pi+) pi+]CC", + "Pi" : "[D*(2010)+ => ([D0]CC => K- ^pi+) pi+]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Dst" : vars + get_collections_mcparticle( config ), + "Pis" : vars + get_collections_mcparticle( config ), + "D0" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Dst_D0pi_KPi_TightCut") +def Dst_D0pi_KPi_TightCut_MCDT(options: Options, config: Config): + modename = "Dst_D0pi_KPi_TightCut" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Dst" : "[D*(2010)+ => ([D0]CC => K- pi+) pi+]CC", + "Pis" : "[D*(2010)+ => ([D0]CC => K- pi+) ^pi+]CC", + "D0" : "[D*(2010)+ => ^([D0]CC => K- pi+) pi+]CC", + "K" : "[D*(2010)+ => ([D0]CC => ^K- pi+) pi+]CC", + "Pi" : "[D*(2010)+ => ([D0]CC => K- ^pi+) pi+]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Dst" : vars + get_collections_mcparticle( config ), + "Pis" : vars + get_collections_mcparticle( config ), + "D0" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Dst_D0pi_KK_TightCut") +def Dst_D0pi_KK_TightCut_MCDT(options: Options, config: Config): + modename = "Dst_D0pi_KK_TightCut" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Dst" : "[D*(2010)+ => ([D0]CC => K- K+) pi+]CC", + "Pis" : "[D*(2010)+ => ([D0]CC => K- K+) ^pi+]CC", + "D0" : "[D*(2010)+ => ^([D0]CC => K- K+) pi+]CC", + "K1" : "[D*(2010)+ => ([D0]CC => ^K- K+) pi+]CC", + "K2" : "[D*(2010)+ => ([D0]CC => K- ^K+) pi+]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Dst" : vars + get_collections_mcparticle( config ), + "Pis" : vars + get_collections_mcparticle( config ), + "D0" : vars + get_collections_mcparticle( config ), + "K1" : vars + get_collections_mcparticle( config ), + "K2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("Dst_D0pi_PiPi_TightCut") +def Dst_D0pi_PiPi_TightCut_MCDT(options: Options, config: Config): + modename = "Dst_D0pi_PiPi_TightCut" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Dst" : "[D*(2010)+ => ([D0]CC => pi- pi+) pi+]CC", + "Pis" : "[D*(2010)+ => ([D0]CC => pi- pi+) ^pi+]CC", + "D0" : "[D*(2010)+ => ^([D0]CC => pi- pi+) pi+]CC", + "Pi1" : "[D*(2010)+ => ([D0]CC => ^pi- pi+) pi+]CC", + "Pi2" : "[D*(2010)+ => ([D0]CC => pi- ^pi+) pi+]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Dst" : vars + get_collections_mcparticle( config ), + "Pis" : vars + get_collections_mcparticle( config ), + "D0" : vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("Bs_mumu") +def Bs_mumu_MCDT( options: Options, config : Config): + modename = "Bs_mumu" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B_s0]CC => mu- mu+", + "Mu1" : "[B_s0]CC => ^mu- mu+", + "Mu2" : "[B_s0]CC => mu- ^mu+", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Mu1" : vars + get_collections_mcparticle( config ), + "Mu2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +# Deprecated from previous version, naming clean-up +# @bind_sampleID("B_2mu_Bd_MuMu") +# def B_2mu_Bd_MuMu_MCDT( options: Options, config : Config): +# modename = "B_2mu_Bd_MuMu" +@bind_sampleID("Bd_mumu") +def Bd_mumu_MCDT( options: Options, config : Config): + modename = "Bd_mumu" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B0]CC => mu- mu+", + "Mu1" : "[B0]CC => ^mu- mu+", + "Mu2" : "[B0]CC => mu- ^mu+", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Mu1" : vars + get_collections_mcparticle( config ), + "Mu2" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bs_emu") +def Bs_emu_MCDT( options: Options, config : Config): + modename = "Bs_emu" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[[B_s0]CC => e- mu+]CC", + "E" : "[[B_s0]CC => ^e- mu+]CC", + "Mu" : "[[B_s0]CC => e- ^mu+]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "E" : vars + get_collections_mcparticle( config ), + "Mu" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +# Deprecated from previous version, naming clean-up +# @bind_sampleID("B_2mu_Bd_MuMu") +# def B_2mu_Bd_MuMu_MCDT( options: Options, config : Config): +# modename = "B_2mu_Bd_MuMu" +@bind_sampleID("Bd_emu") +def Bd_emu_MCDT( options: Options, config : Config): + modename = "Bd_emu" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[ [B0]CC => e- mu+]CC", + "E" : "[ [B0]CC => ^e- mu+]CC", + "Mu" : "[ [B0]CC => e- ^mu+]CC", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "E" : vars + get_collections_mcparticle( config ), + "Mu" : vars + get_collections_mcparticle( config ), + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +# Deprecated from previous version, naming clean-up +# @bind_sampleID("B_2mu_Bs_KPi") +# def B_2mu_Bs_KPi_MCDT( options: Options, config : Config): +# modename = "B_2mu_Bs_KPi" +@bind_sampleID("Bs_KPi") +def Bs_KPi_MCDT( options: Options, config : Config): + modename = "Bs_KPi" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[ [B_s0]CC => K+ pi-]CC", + "K" : "[ [B_s0]CC => ^K+ pi-]CC", + "Pi" : "[ [B_s0]CC => K+ ^pi-]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + + +@bind_sampleID("Bd_KPi") +def Bd_KPi_MCDT( options: Options, config : Config): + modename = "Bd_KPi" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[[B0]CC => K+ pi-]CC", + "K" : "[[B0]CC => ^K+ pi-]CC", + "Pi" : "[[B0]CC => K+ ^pi-]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "K" : vars + get_collections_mcparticle( config ), + "Pi" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + + +# +@bind_sampleID("Bs_KK") +def Bs_KK_MCDT( options: Options, config : Config): + modename = "Bs_KK" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B_s0]CC => K+ K-", + "K1" : "[B_s0]CC => ^K+ K-", + "K2" : "[B_s0]CC => K+ ^K-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "K1" : vars + get_collections_mcparticle( config ), + "K2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bd_KK_noCPV") +def Bd_KK_noCPV_MCDT( options: Options, config : Config): + modename = "Bd_KK_noCPV" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B0]CC => K+ K-", + "K1" : "[B0]CC => ^K+ K-", + "K2" : "[B0]CC => K+ ^K-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "K1" : vars + get_collections_mcparticle( config ), + "K2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("Bd_PiPi") +def Bd_PiPi_MCDT( options: Options, config : Config): + modename = "Bd_PiPi" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B0]CC => pi+ pi-", + "Pi1" : "[B0]CC => ^pi+ pi-", + "Pi2" : "[B0]CC => pi+ ^pi-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bs_PiPi_noCPV") +def Bs_PiPi_noCPV_MCDT( options: Options, config : Config): + modename = "Bs_PiPi_noCPV" + assert( config.isMC() ) + assert( config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices( "/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B_s0]CC => pi+ pi-", + "Pi1" : "[B_s0]CC => ^pi+ pi-", + "Pi2" : "[B_s0]CC => pi+ ^pi-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "B" : vars + get_collections_mcparticle( config ), + "Pi1" : vars + get_collections_mcparticle( config ), + "Pi2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("Lb_PPi") +def Lb_PPi_MCDT( options : Options, config : Config): + modename = "Lb_PPi" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lb": "[Lambda_b0 => p+ pi-]CC", + "P" : "[Lambda_b0 => p+ pi-]CC", + "Pi": "[Lambda_b0 => p+ pi-]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lb": vars + get_collections_mcparticle( config ), + "P" : vars + get_collections_mcparticle( config ), + "Pi": vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("Lb_pK") +def Lb_pK_MCDT( options : Options, config : Config): + modename = "Lb_pK" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Lb": "[Lambda_b0 => p+ K-]CC", + "P" : "[Lambda_b0 => p+ K-]CC", + "K": "[Lambda_b0 => p+ K-]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Lb": vars + get_collections_mcparticle( config ), + "P" : vars + get_collections_mcparticle( config ), + "K": vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("InclPsi2JPsiPiPi_EE") +def InclPsi2JPsiPiPi_EE_MCDT( options : Options, config : Config): + modename = "InclPsi2JPsiPiPi_EE" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Psi" : "psi(2S) => (J/psi(1S) => e+ e-) pi+ pi-", + "JPsi": "psi(2S) => ^(J/psi(1S) => e+ e-) pi+ pi-", + "E1" : "psi(2S) => (J/psi(1S) => ^e+ e-) pi+ pi-", + "E2" : "psi(2S) => (J/psi(1S) => e+ ^e-) pi+ pi-", + "Pi1" : "psi(2S) => (J/psi(1S) => e+ e-) ^pi+ pi-", + "Pi2" : "psi(2S) => (J/psi(1S) => e+ e-) pi+ ^pi-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Psi" : vars + get_collections_mcparticle( config ) , + "JPsi": vars + get_collections_mcparticle( config ) , + "E1" : vars + get_collections_mcparticle( config ) , + "E2" : vars + get_collections_mcparticle( config ) , + "Pi1" : vars + get_collections_mcparticle( config ) , + "Pi2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("InclPsi2JPsiPiPi_MM") +def InclPsi2JPsiPiPi_MM_MCDT( options : Options, config : Config): + modename = "InclPsi2JPsiPiPi_MM" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Psi" : "psi(2S) => (J/psi(1S) => mu+ mu- ) pi+ pi-", + "JPsi": "psi(2S) => ^(J/psi(1S)=> mu+ mu- ) pi+ pi-", + "M1" : "psi(2S) => (J/psi(1S) => ^mu+ mu- ) pi+ pi-", + "M2" : "psi(2S) => (J/psi(1S) => mu+ ^mu- ) pi+ pi-", + "Pi1" : "psi(2S) => (J/psi(1S) => mu+ mu- ) ^pi+ pi-", + "Pi2" : "psi(2S) => (J/psi(1S) => mu+ mu- ) pi+ ^pi-" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Psi" : vars + get_collections_mcparticle( config ) , + "JPsi": vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + "Pi1" : vars + get_collections_mcparticle( config ) , + "Pi2" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("InclUpsilon_TauTau") +def InclUpsilon_TauTau_MCDT( options : Options, config : Config): + modename = "InclUpsilon_TauTau" + # evt type has TAUOLA 5 , what descriptor to use? + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + # pi+ pi- pi+ anti-nu_tau + "Upsilon1s" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ nu_tau~) (tau- => pi- pi+ pi- nu_tau)", + "tau_plus" : "Upsilon(1S) => ^(tau+ => pi+ pi- pi+ nu_tau~) (tau- => pi- pi+ pi- nu_tau)", + "Pi1_tau_plus" : "Upsilon(1S) => ^(tau+ => pi+ pi- pi+ nu_tau~) (tau- => pi- pi+ pi- nu_tau)", + "Pi2_tau_plus" : "Upsilon(1S) => (tau+ => pi+ ^pi- pi+ nu_tau~) (tau- => pi- pi+ pi- nu_tau)", + "Pi3_tau_plus" : "Upsilon(1S) => (tau+ => pi+ pi- ^pi+ nu_tau~) (tau- => pi- pi+ pi- nu_tau)", + "Nu_tau_plus" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ ^nu_tau~) (tau- => pi- pi+ pi- nu_tau)", + "tau_minus" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ nu_tau~) ^(tau- => pi- pi+ pi- nu_tau)", + "Pi1_tau_minus" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ nu_tau~) (tau- => ^pi- pi+ pi- nu_tau)", + "Pi2_tau_minus" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ nu_tau~) (tau- => pi- ^pi+ pi- nu_tau)", + "Pi3_tau_minus" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ nu_tau~) (tau- => pi- pi+ ^pi- nu_tau)", + "Nu_tau_minus" : "Upsilon(1S) => (tau+ => pi+ pi- pi+ nu_tau~) (tau- => pi- pi+ pi- ^nu_tau)" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + # pi+ pi- pi+ anti-nu_tau + "Upsilon1s" : vars + get_collections_mcparticle( config ) , + "tau_plus" : vars + get_collections_mcparticle( config ) , + "Pi1_tau_plus" : vars + get_collections_mcparticle( config ) , + "Pi2_tau_plus" : vars + get_collections_mcparticle( config ) , + "Pi3_tau_plus" : vars + get_collections_mcparticle( config ) , + "Nu_tau_plus" : vars + get_collections_mcparticle( config ) , + "tau_minus" : vars + get_collections_mcparticle( config ) , + "Pi1_tau_minus" : vars + get_collections_mcparticle( config ) , + "Pi2_tau_minus" : vars + get_collections_mcparticle( config ) , + "Pi3_tau_minus" : vars + get_collections_mcparticle( config ) , + "Nu_tau_minus" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("Bd_KstG_HighPtG") +def Bd_KstG_HighPtG_MCDT( options : Options, config : Config): + modename = "Bd_KstG_HighPtG" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B0]CC => ( [K*(892)0]CC => K+ pi- ) gamma", + "Kst" : "[B0]CC => ^( [K*(892)0]CC => K+ pi- ) gamma", + "K" : "[B0]CC => ( [K*(892)0]CC => ^K+ pi- ) gamma", + "Pi" : "[B0]CC => ( [K*(892)0]CC => K+ ^pi- ) gamma", + "Gamma" : "[B0]CC => ( [K*(892)0]CC => K+ pi- ) ^gamma", + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + + "B" : vars + get_collections_mcparticle( config), + "Kst" : vars + get_collections_mcparticle( config), + "K" : vars + get_collections_mcparticle( config), + "Pi" : vars + get_collections_mcparticle( config), + "Gamma" : vars + get_collections_mcparticle( config) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bs_PhiG_HighPtG") +def Bs_PhiG_HighPtG_MCDT( options : Options, config : Config): + modename = "Bs_PhiG_HighPtG" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "B" : "[B_s0]CC => (phi(1020) => K+ K-) gamma", + "Phi" : "[B_s0]CC => ^(phi(1020) => K+ K-) gamma", + "K1" : "[B_s0]CC => (phi(1020) => ^K+ K-) gamma", + "K2" : "[B_s0]CC => (phi(1020) => K+ ^K-) gamma", + "Gamma" : "[B_s0]CC => (phi(1020) => K+ K-) ^gamma" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + + "B" : vars + get_collections_mcparticle( config), + "Phi" : vars + get_collections_mcparticle( config), + "K1" : vars + get_collections_mcparticle( config), + "K2" : vars + get_collections_mcparticle( config), + "Gamma" : vars + get_collections_mcparticle( config) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bc_JPsiPi_MM") +def Bc_JPsiPi_MM_MCDT( options : Options, config : Config): + modename = "Bc_JPsiPi_MM" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Bc" : "[B_c+ => (J/psi(1S) => mu+ mu-) pi+]CC", + "Jpsi": "[B_c+ => ^(J/psi(1S) => mu+ mu-) pi+]CC", + "M1" : "[B_c+ => (J/psi(1S) => ^mu+ mu-) pi+]CC", + "M2" : "[B_c+ => (J/psi(1S) => mu+ ^mu-) pi+]CC", + "Pi" : "[B_c+ => (J/psi(1S) => mu+ mu-) ^pi+]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Bc" : vars + get_collections_mcparticle( config ) , + "Jpsi": vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("Bc_PiMM") +def Bc_PiMM_MCDT( options : Options, config : Config): + modename = "Bc_PiMM" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Bc" : "[B_c+ => mu+ mu- pi+]CC", + "M1" : "[B_c+ => ^mu+ mu- pi+]CC", + "M2" : "[B_c+ => mu+ ^mu- pi+]CC", + "Pi" : "[B_c+ => mu+ mu- ^pi+]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Bc" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + "Pi" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +@bind_sampleID("TauTo3Mu_fromB") +def TauTo3Mu_fromB_MCDT( options : Options, config : Config): + modename = "TauTo3Mu_fromB" + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Tau" : "[tau+ => mu+ mu+ mu- ]CC", + "M1" : "[tau+ => ^mu+ mu+ mu- ]CC", + "M2" : "[tau+ => mu+ ^mu+ mu- ]CC", + "M3" : "[tau+ => mu+ mu+ ^mu- ]CC" + } + vars = FunctorCollection( { + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Tau" : vars + get_collections_mcparticle( config ) , + "M1" : vars + get_collections_mcparticle( config ) , + "M2" : vars + get_collections_mcparticle( config ) , + "M3" : vars + get_collections_mcparticle( config ) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + +# TODO : write a function which check for the info.yaml the available MCDT +@bind_sampleID("Dp_TauNu_TauTo3Mu_fromD") +def Dp_TauNu_TauTo3Mu_fromD_MCDT( options : Options, config : Config, mode_name = ""): + modename = "Dp_TauNu_TauTo3Mu_fromD" if mode_name == "" else mode_name + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Dp" : "[D+ => (tau+ => mu+ mu+ mu- ) nu_tau ]CC", + "Tau" : "[D+ => ^(tau+ => mu+ mu+ mu- ) nu_tau ]CC", + "Mu1" : "[D+ => (tau+ => ^mu+ mu+ mu- ) nu_tau ]CC", + "Mu2" : "[D+ => (tau+ => mu+ ^mu+ mu- ) nu_tau ]CC", + "Mu3" : "[D+ => (tau+ => mu+ mu+ ^mu- ) nu_tau ]CC", + "Nu" : "[D+ => (tau+ => mu+ mu+ mu- ) ^nu_tau ]CC" + } + vars = FunctorCollection({ + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Dp" : vars + get_collections_mcparticle( config), + "Tau" : vars + get_collections_mcparticle( config), + "Mu1" : vars + get_collections_mcparticle( config), + "Mu2" : vars + get_collections_mcparticle( config), + "Mu3" : vars + get_collections_mcparticle( config), + "Nu" : vars + get_collections_mcparticle( config) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("Ds_TauNu_TauTo3Mu_fromD") +def Ds_TauNu_TauTo3Mu_fromD_MCDT( options : Options, config : Config, mode_name = ""): + modename = "Ds_TauNu_TauTo3Mu_fromD" if mode_name == "" else mode_name + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + FIELDS = { + "Ds" : "[D_s+ => (tau+ => mu+ mu+ mu- ) nu_tau ]CC", + "Tau" : "[D_s+ => ^(tau+ => mu+ mu+ mu- ) nu_tau ]CC", + "Mu1" : "[D_s+ => (tau+ => ^mu+ mu+ mu- ) nu_tau ]CC", + "Mu2" : "[D_s+ => (tau+ => mu+ ^mu+ mu- ) nu_tau ]CC", + "Mu3" : "[D_s+ => (tau+ => mu+ mu+ ^mu- ) nu_tau ]CC", + "Nu" : "[D_s+ => (tau+ => mu+ mu+ mu- ) ^nu_tau ]CC" + } + vars = FunctorCollection({ + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Ds" : vars + get_collections_mcparticle( config), + "Tau" : vars + get_collections_mcparticle( config), + "Mu1" : vars + get_collections_mcparticle( config), + "Mu2" : vars + get_collections_mcparticle( config), + "Mu3" : vars + get_collections_mcparticle( config), + "Nu" : vars + get_collections_mcparticle( config) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) +@bind_sampleID("Ds_PhiPi_PhiToMuMu_fromD") +def Ds_PhiPi_PhiToMuMu_fromD_MCDT( options : Options, config : Config, mode_name = ""): + modename = "Ds_PhiPi_PhiToMuMu_fromD" if mode_name == "" else mode_name + assert(config.isMC()) + assert(config.SampleNameID() == modename) + mc_particles = get_mc_particles("/Event/HLT2/MC/Particles") + mc_vertices = get_mc_vertices("/Event/HLT2/MC/Vertices") + if config.MCDTONLY() : + mc_particles = get_mc_particles("/Event/MC/Particles") + mc_vertices = get_mc_vertices("/Event/MC/Vertices") + #[ D_s+ => ( ^(phi(1020) => ^mu+ ^mu-) ) ^pi+ ]CC + FIELDS = { + "Ds" : "[ D_s+ => (phi(1020) => mu+ mu-) pi+ ]CC", + "Phi" : "[ D_s+ => ^(phi(1020) => mu+ mu-) pi+ ]CC", + "Mu1" : "[ D_s+ => (phi(1020) => ^mu+ mu-) pi+ ]CC", + "Mu2" : "[ D_s+ => (phi(1020) => mu+ ^mu-) pi+ ]CC", + "Pi" : "[ D_s+ => (phi(1020) => mu+ mu-) ^pi+ ]CC", + } + vars = FunctorCollection({ + "M" : F.MASS, + "P" : F.P, + "PT": F.PT, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "ETA": F.ETA, + "ID" : F.PARTICLE_ID, + "ENERGY": F.ENERGY, + "ID": F.PARTICLE_ID + }) + VARIABLES = { + "Ds" : vars + get_collections_mcparticle( config), + "Phi" : vars + get_collections_mcparticle( config), + "Mu1" : vars + get_collections_mcparticle( config), + "Mu2" : vars + get_collections_mcparticle( config), + "Pi" : vars + get_collections_mcparticle( config) + } + evtinfo = get_collections_mcevent( config) + return MCFuntuple( + name=f"{modename}_MCDecayTree", + tuple_name="MCDecayTree", + fields=FIELDS, + variables=VARIABLES, + event_variables=evtinfo, + inputs=mc_particles + ) + + +@bind_sampleID("Dp_TauNu_TauTo3Mu_fromB") +def Dp_TauNu_TauTo3Mu_fromB_MCDT( options : Options, config : Config): + modename = "Dp_TauNu_TauTo3Mu_fromB" + return Dp_TauNu_TauTo3Mu_fromD_MCDT( options, config, modename ) + +@bind_sampleID("Ds_TauNu_TauTo3Mu_fromB") +def Ds_TauNu_TauTo3Mu_fromB_MCDT( options : Options, config : Config): + modename = "Ds_TauNu_TauTo3Mu_fromB" + return Ds_TauNu_TauTo3Mu_fromD_MCDT( options, config, modename ) + +@bind_sampleID("Ds_PhiPi_PhiToMuMu_fromB") +def Ds_PhiPi_PhiToMuMu_fromB( options : Options, config : Config): + modename = "Ds_PhiPi_PhiToMuMu_fromB" + return Ds_PhiPi_PhiToMuMu_fromD_MCDT( options, config, modename ) + + +######################################################################### +######################################################################### +######################################################################### +SAMPLE_MCDECAYTREEALG = {} +globals_copy = dict(globals()) +for name, obj in globals_copy.items(): + if callable(obj) and hasattr(obj, 'sampleID'): + if obj.sampleID not in SAMPLE_MCDECAYTREEALG : + SAMPLE_MCDECAYTREEALG[obj.sampleID] = obj +for k in SAMPLE_MCDECAYTREEALG.keys() : + logger.debug(f"{k} can be bound to its own function, all the rest no. Bounded to {SAMPLE_MCDECAYTREEALG[k]}") diff --git a/rd_ap_2024/tupling/README.md b/rd_ap_2024/tupling/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d7eb881fde196d865c0998e27b1d218b46681894 --- /dev/null +++ b/rd_ap_2024/tupling/README.md @@ -0,0 +1,140 @@ +## How to tuple your line output adding just few lines to the existing AP + + +## NB : for the moment the data processing is checked to work, for simulation, something centralised with hlt1,hlt2,spruce should be put in place. Be patient. + +## TO BE REDONE with fixes + + + +All you need is to decorate a custom code for this piece of code + +1. Look up your line of interest in https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/hlt2_lines_reference.html + + + +2. Figure out the decay descriptor used in it and introduce the following information : + +- LINE_NAME +- V2_PVS +- DECAY_DESCRIPTOR +- FIELDS +as bare minimum +Copy the rest of the tupling code in ```main.py``` please add in ```get_user_algorithms``` function within the dictionary and 'Data' field the name of your line/function. + +3. To enable the tupling of your line in the AP together to the other lines you need to write a function like this : keep the bind_string and the function name coherent doing so . Example follow + +```python +@bind_string("Hlt2RD_BuToKpEE") +def Hlt2RD_BuToKpEE(options:Options, config : Config) : + LINE_NAME = "Hlt2RD_BuToKpEE" + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + DECAY_DESCRIPTOR = 'B+ -> (J/psi(1S) -> e+ e-) K+' + FIELDS = { + "B" : "[B+ -> (J/psi(1S) -> e+ e-) K+]CC", + "Jpsi": "[B+ -> ^(J/psi(1S) -> e+ e-) K+]CC", + "L1" : "[B+ -> (J/psi(1S) -> ^e+ e-) K+]CC", + "L2" : "[B+ -> (J/psi(1S) -> e+ ^e-) K+]CC", + "K" : "[B+ -> (J/psi(1S) -> e+ e-) ^K+]CC", + } + FIELDS_ISOLATION_LOCATIONS = { + "B" : ["B_LongTrackIsolation","B_NeutralIsolation"], + "K" : ["K_LongTrackIsolation","K_LongTrackIsolation"], + "L" : ["e_LongTrackIsolation","e_NeutralIsolation"], + } + ####### used to create the Swap DTFs on + SUBST_DICT = { + # single swap K->pi + "K2Pi": {"substitutions":['B+ -> (J/psi(1S) -> e+ e-) K+{{pi+}}', + 'B- -> (J/psi(1S) -> e+ e-) K-{{pi-}}'], #CC + "mass_dict":{'B+':'J/psi(1S)','J/psi(1S)':'B+'} + }, + # double swap K->mu mu->K + "KE2EK": {"substitutions":[ 'B+ -> (J/psi(1S) -> mu+ {{K+}} e-) K+{{e+}}', + 'B- -> (J/psi(1S) -> mu+ mu-{{K-}}) K-{{e-}}'], #CC + "mass_dict":{'B+':'J/psi(1S)','J/psi(1S)':'B+'}, + }, + # double misid + "EE2KK": {"substitutions":[ 'B+ -> (J/psi(1S) -> e+{{K+}} e-{{K-}}) K+', + 'B- -> (J/psi(1S) -> e+{{K+}} e-{{K-}}) K-'], #CC + "mass_dict":{'B+':'J/psi(1S)', 'J/psi(1S)':'B+'}, + }, + # double misid + "EE2PiPi": {"substitutions": ['B+ -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) K+', + 'B- -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) K-'], #CC + "mass_dict":{'B+':'J/psi(1S)', 'J/psi(1S)':'B+'}, + }, + } + SUBSTITUTION_DICT = update_subsdict_with_swapped_hypothesis(LINE_DATA, SUBST_DICT ) +# TODO: Outdated example + print("-------------- CREATING VARIABLES --------------------") + VARIABLES = { + "B": ( make_dtf_variables_with_swapped_mass_hypothesis(options, v2_pvs = V2_PVS, substitution_dict=SUBSTITUTION_DICT, particle='B+') + + make_composite_variables(options, data= LINE_DATA, v2_pvs= V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH ) + + make_dtf_variables (options, data= LINE_DATA, v2_pvs= V2_PVS, addMassConstraints=True, mB=["B+"],decay_descriptor_for_subs_constraint=DECAY_DESCRIPTOR )+ + make_iddl_electron_mva( options, data= LINE_DATA, v2_pvs= V2_PVS, nbody= '2' ) + ), + "Jpsi": (make_dtf_variables_with_swapped_mass_hypothesis(options, v2_pvs=V2_PVS, substitution_dict=SUBSTITUTION_DICT, particle='B+') + + make_basic_variables( + options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH + ) + + make_intermediate_resonances_variables(options, data = LINE_DATA, v2_pvs= V2_PVS) + + make_dtf_variables(options, data = LINE_DATA, v2_pvs = V2_PVS, addMassConstraints=True, mB=["B+"],decay_descriptor_for_subs_constraint=DECAY_DESCRIPTOR ) + ), + "K": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables( + options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH + ) + + make_track_variables(options, data=LINE_DATA) ), + "L1": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables( + options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH + ) + + make_track_variables(options, data=LINE_DATA)), + "L2": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables( + options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH + ) + + make_track_variables(options, data=LINE_DATA) ), + #"ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert( sorted( VARIABLES.keys() == sorted( FIELDS.keys()))) + # define FunTuple instance + return Funtuple_with_filter( + options =options, + line_name = LINE_NAME, + fields = FIELDS, + variables = VARIABLES, + inputs = LINE_DATA, + name= f"{LINE_NAME}" , + tuple_name = "DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +``` + +4. the last step to enable this algorithm to execute and make your tuple is to include in ```get_user_algorithms``` function and dictionary the actual binded string to a line tupling you created beforehand. For example in Data to make your tuple from a given line named ```Hlt2RD_XXXX``` for which you defined your binded-string function ```Hlt2RD_XXXX```, you just need to extend +```python +def get_user_algorithms( options : Options, config : Config ): + if config.isTurbo() : + mydict = { + "Bu_JPsiK_EE" : [ "Hlt2RD_BuToKpEE", "Hlt2RD_BuToKpEE_SameSign"], + "Bu_JPsiK_MM" : [ "Hlt2RD_BuToHpMuMu_Incl"], #, "Hlt2RD_BuToHpMuMu_Incl" , "Hlt2RD_B0ToKpKmMuMu" ], + "Bd_JPsiKst_MM": [ "Hlt2RD_BuToHpMuMu_Incl"], #, "Hlt2RD_BuToHpMuMu_Incl" , "Hlt2RD_B0ToKpKmMuMu" ], + "Bs_PhiKst_MM" : [ "Hlt2RD_BuToHpMuMu_Incl"], #, "Hlt2RD_BuToHpMuMu_Incl" , "Hlt2RD_B0ToKpKmMuMu" ], + "MinBias" : [ "Hlt2RD_BuToHpMuMu_Incl" , "Hlt2RD_BuToHpMuMu_Incl" , + "Hlt2RD_BuToKpEE" , "Hlt2RD_BuToKpEE" + ], + "Data" : [ "Hlt2RD_BuToKpEE", "Hlt2RD_BuToHpMuMu_Incl"] + [ "Hlt2RD_XXXX"] ##<--- HERE + } +``` + +NB: code is in dev/prototyping and MC checks to be done still. +NB2: in the posted code, a given EventType number is assigned to a name of the decay, the idea is that for MC we can do the same, so that a given analysis can just enumerate the BKG samples needed and the line to tuple them, and get out all needed. \ No newline at end of file diff --git a/rd_ap_2024/tupling/config/b_to_xll_mva.yaml b/rd_ap_2024/tupling/config/b_to_xll_mva.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b81c167d4962d7678197f183fa14099359aa12b7 --- /dev/null +++ b/rd_ap_2024/tupling/config/b_to_xll_mva.yaml @@ -0,0 +1,1281 @@ +#------------------------------------------- +isolation: + #Used to find path to container with tracks + max_delta_chi2 : ['9.0'] + angles : ['0.10', '0.15', '0.20', '0.25', '0.30'] + header : + Hlt2RD_BuToKpEE_MVA : bp + Hlt2RD_BuToKpMuMu_MVA : bp + Hlt2RD_BuToKpEE_SameSign_MVA : bp + Hlt2RD_BuToKpMuMu_SameSign_MVA : bp + Hlt2RD_BuToKpEE_MVA_misid : bp + Hlt2RD_BuToKpEE_MVA_cal : bp + #----------------- + Hlt2RD_B0ToKpPimEE_MVA : bd + Hlt2RD_B0ToKpPimMuMu_MVA : bd + Hlt2RD_B0ToKpPimEE_SameSign_MVA : bd + Hlt2RD_B0ToKpPimMuMu_SameSign_MVA : bd + Hlt2RD_B0ToKpPimEE_MVA_misid : bd + Hlt2RD_B0ToKpPimEE_MVA_cal : bd + #----------------- + Hlt2RD_LbTopKEE_MVA : Lb + Hlt2RD_LbTopKMuMu_MVA : Lb + Hlt2RD_LbTopKEE_SameSign_MVA : Lb + Hlt2RD_LbTopKMuMu_SameSign_MVA : Lb + Hlt2RD_LbTopKEE_MVA_misid : Lb + #----------------- + Hlt2RD_BsToPhiEE_MVA : B + Hlt2RD_BsToPhiMuMu_MVA : B + Hlt2RD_BsToPhiEE_SameSign_MVA : B + Hlt2RD_BsToPhiMuMu_SameSign_MVA : B + Hlt2RD_BsToPhiEE_MVA_misid : B +#------------------------------------------- +#Bu -> K+ ll +#------------------------------------------- +Hlt2RD_BuToKpMuMu_MVA : &buk_mm_os + head : 'B+' + custom: + Hlt2RD_BuToKpMuMu_MVA_noPID: + dimuon: + pidmu_muon_min : -999 + kaon: + pid : -999 + fields : + B : '[B+ -> (J/psi(1S) -> mu+ mu-) K+]CC' + Jpsi : '[B+ -> ^(J/psi(1S) -> mu+ mu-) K+]CC' + L1 : '[B+ -> (J/psi(1S) -> ^mu+ mu-) K+]CC' + L2 : '[B+ -> (J/psi(1S) -> mu+ ^mu-) K+]CC' + K : '[B+ -> (J/psi(1S) -> mu+ mu-) ^K+]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_MM2KK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{K+}} mu-{{K-}} ) K+ ]CC' + DTF_MM2KPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{K+}} mu-{{pi-}}) K+ ]CC' + DTF_MM2PiK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{pi+}} mu-{{K-}} ) K+ ]CC' + DTF_MM2PiPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{pi+}} mu-{{pi-}}) K+ ]CC' + DTF_HEAD: + mass_constraints: + - B+ + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_K2Pi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+ mu-) K+{{pi+}}]CC' + DTF_KM2MK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{K+}} mu-) K+{{mu+}} ]CC' + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) K+]CC' +#------------------------------------------- +Hlt2RD_BuToKpMuMu_SameSign_MVA: + head : 'B+' + fields : + B : '[B+ -> (J/psi(1S) -> mu+ mu+) K+]CC' + Jpsi : '[B+ -> ^(J/psi(1S) -> mu+ mu+) K+]CC' + L1 : '[B+ -> (J/psi(1S) -> ^mu+ mu+) K+]CC' + L2 : '[B+ -> (J/psi(1S) -> mu+ ^mu+) K+]CC' + K : '[B+ -> (J/psi(1S) -> mu+ mu+) ^K+]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_MM2KK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{K+}} mu+{{K+}} ) K+ ]CC' + DTF_MM2KPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{K+}} mu+{{pi+}}) K+ ]CC' + DTF_MM2PiK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{pi+}} mu+{{K+}} ) K+ ]CC' + DTF_MM2PiPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{pi+}} mu+{{pi+}}) K+ ]CC' + DTF_HEAD: + mass_constraints: + - B+ + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_K2Pi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+ mu+) K+{{pi+}}]CC' + DTF_KM2MK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> mu+{{K+}} mu+) K+{{mu+}} ]CC' + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu+) K+]CC' +#------------------------------------------- +Hlt2RD_BuToKpEE_MVA : &buk_ee_os + head : 'B+' + custom: + Hlt2RD_BuToKpEE_MVA_noPID: + dielectron_tight: + pid_e_min : -999 + kaon: + pid : -999 + fields : + B : '[B+ -> (J/psi(1S) -> e+ e-) K+]CC' + Jpsi : '[B+ -> ^(J/psi(1S) -> e+ e-) K+]CC' + L1 : '[B+ -> (J/psi(1S) -> ^e+ e-) K+]CC' + L2 : '[B+ -> (J/psi(1S) -> e+ ^e-) K+]CC' + K : '[B+ -> (J/psi(1S) -> e+ e-) ^K+]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_EE2KK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{K+}} e-{{K-}} ) K+ ]CC' + DTF_EE2KPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{K+}} e-{{pi-}}) K+ ]CC' + DTF_EE2PiK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{pi+}} e-{{K-}} ) K+ ]CC' + DTF_EE2PiPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) K+ ]CC' + DTF_HEAD: + mass_constraints: + - B+ + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_K2Pi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+ e-) K+{{pi+}}]CC' + DTF_KE2EK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{K+}} e-) K+{{e+}} ]CC' + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B+ -> (J/psi(1S){{psi(2S)}} -> e+ e-) K+]CC' +#------------------------------------------- +Hlt2RD_BuToKpEE_SameSign_MVA: + head : 'B+' + fields : + B : '[B+ -> (J/psi(1S)-> e+ e+) K+]CC' + Jpsi : '[B+ -> ^(J/psi(1S)-> e+ e+) K+]CC' + K : '[B+ -> (J/psi(1S)-> e+ e+) ^K+]CC' + L1 : '[B+ -> (J/psi(1S)-> ^e+ e+) K+]CC' + L2 : '[B+ -> (J/psi(1S)-> e+ ^e+) K+]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_EE2KK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{K+}} e+{{K+}} ) K+ ]CC' + DTF_EE2KPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{K+}} e+{{pi+}}) K+ ]CC' + DTF_EE2PiK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{pi+}} e+{{K+}} ) K+ ]CC' + DTF_EE2PiPi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{pi+}} e+{{pi+}}) K+ ]CC' + DTF_HEAD: + mass_constraints: + - B+ + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_K2Pi_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+ e+) K+{{pi+}}]CC' + DTF_KE2EK_Swap: + mass_constraints: [] + substitutions: + - '[B+ -> (J/psi(1S) -> e+{{K+}} e+) K+{{e+}} ]CC' + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B+ -> (J/psi(1S){{psi(2S)}} -> e+ e+) K+]CC' +#------------------------------------------- +Hlt2RD_BuToKpEE_MVA_cal : *buk_ee_os +Hlt2RD_BuToKpEE_MVA_misid : *buk_ee_os +#------------------------------------------- +#Bd -> K* ll +#------------------------------------------- +Hlt2RD_B0ToKpPimMuMu_MVA : &bdkst_mm_os + head : 'B0' + custom : + Hlt2RD_B0ToKpPimMuMu_MVA_noPID: + dimuon: + pidmu_muon_min : -999 + Kst0s: + pi_pid: +999 + k_pid : -999 + fields : + B : '[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC' + Jpsi : '[B0 -> ^(J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC' + L1 : '[B0 -> (J/psi(1S) -> ^mu+ mu-) (K*(892)0-> K+ pi-)]CC' + L2 : '[B0 -> (J/psi(1S) -> mu+ ^mu-) (K*(892)0-> K+ pi-)]CC' + Kst : '[B0 -> (J/psi(1S) -> mu+ mu-) ^(K*(892)0-> K+ pi-)]CC' + H1 : '[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> ^K+ pi-)]CC' + H2 : '[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ ^pi-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - B0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (K*(892)0-> K+ pi-)]CC' +#------------------------------------------- +Hlt2RD_B0ToKpPimMuMu_SameSign_MVA: + head : 'B0' + fields : + B : '[B0 -> (J/psi(1S) -> mu+ mu+) (K*(892)0-> K+ pi-)]CC' + Jpsi : '[B0 -> ^(J/psi(1S) -> mu+ mu+) (K*(892)0-> K+ pi-)]CC' + L1 : '[B0 -> (J/psi(1S) -> ^mu+ mu+) (K*(892)0-> K+ pi-)]CC' + L2 : '[B0 -> (J/psi(1S) -> mu+ ^mu+) (K*(892)0-> K+ pi-)]CC' + Kst : '[B0 -> (J/psi(1S) -> mu+ mu+) ^(K*(892)0-> K+ pi-)]CC' + H1 : '[B0 -> (J/psi(1S) -> mu+ mu+) (K*(892)0-> ^K+ pi-)]CC' + H2 : '[B0 -> (J/psi(1S) -> mu+ mu+) (K*(892)0-> K+ ^pi-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - B0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu+) (K*(892)0-> K+ pi-)]CC' +#------------------------------------------- +Hlt2RD_B0ToKpPimEE_MVA : &bdkst_ee_os + head : 'B0' + custom: + Hlt2RD_B0ToKpPimEE_MVA_noPID: + dielectron_tight: + pid_e_min : -999 + Kst0s: + pi_pid: +999 + k_pid : -999 + fields : + B : '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC' + Jpsi : '[B0 -> ^(J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC' + L1 : '[B0 -> (J/psi(1S) -> ^e+ e-) (K*(892)0-> K+ pi-)]CC' + L2 : '[B0 -> (J/psi(1S) -> e+ ^e-) (K*(892)0-> K+ pi-)]CC' + Kst : '[B0 -> (J/psi(1S) -> e+ e-) ^(K*(892)0-> K+ pi-)]CC' + H1 : '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> ^K+ pi-)]CC' + H2 : '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ ^pi-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_EE2KK: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{K+}} e-{{K-}} ) (K*(892)0-> K+ pi-)]CC' + DTF_EE2KPi: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{K+}} e-{{pi-}}) (K*(892)0-> K+ pi-)]CC' + DTF_EE2PiK: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{pi+}} e-{{K-}} ) (K*(892)0-> K+ pi-)]CC' + DTF_EE2PiPi: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) (K*(892)0-> K+ pi-)]CC' + DTF_HEAD: + mass_constraints: + - B0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_K2P: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{p+}} pi-)]CC' + DTF_K2P_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{p+}} pi-)]CC' + DTF_K2P_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+{{p+}} pi-)]CC' + DTF_K2Pi: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{pi+}} pi-)]CC' + DTF_K2Pi_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{pi+}} pi-)]CC' + DTF_K2Pi_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+{{pi+}} pi-)]CC' + DTF_Pi2K: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{K-}})]CC' + DTF_Pi2K_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{K-}})]CC' + DTF_Pi2K_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-{{K-}})]CC' + DTF_Pi2P: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{p~-}})]CC' + DTF_Pi2P_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{p~-}})]CC' + DTF_Pi2P_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-{{p~-}})]CC' + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-)]CC' +#------------------------------------------- +Hlt2RD_B0ToKpPimEE_SameSign_MVA : + head : 'B0' + fields : + B : '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+ pi-)]CC' + Jpsi : '[B0 -> ^(J/psi(1S) -> e+ e+) (K*(892)0-> K+ pi-)]CC' + L1 : '[B0 -> (J/psi(1S) -> ^e+ e+) (K*(892)0-> K+ pi-)]CC' + L2 : '[B0 -> (J/psi(1S) -> e+ ^e+) (K*(892)0-> K+ pi-)]CC' + Kst : '[B0 -> (J/psi(1S) -> e+ e+) ^(K*(892)0-> K+ pi-)]CC' + H1 : '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> ^K+ pi-)]CC' + H2 : '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+ ^pi-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_EE2KK: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{K+}} e+{{K-}} ) (K*(892)0-> K+ pi-)]CC' + DTF_EE2KPi: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{K+}} e+{{pi-}}) (K*(892)0-> K+ pi-)]CC' + DTF_EE2PiK: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{pi+}} e+{{K-}} ) (K*(892)0-> K+ pi-)]CC' + DTF_EE2PiPi: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+{{pi+}} e+{{pi-}}) (K*(892)0-> K+ pi-)]CC' + DTF_HEAD: + mass_constraints: + - B0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_K2P: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+{{p+}} pi-)]CC' + DTF_K2P_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+{{p+}} pi-)]CC' + DTF_K2P_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e+) (K*(892)0-> K+{{p+}} pi-)]CC' + DTF_K2Pi: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+{{pi+}} pi-)]CC' + DTF_K2Pi_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+{{pi+}} pi-)]CC' + DTF_K2Pi_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e+) (K*(892)0-> K+{{pi+}} pi-)]CC' + DTF_Pi2K: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+ pi-{{K-}})]CC' + DTF_Pi2K_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+ pi-{{K-}})]CC' + DTF_Pi2K_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e+) (K*(892)0-> K+ pi-{{K-}})]CC' + DTF_Pi2P: + mass_constraints: [] + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+ pi-{{p~-}})]CC' + DTF_Pi2P_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[B0 -> (J/psi(1S) -> e+ e+) (K*(892)0-> K+ pi-{{p~-}})]CC' + DTF_Pi2P_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e+) (K*(892)0-> K+ pi-{{p~-}})]CC' + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - '[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e+) (K*(892)0-> K+ pi-)]CC' +#------------------------------------------- +Hlt2RD_B0ToKpPimEE_MVA_cal : *bdkst_ee_os +Hlt2RD_B0ToKpPimEE_MVA_misid: *bdkst_ee_os +#------------------------------------------- +#Lb -> pk ll +#------------------------------------------- +Hlt2RD_LbTopKMuMu_MVA : &lbpk_mm_os + head : 'Lambda_b0' + fields : + Lb : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC' + Jpsi : '[Lambda_b0 -> ^(J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC' + L1 : '[Lambda_b0 -> (J/psi(1S) -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC' + L2 : '[Lambda_b0 -> (J/psi(1S) -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-)]CC' + Lz : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-)]CC' + P : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-)]CC' + K : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - Lambda_b0 + substitutions: [] + #--- + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Jpsi_K2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Jpsi_K2p: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Jpsi_p2K: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Jpsi_p2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Jpsi_pK2KPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Jpsi_pK2Kp: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiP: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + #--- + DTF_Psi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K- )]CC' + DTF_Psi_K2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Psi_K2p: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Psi_p2K: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Psi_p2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Psi_pK2KPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Psi_pK2Kp: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiP: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + #--- + DTF_K2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_K2p: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_p2K: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_p2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_pK2KPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_pK2Kp: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_pK2PiP: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_pK2PiPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' +#------------------------------------------- +Hlt2RD_LbTopKMuMu_SameSign_MVA: + head : 'Lambda_b0' + fields : + Lb : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu+) (Lambda(1520)0 -> p+ K-)]CC' + Jpsi : '[Lambda_b0 -> ^(J/psi(1S) -> mu+ mu+) (Lambda(1520)0 -> p+ K-)]CC' + L1 : '[Lambda_b0 -> (J/psi(1S) -> ^mu+ mu+) (Lambda(1520)0 -> p+ K-)]CC' + L2 : '[Lambda_b0 -> (J/psi(1S) -> mu+ ^mu+) (Lambda(1520)0 -> p+ K-)]CC' + Lz : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu+) ^(Lambda(1520)0 -> p+ K-)]CC' + P : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu+) (Lambda(1520)0 -> ^p+ K-)]CC' + K : '[Lambda_b0 -> (J/psi(1S) -> mu+ mu+) (Lambda(1520)0 -> p+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - Lambda_b0 + substitutions: [] + #---- + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Jpsi_K2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Jpsi_K2p: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Jpsi_p2K: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Jpsi_p2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Jpsi_pK2KPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Jpsi_pK2Kp: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiP: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + #---- + DTF_Psi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K- )]CC' + DTF_Psi_K2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Psi_K2p: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Psi_p2K: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Psi_p2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Psi_pK2KPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Psi_pK2Kp: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiP: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + #---- + DTF_K2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_K2p: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_p2K: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_p2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_pK2KPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_pK2Kp: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_pK2PiP: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_pK2PiPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> mu+ mu+ )]CC (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' +#------------------------------------------- +Hlt2RD_LbTopKEE_MVA : &lbpk_ee_os + head : 'Lambda_b0' + fields : + Lb : '[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC' + Jpsi : '[Lambda_b0 -> ^(J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC' + L1 : '[Lambda_b0 -> (J/psi(1S) -> ^e+ e-) (Lambda(1520)0 -> p+ K-)]CC' + L2 : '[Lambda_b0 -> (J/psi(1S) -> e+ ^e-) (Lambda(1520)0 -> p+ K-)]CC' + Lz : '[Lambda_b0 -> (J/psi(1S) -> e+ e-) ^(Lambda(1520)0 -> p+ K-)]CC' + P : '[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> ^p+ K-)]CC' + K : '[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - Lambda_b0 + substitutions: [] + # --- + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Jpsi_K2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Jpsi_K2p: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Jpsi_p2K: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Jpsi_p2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Jpsi_pK2KPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Jpsi_pK2Kp: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiP: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + # --- + DTF_Psi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+ K- )]CC' + DTF_Psi_K2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Psi_K2p: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Psi_p2K: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Psi_p2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Psi_pK2KPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Psi_pK2Kp: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiP: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + # --- + DTF_K2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_K2p: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_p2K: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_p2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_pK2KPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_pK2Kp: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_pK2PiP: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_pK2PiPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' +#------------------------------------------- +Hlt2RD_LbTopKEE_SameSign_MVA: + head : 'Lambda_b0' + fields : + Lb : '[Lambda_b0 -> (J/psi(1S) -> e+ e+) (Lambda(1520)0 -> p+ K-)]CC' + Jpsi : '[Lambda_b0 -> ^(J/psi(1S) -> e+ e+) (Lambda(1520)0 -> p+ K-)]CC' + L1 : '[Lambda_b0 -> (J/psi(1S) -> ^e+ e+) (Lambda(1520)0 -> p+ K-)]CC' + L2 : '[Lambda_b0 -> (J/psi(1S) -> e+ ^e+) (Lambda(1520)0 -> p+ K-)]CC' + Lz : '[Lambda_b0 -> (J/psi(1S) -> e+ e+) ^(Lambda(1520)0 -> p+ K-)]CC' + P : '[Lambda_b0 -> (J/psi(1S) -> e+ e+) (Lambda(1520)0 -> ^p+ K-)]CC' + K : '[Lambda_b0 -> (J/psi(1S) -> e+ e+) (Lambda(1520)0 -> p+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - Lambda_b0 + substitutions: [] + # --- + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Jpsi_K2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Jpsi_K2p: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Jpsi_p2K: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Jpsi_p2Pi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Jpsi_pK2KPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Jpsi_pK2Kp: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiP: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Jpsi_pK2PiPi: + mass_constraints: + - J/psi(1S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + # --- + DTF_Psi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+ K- )]CC' + DTF_Psi_K2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_Psi_K2p: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_Psi_p2K: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_Psi_p2Pi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_Psi_pK2KPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_Psi_pK2Kp: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiP: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_Psi_pK2PiPi: + mass_constraints: + - psi(2S) + substitutions: + - '[Lambda_b0 -> [(J/psi(1S){{psi(2S)}} -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' + # --- + DTF_K2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+ K-{{pi-}} )]CC' + DTF_K2p: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+ K-{{p~-}} )]CC' + DTF_p2K: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K- )]CC' + DTF_p2Pi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K- )]CC' + DTF_pK2KPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC' + DTF_pK2Kp: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC' + DTF_pK2PiP: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC' + DTF_pK2PiPi: + mass_constraints: [] + substitutions: + - '[Lambda_b0 -> [(J/psi(1S) -> e+ e+)]CC (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC' +#------------------------------------------- +Hlt2RD_LbTopKEE_MVA_misid : *lbpk_ee_os +#------------------------------------------- +#Bs -> phi ll +#------------------------------------------- +Hlt2RD_BsToPhiMuMu_MVA : &bsph_mm_os + head : 'B_s0' + fields : + B : '[B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ K-)]CC' + Jpsi : '[B_s0 -> ^(J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ K-)]CC' + L1 : '[B_s0 -> (J/psi(1S) -> ^mu+ mu-) (phi(1020) -> K+ K-)]CC' + L2 : '[B_s0 -> (J/psi(1S) -> mu+ ^mu-) (phi(1020) -> K+ K-)]CC' + Phi : '[B_s0 -> (J/psi(1S) -> mu+ mu-) ^(phi(1020) -> K+ K-)]CC' + H1 : '[B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> ^K+ K-)]CC' + H2 : '[B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - B_s0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - B_s0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (phi(1020)-> K+ K-) +#------------------------------------------- +Hlt2RD_BsToPhiMuMu_SameSign_MVA: + head : 'B_s0' + fields : + B : '[B_s0 -> (J/psi(1S) -> mu+ mu+) (phi(1020) -> K+ K-)]CC' + Jpsi : '[B_s0 -> ^(J/psi(1S) -> mu+ mu+) (phi(1020) -> K+ K-)]CC' + L1 : '[B_s0 -> (J/psi(1S) -> ^mu+ mu+) (phi(1020) -> K+ K-)]CC' + L2 : '[B_s0 -> (J/psi(1S) -> mu+ ^mu+) (phi(1020) -> K+ K-)]CC' + Phi : '[B_s0 -> (J/psi(1S) -> mu+ mu+) ^(phi(1020) -> K+ K-)]CC' + H1 : '[B_s0 -> (J/psi(1S) -> mu+ mu+) (phi(1020) -> ^K+ K-)]CC' + H2 : '[B_s0 -> (J/psi(1S) -> mu+ mu+) (phi(1020) -> K+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - B_s0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - B_s0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu+) (phi(1020)-> K+ K-) +#------------------------------------------- +Hlt2RD_BsToPhiEE_MVA : &bsph_ee_os + head : 'B_s0' + fields : + B : '[B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020) -> K+ K-)]CC' + Jpsi : '[B_s0 -> ^(J/psi(1S) -> e+ e-) (phi(1020) -> K+ K-)]CC' + L1 : '[B_s0 -> (J/psi(1S) -> ^e+ e-) (phi(1020) -> K+ K-)]CC' + L2 : '[B_s0 -> (J/psi(1S) -> e+ ^e-) (phi(1020) -> K+ K-)]CC' + Phi : '[B_s0 -> (J/psi(1S) -> e+ e-) ^(phi(1020) -> K+ K-)]CC' + H1 : '[B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020) -> ^K+ K-)]CC' + H2 : '[B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020) -> K+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - B_s0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - B_s0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (phi(1020)-> K+ K-) +#------------------------------------------- +Hlt2RD_BsToPhiEE_SameSign_MVA: + head : 'B_s0' + fields : + B : '[B_s0 -> (J/psi(1S) -> e+ e+) (phi(1020) -> K+ K-)]CC' + Jpsi : '[B_s0 -> ^(J/psi(1S) -> e+ e+) (phi(1020) -> K+ K-)]CC' + L1 : '[B_s0 -> (J/psi(1S) -> ^e+ e+) (phi(1020) -> K+ K-)]CC' + L2 : '[B_s0 -> (J/psi(1S) -> e+ ^e+) (phi(1020) -> K+ K-)]CC' + Phi : '[B_s0 -> (J/psi(1S) -> e+ e+) ^(phi(1020) -> K+ K-)]CC' + H1 : '[B_s0 -> (J/psi(1S) -> e+ e+) (phi(1020) -> ^K+ K-)]CC' + H2 : '[B_s0 -> (J/psi(1S) -> e+ e+) (phi(1020) -> K+ ^K-)]CC' + substitutions: + DTF: + mass_constraints: [] + substitutions: [] + DTF_HEAD: + mass_constraints: + - B_s0 + substitutions: [] + DTF_Jpsi: + mass_constraints: + - J/psi(1S) + substitutions: [] + DTF_Psi2S: + mass_constraints: + - psi(2S) + substitutions: + - B_s0 -> (J/psi(1S){{psi(2S)}} -> e+ e+) (phi(1020)-> K+ K-) +#------------------------------------------- +Hlt2RD_BsToPhiEE_MVA_misid : *bsph_ee_os +#------------------------------------------- +#Section below is used within Config.py to match MC sample to triggers that need to be +#processed with it +#------------------------------------------- +processes: + # This section tells the code that for a given event type (corresponding to a given MC sample) + # a given set of HLT lines exist. If the section is missing, the MVA lines will not be processed for the sample. + # --- + # Bd mumu + # --- + Bd_KstMM : &bdkstmm + - Hlt2RD_B0ToKpPimMuMu_MVA + - Hlt2RD_BuToKpMuMu_MVA + Bd_JPsiKst_MM : *bdkstmm + Bd_Psi2SKst_MM: *bdkstmm + # --- + # Bd ee + # --- + Bd_KstEE : &bdkstee + - Hlt2RD_B0ToKpPimEE_MVA + - Hlt2RD_BuToKpEE_MVA + - Hlt2RD_B0ToKpPimEE_MVA_cal + Bd_JPsiKst_EE : *bdkstee + Bd_Psi2SKst_EE: *bdkstee + # --- + # B+ mumu + # --- + Bu_KMM : &bukmm + - Hlt2RD_BuToKpMuMu_MVA + - Hlt2RD_B0ToKpPimMuMu_MVA + Bu_JPsiK_MM : *bukmm + Bu_JPsiPi_MM: *bukmm + Bu_Psi2SK_MM: *bukmm + # --- + # B+ ee + # --- + Bu_KEE : &bukee + - Hlt2RD_BuToKpEE_MVA + - Hlt2RD_B0ToKpPimEE_MVA + - Hlt2RD_BuToKpEE_MVA_cal + Bu_JPsiK_EE : *bukee + Bu_JPsiPi_EE: *bukee + Bu_Psi2SK_EE: *bukee + # --- + # Inclusive + # --- + Bd_JPsiX_MM : *bdkstmm + Bu_JPsiX_MM : *bukmm + Bd_JPsiX_EE : *bdkstee + Bu_JPsiX_EE : *bukee + # --- + # Bs + # --- + Bs_JPsiPhi_MM: + - Hlt2RD_BsToPhiMuMu_MVA + Bs_JPsiPhi_EE: + - Hlt2RD_BsToPhiEE_MVA + # --- + # Lb + # --- + Lb_JPsiPK_MM: &lbpkmm + - Hlt2RD_LbTopKMuMu_MVA + Lb_JPsiLz_MM: *lbpkmm + Lb_JPsiPK_EE: &lbpkee + - Hlt2RD_LbTopKEE_MVA + Lb_JPsiLz_EE: *lbpkee diff --git a/rd_ap_2024/tupling/hlt2/Rpk_lines.py b/rd_ap_2024/tupling/hlt2/Rpk_lines.py new file mode 100644 index 0000000000000000000000000000000000000000..0cff9a4edc57cb32ba69d954904796b232320ca3 --- /dev/null +++ b/rd_ap_2024/tupling/hlt2/Rpk_lines.py @@ -0,0 +1,775 @@ +############################################################################### +# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### + +from rd_ap_2024.utils.log_store import LogStore +from rd_ap_2024.tupling.Config import Config +from rd_ap_2024.tupling.variables.rd_stream_tupling_functions import ( + make_composite_variables, + make_basic_variables, + make_hlt_event_variables, + make_track_variables, + Funtuple_with_filter, + make_intermediate_resonances_variables, + make_truth_variables, + make_variables_with_swapped_mass_hypothesis +) + +from rd_ap_2024.tupling.variables.inclusive_detached_dilepton_mvas import( + #dimuons + InclDetDimuon_MVA, + InclDetDimuon_ThreeBody_MVA, + InclDetDimuon_FourBody_MVA, + InclDetDimuon_neutral_MVA, + #dielectrons + InclDetDielectron_MVA, + InclDetDielectron_ThreeBody_MVA, + InclDetDielectron_FourBody_MVA, + InclDetDielectron_neutral_MVA, + #di electron/muon + InclDetElectronMuon_MVA, + InclDetElectronMuon_ThreeBody_MVA, + InclDetElectronMuon_FourBody_MVA, + InclDetElectronMuon_neutral_MVA +) + +from rd_ap_2024.tupling.variables.tupling_dtf import ( + make_dtf_variables_v2 +) +from rd_ap_2024.tupling.variables.flavour_tagging_variables import make_ft_variables +from DaVinciTools import SubstitutePID + + +from rd_ap_2024.tupling.variables.rd_stream_isolation_functions import ( + make_Isolation_variables +) + +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) +import Functors as F +import FunTuple.functorcollections as FC +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +from PyConf.Algorithms import AdvancedCloneKiller, Run2SSPionTagger +from GaudiKernel.SystemOfUnits import GeV +from Hlt2Conf.algorithms_thor import ParticleFilter +from Hlt2Conf.standard_particles import ( # type: ignore[import] + make_long_pions, + make_long_kaons, + make_long_muons, + standard_protoparticle_filter, +) +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +from DaVinciMCTools import MCTruthAndBkgCat +from FunTuple.functorcollections import SelectionInfo +from DecayTreeFitter import DecayTreeFitter +# specific for the B2OC SigmaNet +import Functors.math as fmath + + +logger=LogStore.add_logger('rd_ap_2024:Rpk_lines') + +def bind_string(name): + def decorator(func): + func.name = name + return func + return decorator + + +# https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r7/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/RpK_lines.py?ref_type=tags + +@bind_string("Hlt2RD_LambdabToPKMuMu") +def Hlt2RD_LambdabToPKMuMu(options:Options, config : Config) : + LINE_NAME = "Hlt2RD_LambdabToPKMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC", + "Jpsi" : "[Lambda_b0 -> ^(J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC", + "L1" : "[Lambda_b0 -> (J/psi(1S) -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC", + "L2" : "[Lambda_b0 -> (J/psi(1S) -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-)]CC", + "X" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-)]CC", + "H1" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-)]CC", + "H2" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-)]CC", + } + + + # probbaly needs also track states covariances to store to use Christoph L. offline code ? + logger.debug("-------------- CREATING VARIABLES --------------------") + + ####### DTF with Jpsi and Psi2S constraint saving kinematics and lifetime + Constraints_Dict = { + "DTF" : {"substitutions" : [],"mass_constraints" : []}, + # Jpsi mass constraint + "DTF_Jpsi" : {"substitutions" : [],"mass_constraints" : ["J/psi(1S)"]}, + # Psi2S mass constraint + "DTF_Psi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K- )]CC"], "mass_constraints" : ["psi(2S)"]}, + # Constrained Lb mass + "DTF_HEAD" : {"substitutions" : [], "mass_constraints" : ["Lambda_b0"]}, + # p2K swap + "DTF_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K- )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K- )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K- )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p2Pi swap + "DTF_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K- )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K- )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K- )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2p swap + "DTF_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2pi swap + "DTF_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K p double swaps + "DTF_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> pi pi double swaps + "DTF_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K pi double swaps + "DTF_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> Pi p double swaps + "DTF_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + } + + + variables_DTF_results = make_dtf_variables_v2( + options = options, + data = LINE_DATA, + v2_pvs = V2_PVS, # comment out if no PV constraint? + Constraints_Config = Constraints_Dict) + + ####### PID substitution + + # pKmm_substitution_vars = FunctorCollection({ + # # proton ID + # "M_pKll_p2pi" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "pi+", "K-" )), + # "M_pKll_p2K" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "K+" , "K-" )), + # # kaon ID + # "M_pKll_K2pi" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "p+" , "pi-")), + # "M_pKll_K2p" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "p+" , "p~-" )), + # # double swaps + # "M_pKll_pK2Kp" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "K+" , "p~-" )), + # "M_pKll_pK2pipi": F.MASSWITHHYPOTHESES(("mu+", "mu-", "pi+", "pi-")), + # "M_pKll_pK2Kpi" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "K+" , "pi-")), + # "M_pKll_pK2pip" : F.MASSWITHHYPOTHESES(("mu+", "mu-", "pi+", "p~-" )), + # }) + + pK_substitution_vars = FunctorCollection({ + # proton ID + "M_pK_p2pi" : F.MASSWITHHYPOTHESES(("pi+", "K-" )), + "M_pK_p2K" : F.MASSWITHHYPOTHESES(("K+" , "K-" )), + # kaon ID + "M_pK_K2pi" : F.MASSWITHHYPOTHESES(("p+" , "pi-")), + "M_pK_K2p" : F.MASSWITHHYPOTHESES(("p+" , "p~-" )), + # double swaps + "M_pK_pK2Kp" : F.MASSWITHHYPOTHESES(("K+" , "p~-" )), + "M_pK_pK2pipi": F.MASSWITHHYPOTHESES(("pi+", "pi-")), + "M_pK_pK2Kpi" : F.MASSWITHHYPOTHESES(("K+" , "pi-")), + "M_pK_pK2pip" : F.MASSWITHHYPOTHESES(("pi+", "p~-" )), + }) + + # m_pmu_p2mu, m_Kmu_K2mu variables and m_Kmumu to be reconstructed offline + + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options,data = LINE_DATA,v2_pvs= V2_PVS , ndau=2)+ + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + make_Isolation_variables(options = options, + bhead_label_decay = "Lambda_b0", + data = LINE_DATA, + line = LINE_NAME, + header_tes = 'Lb', + dr2_angle_list = [ '0.15' ], + max_delta_vertex_chi2_cuts = ['9.0'], + filter_tree_name = None + )), + "Jpsi":(variables_DTF_results["intermediate"] + + make_composite_variables(options, data= LINE_DATA, + v2_pvs= V2_PVS, + simulation=config.isMC(), + MCTRUTH=MCTRUTH ) + + InclDetDimuon_MVA( pvs = V2_PVS, DiLeptonFromB=False,DiLeptonChildIdx=1 ) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options,data = LINE_DATA,v2_pvs= V2_PVS,ndau=2)), + "L1": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "X" : (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + pK_substitution_vars + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + make_intermediate_resonances_variables(options, data= LINE_DATA,v2_pvs= V2_PVS , ndau=2) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) ), + "H1": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "H2": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + #"ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert( sorted( VARIABLES.keys()) == sorted( FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options =options, + line_name = LINE_NAME, + fields = FIELDS, + variables = VARIABLES, + inputs = LINE_DATA, + name= f"{LINE_NAME}" , + tuple_name = "DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +@bind_string("Hlt2RD_LambdabToPKMuMu_SS") +def Hlt2RD_LambdabToPKMuMu_SS(options:Options, config : Config) : + LINE_NAME = "Hlt2RD_LambdabToPKMuMu_SS" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) [ (Lambda(1520)0 -> p+ K+) ]CC ]CC", + "Jpsi" : "[Lambda_b0 -> ^(J/psi(1S) -> mu+ mu-) [ (Lambda(1520)0 -> p+ K+) ]CC ]CC", + "L1" : "[Lambda_b0 -> (J/psi(1S) -> ^mu+ mu-) [ (Lambda(1520)0 -> p+ K+) ]CC ]CC", + "L2" : "[Lambda_b0 -> (J/psi(1S) -> mu+ ^mu-) [ (Lambda(1520)0 -> p+ K+) ]CC ]CC", + "X" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) ^[ (Lambda(1520)0 -> p+ K+) ]CC ]CC", + "H1" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) [ (Lambda(1520)0 -> ^p+ K+) ]CC ]CC", + "H2" : "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) [ (Lambda(1520)0 -> p+ ^K+) ]CC ]CC", + } + + # probbaly needs also track states covariances to store to use Christoph L. offline code ? + logger.debug("-------------- CREATING VARIABLES --------------------") + + ####### DTF with Jpsi and Psi2S constraint saving kinematics and lifetime + Constraints_Dict = { + "DTF" : {"substitutions" : [],"mass_constraints" : []}, + # Jpsi mass constraint + "DTF_Jpsi" : {"substitutions" : [],"mass_constraints" : ["J/psi(1S)"]}, + # Psi2S mass constraint + "DTF_Psi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [(Lambda(1520)0 -> p+ K+ ) ]CC ]CC"], "mass_constraints" : ["psi(2S)"]}, + # Constrained Lb mass + "DTF_HEAD" : {"substitutions" : [], "mass_constraints" : ["Lambda_b0"]}, + # p2K swap + "DTF_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+ ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+ ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+ ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p2Pi swap + "DTF_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+ ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+ ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+ ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2p swap + "DTF_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+ K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+ K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+ K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2pi swap + "DTF_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+ K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+ K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+ K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K p double swaps + "DTF_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> pi pi double swaps + "DTF_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K pi double swaps + "DTF_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{K+}} K+{{pi+}} ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> Pi p double swaps + "DTF_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu- ) [ (Lambda(1520)0 -> p+{{pi+}} K+{{p+}} ) ]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + } + + variables_DTF_results = make_dtf_variables_v2( + options = options, + data = LINE_DATA, + v2_pvs = V2_PVS, # comment out if no PV constraint? + Constraints_Config = Constraints_Dict) + + ####### PID substitution + + # pKmm_substitution_vars = FunctorCollection({ + # # proton ID + # "M_pKll_p2pi" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "pi+", "K-" )), + # "M_pKll_p2K" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "K+" , "K-" )), + # # kaon ID + # "M_pKll_K2pi" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "p+" , "pi-")), + # "M_pKll_K2p" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "p+" , "p~-" )), + # # double swaps + # "M_pKll_pK2Kp" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "K+" , "p~-" )), + # "M_pKll_pK2pipi": F.MASSWITHHYPOTHESES(("mu+", "mu+", "pi+", "pi-")), + # "M_pKll_pK2Kpi" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "K+" , "pi-")), + # "M_pKll_pK2pip" : F.MASSWITHHYPOTHESES(("mu+", "mu+", "pi+", "p~-" )), + # }) + + pK_substitution_vars = FunctorCollection({ + # proton ID + "M_pK_p2pi" : F.MASSWITHHYPOTHESES(("pi+", "K+" )), + "M_pK_p2K" : F.MASSWITHHYPOTHESES(("K+" , "K+" )), + # kaon ID + "M_pK_K2pi" : F.MASSWITHHYPOTHESES(("p+" , "pi+")), + "M_pK_K2p" : F.MASSWITHHYPOTHESES(("p+" , "p+" )), + # double swaps + "M_pK_pK2Kp" : F.MASSWITHHYPOTHESES(("K+" , "p+" )), + "M_pK_pK2pipi": F.MASSWITHHYPOTHESES(("pi+", "pi+")), + "M_pK_pK2Kpi" : F.MASSWITHHYPOTHESES(("K+" , "pi+")), + "M_pK_pK2pip" : F.MASSWITHHYPOTHESES(("pi+", "p+" )), + }) + + # m_pmu_p2mu, m_Kmu_K2mu variables and m_Kmumu to be reconstructed offline + + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options,data = LINE_DATA,v2_pvs= V2_PVS , ndau=2)+ + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + InclDetDielectron_MVA(pvs = V2_PVS, DiLeptonFromB=True,DiLeptonChildIdx=1 ) + + make_Isolation_variables(options = options, + bhead_label_decay = "Lambda_b0", + data = LINE_DATA, + line = LINE_NAME, + header_tes = 'Lb', + dr2_angle_list = [ '0.15' ], + max_delta_vertex_chi2_cuts = ['9.0'], + filter_tree_name = None )), + "Jpsi":(variables_DTF_results["intermediate"] + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + InclDetDimuon_MVA( pvs = V2_PVS, DiLeptonFromB=False,DiLeptonChildIdx=1 ) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options,data = LINE_DATA,v2_pvs= V2_PVS,ndau=2)), + "L1": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "X" : (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + pK_substitution_vars + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + make_intermediate_resonances_variables(options, data= LINE_DATA,v2_pvs= V2_PVS , ndau=2) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + ), + "H1": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "H2": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + #"ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert( sorted( VARIABLES.keys()) == sorted( FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options =options, + line_name = LINE_NAME, + fields = FIELDS, + variables = VARIABLES, + inputs = LINE_DATA, + name= f"{LINE_NAME}" , + tuple_name = "DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + + + +@bind_string("Hlt2RD_LambdabToPKEE") +def Hlt2RD_LambdabToPKEE(options:Options, config : Config) : + LINE_NAME = "Hlt2RD_LambdabToPKEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC", + "Jpsi" : "[Lambda_b0 -> ^(J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC", + "L1" : "[Lambda_b0 -> (J/psi(1S) -> ^e+ e-) (Lambda(1520)0 -> p+ K-)]CC", + "L2" : "[Lambda_b0 -> (J/psi(1S) -> e+ ^e-) (Lambda(1520)0 -> p+ K-)]CC", + "X" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) ^(Lambda(1520)0 -> p+ K-)]CC", + "H1" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> ^p+ K-)]CC", + "H2" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ ^K-)]CC", + } + + logger.debug("-------------- CREATING VARIABLES --------------------") + + + ####### DTF with Jpsi and Psi2S constraint saving kinematics and lifetime + Constraints_Dict = { + "DTF" : {"substitutions" : [],"mass_constraints" : []}, + # Jpsi mass constraint + "DTF_Jpsi" : {"substitutions" : [],"mass_constraints" : ["J/psi(1S)"]}, + # Psi2S mass constraint + "DTF_Psi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+ K- )]CC"], "mass_constraints" : ["psi(2S)"]}, + # Constrained Lb mass + "DTF_HEAD" : {"substitutions" : [], "mass_constraints" : ["Lambda_b0"]}, + # p2K swap + "DTF_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K- )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K- )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K- )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p2Pi swap + "DTF_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K- )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K- )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K- )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2p swap + "DTF_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+ K-{{p~-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2pi swap + "DTF_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+ K-{{pi-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K p double swaps + "DTF_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> pi pi double swaps + "DTF_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K pi double swaps + "DTF_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{K+}} K-{{pi-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> Pi p double swaps + "DTF_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e- ) (Lambda(1520)0 -> p+{{pi+}} K-{{p~-}} )]CC" ],"mass_constraints" : ["psi(2S)"]}, + } + + + + variables_DTF_results = make_dtf_variables_v2( + options = options, + data = LINE_DATA, + v2_pvs = V2_PVS, # comment out if no PV constraint? + Constraints_Config = Constraints_Dict) + + + + ####### PID substitution + # TODO : not possible to do with intermediate J/Psi + # pKee_substitution_vars = FunctorCollection({ + # # proton ID + # "M_pKll_p2pi" : F.MASSWITHHYPOTHESES(("e+", "e-", "pi+", "K-" )), + # "M_pKll_p2K" : F.MASSWITHHYPOTHESES(("e+", "e-", "K+" , "K-" )), + # # kaon ID + # "M_pKll_K2pi" : F.MASSWITHHYPOTHESES(("e+", "e-", "p+" , "pi-")), + # "M_pKll_K2p" : F.MASSWITHHYPOTHESES(("e+", "e-", "p+" , "p~-" )), + # # double swaps + # "M_pKll_pK2Kp" : F.MASSWITHHYPOTHESES(("e+", "e-", "K+" , "p~-" )), + # "M_pKll_pK2pipi": F.MASSWITHHYPOTHESES(("e+", "e-", "pi+", "pi-")), + # "M_pKll_pK2Kpi" : F.MASSWITHHYPOTHESES(("e+", "e-", "K+" , "pi-")), + # "M_pKll_pK2pip" : F.MASSWITHHYPOTHESES(("e+", "e-", "pi+", "p~-" )), + # }) + + pK_substitution_vars = FunctorCollection({ + # proton ID + "M_pK_p2pi" : F.MASSWITHHYPOTHESES(("pi+", "K-" )), + "M_pK_p2K" : F.MASSWITHHYPOTHESES(("K+" , "K-" )), + # kaon ID + "M_pK_K2pi" : F.MASSWITHHYPOTHESES(("p+" , "pi-")), + "M_pK_K2p" : F.MASSWITHHYPOTHESES(("p+" , "p~-" )), + # double swaps + "M_pK_pK2Kp" : F.MASSWITHHYPOTHESES(("K+" , "p~-" )), + "M_pK_pK2pipi": F.MASSWITHHYPOTHESES(("pi+", "pi-")), + "M_pK_pK2Kpi" : F.MASSWITHHYPOTHESES(("K+" , "pi-")), + "M_pK_pK2pip" : F.MASSWITHHYPOTHESES(("pi+", "p~-" )), + }) + + + + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data = LINE_DATA, v2_pvs= V2_PVS , ndau=2)+ + make_composite_variables(options, data= LINE_DATA, v2_pvs= V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH ) + + InclDetDielectron_MVA( pvs = V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1 ) + + make_Isolation_variables(options = options, + bhead_label_decay = "Lambda_b0", + data = LINE_DATA, + line = LINE_NAME, + header_tes = 'Lb', + dr2_angle_list = [ '0.15' ], + max_delta_vertex_chi2_cuts = ['9.0'], + filter_tree_name = None + )) , + "Jpsi":(variables_DTF_results["intermediate"] + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH ) + + InclDetDielectron_MVA(pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1 ) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA,v2_pvs= V2_PVS, ndau=2)), + "L1": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "X" : (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + pK_substitution_vars + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + make_intermediate_resonances_variables(options, data = LINE_DATA,v2_pvs= V2_PVS , ndau=2) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) ), + "H1": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "H2": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + #"ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert( sorted( VARIABLES.keys()) == sorted( FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options =options, + line_name = LINE_NAME, + fields = FIELDS, + variables = VARIABLES, + inputs = LINE_DATA, + name= f"{LINE_NAME}" , + tuple_name = "DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + + +@bind_string("Hlt2RD_LambdabToPKEE_SS") +def Hlt2RD_LambdabToPKEE_SS(options:Options, config : Config) : + LINE_NAME = "Hlt2RD_LambdabToPKEE_SS" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) [ (Lambda(1520)0 -> p+ K+ ) ]CC ]CC", + "Jpsi" : "[Lambda_b0 -> ^(J/psi(1S) -> e+ e-) [ (Lambda(1520)0 -> p+ K+ ) ]CC ]CC", + "L1" : "[Lambda_b0 -> (J/psi(1S) -> ^e+ e-) [ (Lambda(1520)0 -> p+ K+ ) ]CC ]CC", + "L2" : "[Lambda_b0 -> (J/psi(1S) -> e+ ^e-) [ (Lambda(1520)0 -> p+ K+ ) ]CC ]CC", + "X" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) ^[ (Lambda(1520)0 -> p+ K+ ) ]CC ]CC", + "H1" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) [ (Lambda(1520)0 -> ^p+ K+ ) ]CC ]CC", + "H2" : "[Lambda_b0 -> (J/psi(1S) -> e+ e-) [ (Lambda(1520)0 -> p+ ^K+ ) ]CC ]CC", + } + + logger.debug("-------------- CREATING VARIABLES --------------------") + + ####### DTF with Jpsi and Psi2S constraint saving kinematics and lifetime + Constraints_Dict = { + "DTF" : {"substitutions" : [],"mass_constraints" : []}, + # Jpsi mass constraint + "DTF_Jpsi" : {"substitutions" : [],"mass_constraints" : ["J/psi(1S)"]}, + # Psi2S mass constraint + "DTF_Psi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+ K+ )]CC ]CC"], "mass_constraints" : ["psi(2S)"]}, + # Constrained Lb mass + "DTF_HEAD" : {"substitutions" : [], "mass_constraints" : ["Lambda_b0"]}, + # p2K swap + "DTF_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+ )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+ )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2K" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+ )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p2Pi swap + "DTF_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+ )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+ )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_p2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+ )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2p swap + "DTF_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+ K+{{p+}} )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+ K+{{p+}} )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2p" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+ K+{{p+}} )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # K2pi swap + "DTF_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+ K+{{pi+}} )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+ K+{{pi+}} )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_K2Pi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+ K+{{pi+}} )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K p double swaps + "DTF_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+{{p+}} )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+{{p+}} )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2Kp" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+{{p+}} )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> pi pi double swaps + "DTF_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+{{pi+}} )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+{{pi+}} )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+{{pi+}} )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> K pi double swaps + "DTF_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+{{pi+}} )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+{{pi+}} )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2KPi" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+{{K+}} K+{{pi+}} )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + # p K -> Pi p double swaps + "DTF_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+{{p+}} )]CC ]CC" ],"mass_constraints" : []}, + "DTF_Jpsi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S) -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+{{p+}} )]CC ]CC" ],"mass_constraints" : ["J/psi(1S)"]}, + "DTF_Psi_pK2PiP" : {"substitutions" : ["[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) [(Lambda(1520)0 -> p+{{pi+}} K+{{p+}} )]CC ]CC" ],"mass_constraints" : ["psi(2S)"]}, + } + + variables_DTF_results = make_dtf_variables_v2( + options = options, + data = LINE_DATA, + v2_pvs = V2_PVS, # comment out if no PV constraint? + Constraints_Config = Constraints_Dict) + + + + + ####### PID substitution + # TODO : NOT POSSIBLE to do with an intermediate J/Psi ( solutions? ) + # pKee_substitution_vars = FunctorCollection({ + # # proton ID + # "M_pKll_p2pi" : F.MASSWITHHYPOTHESES(("e+", "e+", "pi+", "K-" )), + # "M_pKll_p2K" : F.MASSWITHHYPOTHESES(("e+", "e+", "K+" , "K-" )), + # # kaon ID + # "M_pKll_K2pi" : F.MASSWITHHYPOTHESES(("e+", "e+", "p+" , "pi-")), + # "M_pKll_K2p" : F.MASSWITHHYPOTHESES(("e+", "e+", "p+" , "p~-" )), + # # double swaps + # "M_pKll_pK2Kp" : F.MASSWITHHYPOTHESES(("e+", "e+", "K+" , "p~-" )), + # "M_pKll_pK2pipi": F.MASSWITHHYPOTHESES(("e+", "e+", "pi+", "pi-")), + # "M_pKll_pK2Kpi" : F.MASSWITHHYPOTHESES(("e+", "e+", "K+" , "pi-")), + # "M_pKll_pK2pip" : F.MASSWITHHYPOTHESES(("e+", "e+", "pi+", "p~-" )), + # }) + + pK_substitution_vars = FunctorCollection({ + # proton ID + "M_pK_p2pi" : F.MASSWITHHYPOTHESES(("pi+", "K+" )), + "M_pK_p2K" : F.MASSWITHHYPOTHESES(("K+" , "K+" )), + # kaon ID + "M_pK_K2pi" : F.MASSWITHHYPOTHESES(("p+" , "pi+")), + "M_pK_K2p" : F.MASSWITHHYPOTHESES(("p+" , "p+" )), + # double swaps + "M_pK_pK2Kp" : F.MASSWITHHYPOTHESES(("K+" , "p+" )), + "M_pK_pK2pipi": F.MASSWITHHYPOTHESES(("pi+", "pi-")), + "M_pK_pK2Kpi" : F.MASSWITHHYPOTHESES(("K+" , "pi-")), + "M_pK_pK2pip" : F.MASSWITHHYPOTHESES(("pi+", "p+" )), + }) + + + + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data = LINE_DATA, v2_pvs= V2_PVS , ndau=2)+ + make_composite_variables(options, data= LINE_DATA, v2_pvs= V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH ) + + InclDetDielectron_MVA( pvs = V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1 ) + + make_Isolation_variables(options = options, + bhead_label_decay = "Lambda_b0", + data = LINE_DATA, + line = LINE_NAME, + header_tes = 'Lb', + dr2_angle_list = [ '0.15' ], + max_delta_vertex_chi2_cuts = ['9.0'], + filter_tree_name = None + )), + "Jpsi":(variables_DTF_results["intermediate"] + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH ) + + InclDetDielectron_MVA(pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1 ) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA,v2_pvs= V2_PVS, ndau=2)), + "L1": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (#make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "X" : (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + pK_substitution_vars + + make_composite_variables(options, data= LINE_DATA,v2_pvs= V2_PVS,simulation=config.isMC(),MCTRUTH=MCTRUTH ) + + make_intermediate_resonances_variables(options, data = LINE_DATA,v2_pvs= V2_PVS , ndau=2) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) ), + "H1": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + "H2": (#make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS,simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA) ), + #"ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert( sorted( VARIABLES.keys()) == sorted( FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options =options, + line_name = LINE_NAME, + fields = FIELDS, + variables = VARIABLES, + inputs = LINE_DATA, + name= f"{LINE_NAME}" , + tuple_name = "DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +######################################################################### +######################################################################### +######################################################################### +TUPLES_ALG_BINDING = {} +# Create a copy of the globals dictionary +globals_copy = dict(globals()) +# Iterate over the copy to avoid modifying the globals dictionary +for name, obj in globals_copy.items(): + if callable(obj) and hasattr(obj, 'name'): + if obj.name not in TUPLES_ALG_BINDING : + TUPLES_ALG_BINDING[obj.name] = obj +for k in TUPLES_ALG_BINDING.keys() : + logger.debug(f"{k} can be bound to its own function, all the rest no. Bounded to {TUPLES_ALG_BINDING[k]}") +######################################################################### +######################################################################### +######################################################################### diff --git a/rd_ap_2024/tupling/hlt2/__init__.py b/rd_ap_2024/tupling/hlt2/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..752448d7703f26f27759e46e23242318d4520e11 --- /dev/null +++ b/rd_ap_2024/tupling/hlt2/__init__.py @@ -0,0 +1,45 @@ +from .b_to_xll import TUPLES_ALG_BINDING as TUPLE_ALG_BIND_hlt2_b_to_xll +from .b_to_xll_mva import TUPLES_ALG_BINDING as TUPLE_ALG_BIND_hlt2_b_to_xll_mva +from .b_to_hemu_control_modes import TUPLES_ALG_BINDING as TUPLE_ALG_BIND_hlt2_b_to_hemu_control_modes +from .Rpk_lines import TUPLES_ALG_BINDING as TUPLE_ALG_BIND_hlt2_Rpk_lines + +def check_no_overlap(dict1 : dict , dict2: dict): + """helper function : check if two dictionary has overlaps in their key content + Args: + dict1 (dictionary): a dictionary (1) + dict2 (dictionary): a dictionary (2) + Returns: + bool: True if no overlaps, False if they overlap + """ + # Get the set of keys for each dictionary + keys1 = set(dict1.keys()) + keys2 = set(dict2.keys()) + # Check if there is an intersection between the sets of keys + if keys1.isdisjoint(keys2): + return True # No overlap + else: + return False # Overlap exists +def merge_dicts_list(dict_list : list[dict]) -> dict: + """ + Args: + dict_list (a list of dictionary): + Raises: + ValueError: chain dictionary keys and ensure when chaining that we have no overlaps + Returns: + dict: a fully merged dictionary + """ + merged_dict = {} + for d in dict_list: + # Check for overlapping keys + if not check_no_overlap(merged_dict, d): + raise ValueError("One or more dictionaries have overlapping keys.") + # Update merged_dict with the contents of d + merged_dict.update(d) + return merged_dict + +TUPLES_ALG_BINDING = merge_dicts_list( [ + TUPLE_ALG_BIND_hlt2_b_to_xll, + TUPLE_ALG_BIND_hlt2_b_to_xll_mva, + TUPLE_ALG_BIND_hlt2_b_to_hemu_control_modes, + TUPLE_ALG_BIND_hlt2_Rpk_lines, +] ) diff --git a/rd_ap_2024/tupling/hlt2/b_to_hemu_control_modes.py b/rd_ap_2024/tupling/hlt2/b_to_hemu_control_modes.py new file mode 100644 index 0000000000000000000000000000000000000000..9e6654c334fbcbbddedb4102d40880d15e6d9988 --- /dev/null +++ b/rd_ap_2024/tupling/hlt2/b_to_hemu_control_modes.py @@ -0,0 +1,850 @@ +from rd_ap_2024.utils.log_store import LogStore +from rd_ap_2024.tupling.Config import Config +from rd_ap_2024.tupling.variables.rd_stream_tupling_functions import ( + make_composite_variables, + make_basic_variables, + make_hlt_event_variables, + make_track_variables, + Funtuple_with_filter, + make_intermediate_resonances_variables, + make_truth_variables, + make_variables_with_swapped_mass_hypothesis +) + +from rd_ap_2024.tupling.variables.inclusive_detached_dilepton_mvas import( + # dimuons + InclDetDimuon_MVA, + InclDetDimuon_ThreeBody_MVA, + InclDetDimuon_FourBody_MVA, + InclDetDimuon_neutral_MVA, + # dielectrons + InclDetDielectron_MVA, + InclDetDielectron_ThreeBody_MVA, + InclDetDielectron_FourBody_MVA, + InclDetDielectron_neutral_MVA, + # di electron/muon + InclDetElectronMuon_MVA, + InclDetElectronMuon_ThreeBody_MVA, + InclDetElectronMuon_FourBody_MVA, + InclDetElectronMuon_neutral_MVA +) + +from rd_ap_2024.tupling.variables.tupling_dtf import ( + make_dtf_variables_v2, +) +from DaVinciTools import SubstitutePID + +from rd_ap_2024.tupling.variables.rd_stream_isolation_functions import ( + make_Isolation_variables +) + +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) +import Functors as F +import FunTuple.functorcollections as FC +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +from PyConf.Algorithms import AdvancedCloneKiller, Run2SSPionTagger +from GaudiKernel.SystemOfUnits import GeV +from Hlt2Conf.algorithms_thor import ParticleFilter +from Hlt2Conf.standard_particles import (# type: ignore[import] + make_long_pions, + make_long_kaons, + make_long_muons, + standard_protoparticle_filter, +) +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +from DaVinciMCTools import MCTruthAndBkgCat +from FunTuple.functorcollections import SelectionInfo +from DecayTreeFitter import DecayTreeFitter +# specific for the B2OC SigmaNet +import Functors.math as fmath + + +logger=LogStore.add_logger('rd_ap_2024:b_to_hemu_control_modes') + +def bind_string(name): + + def decorator(func): + func.name = name + return func + + return decorator + +# Lines from b_to_hemu_control_modes module tupling here +# Algorithms for those Lines covered : +# - Hlt2RD_BuToKpJpsi_JpsiToMuMu +# - Hlt2RD_BuToKpJpsi_JpsiToEE +# - Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE +# - Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu +# - Hlt2RD_LbToPKJpsi_JpsiToMuMu +# - Hlt2RD_LbToPKJpsi_JpsiToEE +# - Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu +# - Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE +# - Hlt2RD_BuToPipJpsi_JpsiToMuMu [TODO] +# - Hlt2RD_BuToPipJpsi_JpsiToEE [TODO] + + +# https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r7/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_hemu_control_modes.py#L40 +@bind_string("Hlt2RD_BuToKpJpsi_JpsiToMuMu") +def Hlt2RD_BuToKpJpsi_JpsiToMuMu(options:Options, config: Config): + LINE_NAME = "Hlt2RD_BuToKpJpsi_JpsiToMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "[B+ -> (J/psi(1S) -> mu+ mu-) K+]CC", + "Jpsi": "[B+ -> ^(J/psi(1S) -> mu+ mu-) K+]CC", + "L1": "[B+ -> (J/psi(1S) -> ^mu+ mu-) K+]CC", + "L2": "[B+ -> (J/psi(1S) -> mu+ ^mu-) K+]CC", + "K": "[B+ -> (J/psi(1S) -> mu+ mu-) ^K+]CC", + } + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["[B+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) K+]CC"] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "B+"]}, + "DTF_K2Pi": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+ mu-) K+{{pi+}}]CC"] , "mass_constraints": []}, + "DTF_K2Pi_JPsi": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+ mu-) K+{{pi+}}]CC"] , "mass_constraints": ["J/psi(1S)"]}, + "DTF_K2Pi_Psi": { "substitutions": ["[B+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) K+{{pi+}}]CC"] , "mass_constraints": ["psi(2S)"]}, + "DTF_KMu2MuK": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+{{K+}} mu- ) K+{{mu+}}]CC"] , "mass_constraints": []}, + "DTF_MuMu2KK": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+{{K+}} mu-{{K-}} ) K+]CC"] , "mass_constraints": []}, + "DTF_MuMu2PiPi": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+{{pi+}} mu-{{pi-}}) K+]CC"] , "mass_constraints": []}, + "DTF_MuMuK2KKPi": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+{{K+}} mu-{{K-}} ) K+{{pi+}}]CC"], "mass_constraints": []}, + "DTF_MuMuK2PiPiPi": { "substitutions": ["[B+ -> (J/psi(1S) -> mu+{{pi+}} mu-{{pi-}}) K+{{pi+}}]CC"], "mass_constraints": []} + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( + variables_DTF_results["mother"] + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_Isolation_variables(options=options, + bhead_label_decay="B+", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Bu', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None) + ), + "Jpsi": ( + variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + ), + "K": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L1": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +@bind_string("Hlt2RD_BuToKpJpsi_JpsiToEE") +def Hlt2RD_BuToKpJpsi_JpsiToEE(options:Options, config: Config): + LINE_NAME = "Hlt2RD_BuToKpJpsi_JpsiToEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "[B+ -> (J/psi(1S) -> e+ e-) K+]CC", + "Jpsi": "[B+ -> ^(J/psi(1S) -> e+ e-) K+]CC", + "L1": "[B+ -> (J/psi(1S) -> ^e+ e-) K+]CC", + "L2": "[B+ -> (J/psi(1S) -> e+ ^e-) K+]CC", + "K": "[B+ -> (J/psi(1S) -> e+ e-) ^K+]CC", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["[B+ -> (J/psi(1S){{psi(2S)}} -> e+ e-) K+]CC"] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "B+"]}, + "DTF_K2Pi": { "substitutions": ["[B+ -> (J/psi(1S) -> e+ e-) K+{{pi+}}]CC"] , "mass_constraints": []}, + "DTF_K2Pi_JPsi": { "substitutions": ["[B+ -> (J/psi(1S) -> e+ e-) K+{{pi+}}]CC"] , "mass_constraints": ["J/psi(1S)"]}, + "DTF_K2Pi_Psi": { "substitutions": ["[B+ -> (J/psi(1S){{psi(2S)}} -> e+ e-) K+{{pi+}}]CC"] , "mass_constraints": ["psi(2S)"]}, + "DTF_KE2EK": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{K+}} e- ) K+{{e+}}]CC" ] , "mass_constraints": []}, + "DTF_EE2KK": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{K+}} e-{{K-}} ) K+]CC"] , "mass_constraints": []}, + "DTF_EE2PiPi": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) K+]CC"] , "mass_constraints": []}, + "DTF_EEK2KKPi": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{K+}} e-{{K-}} ) K+{{pi+}}]CC"] , "mass_constraints": []}, + "DTF_EEK2PiPiPi": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) K+{{pi+}}]CC"], "mass_constraints": []} + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_Isolation_variables(options=options, + bhead_label_decay="B+", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Bu', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + )), + "Jpsi": (variables_DTF_results["intermediate"] + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "K": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L1": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +# https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r7/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_hemu_control_modes.py#L122 +@bind_string("Hlt2RD_LbToPKJpsi_JpsiToMuMu") +def Hlt2RD_LbToPKJpsi_JpsiToMuMu(options:Options, config: Config): + LINE_NAME = "Hlt2RD_LbToPKJpsi_JpsiToMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "Lb": "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC", + "Jpsi": "[Lambda_b0 -> ^(J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC", + "L1": "[Lambda_b0 -> (J/psi(1S) -> ^mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC", + "L2": "[Lambda_b0 -> (J/psi(1S) -> mu+ ^mu-) (Lambda(1520)0 -> p+ K-)]CC", + "Lz": "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) ^(Lambda(1520)0 -> p+ K-)]CC", + "P": "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> ^p+ K-)]CC", + "K": "[Lambda_b0 -> (J/psi(1S) -> mu+ mu-) (Lambda(1520)0 -> p+ ^K-)]CC", + } + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-)]CC'] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "Lambda_b0"]}, + "DTF_K2Pi": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{pi-}})]CC'] , "mass_constraints": []}, + "DTF_K2P": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+ K-{{p~-}})]CC'] , "mass_constraints": []}, + "DTF_P2K": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-)]CC'] , "mass_constraints": []}, + "DTF_KP2PK": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}})]CC'] , "mass_constraints": []}, + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "Lb": (variables_DTF_results["mother"] + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDimuon_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_Isolation_variables(options=options, + bhead_label_decay="Lambda_b0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Lb', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "L1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Lz": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "P": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +# https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r7/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_hemu_control_modes.py#L122 +@bind_string("Hlt2RD_LbToPKJpsi_JpsiToEE") +def Hlt2RD_LbToPKJpsi_JpsiToEE(options:Options, config: Config): + LINE_NAME = "Hlt2RD_LbToPKJpsi_JpsiToEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "Lb": "[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC", + "Jpsi": "[Lambda_b0 -> ^(J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC", + "L1": "[Lambda_b0 -> (J/psi(1S) -> ^e+ e-) (Lambda(1520)0 -> p+ K-)]CC", + "L2": "[Lambda_b0 -> (J/psi(1S) -> e+ ^e-) (Lambda(1520)0 -> p+ K-)]CC", + "Lz": "[Lambda_b0 -> (J/psi(1S) -> e+ e-) ^(Lambda(1520)0 -> p+ K-)]CC", + "P": "[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> ^p+ K-)]CC", + "K": "[Lambda_b0 -> (J/psi(1S) -> e+ e-) (Lambda(1520)0 -> p+ ^K-)]CC", + } + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+ K-)]CC'] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "Lambda_b0"]}, + "DTF_K2Pi": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+ K-{{pi-}})]CC'] , "mass_constraints": []}, + "DTF_K2P": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+ K-{{p~-}})]CC'] , "mass_constraints": []}, + "DTF_P2K": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+{{K+}} K-)]CC'] , "mass_constraints": []}, + "DTF_KP2PK": { "substitutions": ['[Lambda_b0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (Lambda(1520)0 -> p+{{K+}} K-{{p~-}})]CC'] , "mass_constraints": []}, + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "Lb": (variables_DTF_results["mother"] + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC()) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_Isolation_variables(options=options, + bhead_label_decay="Lambda_b0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Lb', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "L1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Lz": (variables_DTF_results["intermediate"] + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "P": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())) + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +# https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r7/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_hemu_control_modes.py#L122 +@bind_string("Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu") +def Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu(options:Options, config: Config): + # ## had a wrong decay descriptor + LINE_NAME = "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + # See diffs introduced in https://gitlab.cern.ch/lhcb/Moore/-/commit/52116267897fc3f38b27aeaacdbbc15aee4aaa7a#fae9b3f7b4e5f397815f800458576e36be314644 for post-TS changes + if config.dataPeriod() in ["Sprucing24c2", "Sprucing24c3", "Sprucing24c4"]: + #### to have this line to not throw errors in the info.yaml the flag must be passed + LINE_DATA = LINE_DATA_RAW + else: + LINE_DATA = SubstitutePID( + "Subs_HEADLABEL_Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu_{hash}", + LINE_DATA_RAW, # input particle container + substitutions=[ + "[B+{{B0}}-> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC" + ], + ).Particles + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": f"[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC", + "Jpsi": f"[B0 -> ^(J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC", + "L1": f"[B0 -> (J/psi(1S) -> ^mu+ mu-) (K*(892)0-> K+ pi-)]CC", + "L2": f"[B0 -> (J/psi(1S) -> mu+ ^mu-) (K*(892)0-> K+ pi-)]CC", + "Kst": f"[B0 -> (J/psi(1S) -> mu+ mu-) ^(K*(892)0-> K+ pi-)]CC", + "H1": f"[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> ^K+ pi-)]CC", + "H2": f"[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ ^pi-)]CC", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["[B0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (K*(892)0-> K+ pi-)]CC"] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "B0"]} + } + + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDimuon_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Bd', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + # InclDetDimuon_MVA( pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": (variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Kst": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "H1": (variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "H2": (variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +################################################################################################################################ + + +@bind_string("Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE") +def Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE(options:Options, config: Config): + # ## had a wrong decay descriptor + LINE_NAME = "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + if config.dataPeriod() in ["Sprucing24c3", "Sprucing24c4"]: + LINE_DATA = LINE_DATA_RAW + else: + LINE_DATA = SubstitutePID( + "Subs_HEADLABEL_Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE_{hash}", + LINE_DATA_RAW, # input particle container + substitutions=[ + "[B+{{B0}}-> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC" + ], + ).Particles + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": f"[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC", + "Jpsi": f"[B0 -> ^(J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC", + "L1": f"[B0 -> (J/psi(1S) -> ^e+ e-) (K*(892)0-> K+ pi-)]CC", + "L2": f"[B0 -> (J/psi(1S) -> e+ ^e-) (K*(892)0-> K+ pi-)]CC", + "Kst": f"[B0 -> (J/psi(1S) -> e+ e-) ^(K*(892)0-> K+ pi-)]CC", + "H1": f"[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> ^K+ pi-)]CC", + "H2": f"[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ ^pi-)]CC", + } + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-)]CC"] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "B0"]} + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Bd', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Kst": ( + variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "H1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "H2": ( + variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)) + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +@bind_string("Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu") +def Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu(options:Options, config: Config): + # ## had a wrong decay descriptor + LINE_NAME = "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + if config.dataPeriod() in ["Sprucing24c2", "Sprucing24c3", "Sprucing24c4"]: + LINE_DATA = LINE_DATA_RAW + else: + LINE_DATA = SubstitutePID( + "Subs_HEADLABEL_Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu_{hash}", + LINE_DATA_RAW, # input particle container + substitutions=[ + "[B+{{B_s0}} -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ K-)]CC" + ], + ).Particles + + FIELDS = { + "B": f"B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ K-)", + "Jpsi": f"B_s0 -> ^(J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ K-)", + "L1": f"B_s0 -> (J/psi(1S) -> ^mu+ mu-) (phi(1020)-> K+ K-)", + "L2": f"B_s0 -> (J/psi(1S) -> mu+ ^mu-) (phi(1020)-> K+ K-)", + "Phi": f"B_s0 -> (J/psi(1S) -> mu+ mu-) ^(phi(1020)-> K+ K-)", + "K1": f"B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> ^K+ K-)", + "K2": f"B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ ^K-)", + } + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["B_s0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (phi(1020)-> K+ K-)"] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "B_s0"]} + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDimuon_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B_s0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Bs', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + # InclDetDimuon_MVA( pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "L2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "Phi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "K1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +@bind_string("Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE") +def Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE(options:Options, config: Config): + # ## had a wrong decay descriptor + LINE_NAME = "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + if config.dataPeriod() in ["Sprucing24c3", "Sprucing24c4"]: + LINE_DATA = LINE_DATA_RAW + else: + LINE_DATA = SubstitutePID( + "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE_{hash}", + LINE_DATA_RAW, # input particle container + substitutions=[ + "[B+{{B_s0}} -> (J/psi(1S) -> e+ e-) (phi(1020)-> K+ K-)]CC" + ], + ).Particles + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": f"B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020)-> K+ K-)", + "Jpsi": f"B_s0 -> ^(J/psi(1S) -> e+ e-) (phi(1020)-> K+ K-)", + "L1": f"B_s0 -> (J/psi(1S) -> ^e+ e-) (phi(1020)-> K+ K-)", + "L2": f"B_s0 -> (J/psi(1S) -> e+ ^e-) (phi(1020)-> K+ K-)", + "Phi": f"B_s0 -> (J/psi(1S) -> e+ e-) ^(phi(1020)-> K+ K-)", + "K1": f"B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020)-> ^K+ K-)", + "K2": f"B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020)-> K+ ^K-)", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["B_s0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (phi(1020)-> K+ K-)"] , "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": [ "B_s0"]} + } + + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B_s0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='Bs', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + # InclDetDimuon_MVA( pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "L2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "Phi": ( + variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "K1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "K2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +######################################################################### +######################################################################### +######################################################################### +TUPLES_ALG_BINDING = {} +# Create a copy of the globals dictionary +globals_copy = dict(globals()) +# Iterate over the copy to avoid modifying the globals dictionary +for name, obj in globals_copy.items(): + if callable(obj) and hasattr(obj, 'name'): + if obj.name not in TUPLES_ALG_BINDING: + TUPLES_ALG_BINDING[obj.name] = obj +for k in TUPLES_ALG_BINDING.keys(): + logger.debug(f"{k} can be bound to its own function, all the rest no. Bounded to {TUPLES_ALG_BINDING[k]}") +######################################################################### +######################################################################### +######################################################################### diff --git a/rd_ap_2024/tupling/hlt2/b_to_xll.py b/rd_ap_2024/tupling/hlt2/b_to_xll.py new file mode 100644 index 0000000000000000000000000000000000000000..0d52ce43962987b3c96e6abe792d581a06f8fea4 --- /dev/null +++ b/rd_ap_2024/tupling/hlt2/b_to_xll.py @@ -0,0 +1,1454 @@ +from rd_ap_2024.utils.log_store import LogStore +from rd_ap_2024.tupling.Config import Config +from rd_ap_2024.tupling.variables.rd_stream_tupling_functions import ( + make_composite_variables, + make_basic_variables, + make_hlt_event_variables, + make_track_variables, + Funtuple_with_filter, FunTuple_no_Filter, Filter_Of_FunTuple, + make_intermediate_resonances_variables, + make_truth_variables, + make_variables_with_swapped_mass_hypothesis +) +from PyConf.Algorithms import ParticleRangeFilter # , ParticleFilter +from PyConf.dataflow import DataHandle # type: ignore[import] +from GaudiKernel.SystemOfUnits import MeV + +from rd_ap_2024.tupling.variables.inclusive_detached_dilepton_mvas import( + # dimuons + InclDetDimuon_MVA, + InclDetDimuon_ThreeBody_MVA, + InclDetDimuon_FourBody_MVA, + InclDetDimuon_neutral_MVA, + # dielectrons + InclDetDielectron_MVA, + InclDetDielectron_ThreeBody_MVA, + InclDetDielectron_FourBody_MVA, + InclDetDielectron_neutral_MVA, + # di electron/muon + InclDetElectronMuon_MVA, + InclDetElectronMuon_ThreeBody_MVA, + InclDetElectronMuon_FourBody_MVA, + InclDetElectronMuon_neutral_MVA +) + +from rd_ap_2024.tupling.variables.tupling_dtf import ( + make_dtf_variables_v2 +) +from DaVinciTools import SubstitutePID + +from rd_ap_2024.tupling.variables.rd_stream_isolation_functions import ( + make_Isolation_variables +) + +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) +import Functors as F +import FunTuple.functorcollections as FC +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +from PyConf.Algorithms import AdvancedCloneKiller, Run2SSPionTagger +from GaudiKernel.SystemOfUnits import GeV +from Hlt2Conf.algorithms_thor import ParticleFilter +from Hlt2Conf.standard_particles import (# type: ignore[import] + make_long_pions, + make_long_kaons, + make_long_muons, + standard_protoparticle_filter, +) +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +from DaVinciMCTools import MCTruthAndBkgCat +from FunTuple.functorcollections import SelectionInfo +from DecayTreeFitter import DecayTreeFitter +# specific for the B2OC SigmaNet +import Functors.math as fmath + +logger=LogStore.add_logger('rd_ap_2024:b_to_xll') + +def bind_string(name): + + def decorator(func): + func.name = name + return func + + return decorator + +# Lines from b_to_xll_hlt2 module tupling here +# b_to_xll_hlt2.py tupling lines +# Algorithms for those Lines covered : +# - Hlt2RD_BuToKpEE +# - Hlt2RD_B0ToKpKmEE +# - Hlt2RD_B0ToKpKmMuMu +# - Hlt2RD_B0ToKpPimMuMu +# - Hlt2RD_B0ToPipPimMuMu +# - Hlt2RD_B0ToKpPimEE +# - Hlt2RD_BuToHpMuMu_Incl +# + + +################################################################################################ +# B+ -> K+ E+E- Line tupling algorithm +############################################################################################### +@bind_string("Hlt2RD_BuToKpEE") +def Hlt2RD_BuToKpEE(options:Options, config: Config): + LINE_NAME = "Hlt2RD_BuToKpEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "[B+ -> (J/psi(1S) -> e+ e-) K+]CC", + "Jpsi": "[B+ -> ^(J/psi(1S) -> e+ e-) K+]CC", + "L1": "[B+ -> (J/psi(1S) -> ^e+ e-) K+]CC", + "L2": "[B+ -> (J/psi(1S) -> e+ ^e-) K+]CC", + "K": "[B+ -> (J/psi(1S) -> e+ e-) ^K+]CC", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": [ "J/psi(1S)"]}, + "DTF_Psi2S": { "substitutions": ["[B+ -> (J/psi(1S){{psi(2S)}} -> e+ e-) K+]CC" ], "mass_constraints": [ "psi(2S)"]}, + "DTF_HEAD": { "substitutions": [], "mass_constraints": [ "B+"]}, + "DTF_K2Pi_Swap": { "substitutions": ["[B+ -> (J/psi(1S) -> e+ e-) K+{{pi+}}]CC" ], "mass_constraints": [ ]}, + "DTF_KE2EK_Swap": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{K+}} e-) K+{{e+}} ]CC" ], "mass_constraints": [ ]}, + "DTF_EE2KK_Swap": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{K+}} e-{{K-}} ) K+ ]CC" ], "mass_constraints": [ ]}, + "DTF_EE2PiPi_Swap": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) K+ ]CC" ], "mass_constraints": [ ]}, + "DTF_EE2KPi_Swap": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{K+}} e-{{pi-}}) K+ ]CC" ], "mass_constraints": [ ]}, + "DTF_EE2PiK_Swap": { "substitutions": ["[B+ -> (J/psi(1S) -> e+{{pi+}} e-{{K-}} ) K+ ]CC" ], "mass_constraints": [ ]} + } + variables_DTF_results = make_dtf_variables_v2(options=options, + data=LINE_DATA, + v2_pvs=V2_PVS, + Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + make_Isolation_variables(options=options, + bhead_label_decay="B+", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None )), + "Jpsi": (variables_DTF_results["intermediate"] + + # InclDetDielectron_MVA( pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1 ) #DEBUG ME to be equal to the other. + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "K": (# make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "L1": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + "L2": (# make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + variables_DTF_results["finalstates"] + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +@bind_string("Hlt2RD_B0ToKpKmEE_SameSign") +def Hlt2RD_B0ToKpKmEE_SameSign(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToKpKmEE_SameSign" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA_RAW = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # Define the swap + LINE_DATA = SubstitutePID( + "Substitue_HEAD_Hlt2RD_B0ToKpKmEE_SameSign_{hash}", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "B0{{B_s0}} -> (J/psi(1S) -> e+ e+) (phi(1020)-> K+ K-)", + "B0{{B_s0}} -> (J/psi(1S) -> e- e-) (phi(1020)-> K+ K-)" + ] + ).Particles + + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "B_s0 -> ( J/psi(1S) -> [e+]CC [e+]CC ) (phi(1020)-> K+ K-)", + "Jpsi": "B_s0 -> ^( J/psi(1S) -> [e+]CC [e+]CC ) (phi(1020)-> K+ K-)", + "L1": "B_s0 -> ( J/psi(1S) -> ^[e+]CC [e+]CC ) (phi(1020)-> K+ K-)", + "L2": "B_s0 -> ( J/psi(1S) -> [e+]CC ^[e+]CC ) (phi(1020)-> K+ K-)", + "Phi": "B_s0 -> ( J/psi(1S) -> [e+]CC [e+]CC ) ^(phi(1020)-> K+ K-)", + "K1": "B_s0 -> ( J/psi(1S) -> [e+]CC [e+]CC ) (phi(1020)-> ^K+ K-)", + "K2": "B_s0 -> ( J/psi(1S) -> [e+]CC [e+]CC ) (phi(1020)-> K+ ^K-)", + } + + Constraints_Dict = { + "DTF" : { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi" : { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S": { "substitutions": [ "B_s0 -> J/psi(1S){{psi(2S)}} (phi(1020) -> K+ K-)"] , "mass_constraints": ["psi(2S)"] }, # does it work? to test + "DTF_HEAD" : { "substitutions": [] , "mass_constraints": ["B_s0"] } + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B_s0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=False) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Phi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "K1": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K2": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +#################################### +# B0 -> K+ K- E+E- Line tupling +#################################### +@bind_string("Hlt2RD_B0ToKpKmEE") +def Hlt2RD_B0ToKpKmEE(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToKpKmEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA_RAW = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # Define the swap + LINE_DATA_SUBST = SubstitutePID( + "Substitue_HEAD_Hlt2RD_B0ToKpKmEE_{hash}", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "B0{{B_s0}} -> (J/psi(1S) -> e+ e-) (phi(1020)-> K+ K-)" + ], + ).Particles + + + K1 = lambda func : F.CHILD(2, F.CHILD(1, func)) + K2 = lambda func : F.CHILD(2, F.CHILD(2, func)) + L1 = lambda func : F.CHILD(1, F.CHILD(1, func)) + L2 = lambda func : F.CHILD(1, F.CHILD(2, func)) + V2_PVS = get_pvs() + + LINE_DATA = ParticleFilter( + Input=LINE_DATA_SUBST, + Cut=F.FILTER(F.require_all( + K1( F.BPVIPCHI2(V2_PVS) >9. ) , + K1( F.PID_K>0.), + K2(F.BPVIPCHI2(V2_PVS) >9. ) , + K2( F.PID_K>0.) ) + )) + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + FIELDS = { + "B": "B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020)-> K+ K-)", + "Jpsi": "B_s0 -> ^(J/psi(1S) -> e+ e-) (phi(1020)-> K+ K-)", + "L1": "B_s0 -> (J/psi(1S) -> ^e+ e-) (phi(1020)-> K+ K-)", + "L2": "B_s0 -> (J/psi(1S) -> e+ ^e-) (phi(1020)-> K+ K-)", + "Phi": "B_s0 -> (J/psi(1S) -> e+ e-) ^(phi(1020)-> K+ K-)", + "K1": "B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020)-> ^K+ K-)", + "K2": "B_s0 -> (J/psi(1S) -> e+ e-) (phi(1020)-> K+ ^K-)", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S": { "substitutions": [ "B_s0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (phi(1020)-> K+ K-)"] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B_s0"] } + } + + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B_s0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=False) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Phi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "K1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K2": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + +################################################################################### +# B0 -> K+ K- Mu+ Mu- Line tupling +################################################################################### +@bind_string("Hlt2RD_B0ToKpKmMuMu") +def Hlt2RD_B0ToKpKmMuMu(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToKpKmMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA_RAW = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + LINE_DATA = SubstitutePID( + "Substitue_HEAD_BsKKE_{hash}", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "B0{{B_s0}} -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ K-)" + ], + ).Particles + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ K-)", + "Jpsi": "B_s0 -> ^(J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ K-)", + "L1": "B_s0 -> (J/psi(1S) -> ^mu+ mu-) (phi(1020)-> K+ K-)", + "L2": "B_s0 -> (J/psi(1S) -> mu+ ^mu-) (phi(1020)-> K+ K-)", + "Phi": "B_s0 -> (J/psi(1S) -> mu+ mu-) ^(phi(1020)-> K+ K-)", + "K1": "B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> ^K+ K-)", + "K2": "B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020)-> K+ ^K-)", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S": { "substitutions": [ "B_s0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (phi(1020)-> K+ K-)"] , "mass_constraints": ["psi(2S)"] }, # does it work? to test + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B_s0"] } + } + + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDimuon_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B_s0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=[ '9.0' ], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + make_basic_variables( + options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH + ) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Phi": ( + variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "K1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K2": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +################################################################################################################################ + + +################################################################################### +# B0 -> K+ Pi- Mu+ Mu- Line tupling +# https://lhcbdoc.web.cern.ch/lhcbdoc/moore/v55r7/_modules/Hlt2Conf/lines/rd/b_to_xll_hlt2.html#B0ToKpPimMuMu_line +################################################################################### +@bind_string("Hlt2RD_B0ToKpPimMuMu") +def Hlt2RD_B0ToKpPimMuMu(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToKpPimMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + + FIELDS = { + "B": "[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC", + "Jpsi": "[B0 -> ^(J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ pi-)]CC", + "L1": "[B0 -> (J/psi(1S) -> ^mu+ mu-) (K*(892)0-> K+ pi-)]CC", + "L2": "[B0 -> (J/psi(1S) -> mu+ ^mu-) (K*(892)0-> K+ pi-)]CC", + "Kst": "[B0 -> (J/psi(1S) -> mu+ mu-) ^(K*(892)0-> K+ pi-)]CC", + "H1": "[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> ^K+ pi-)]CC", + "H2": "[B0 -> (J/psi(1S) -> mu+ mu-) (K*(892)0-> K+ ^pi-)]CC", + } + + + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S":{ "substitutions": [ "[B0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (K*(892)0-> K+ pi-)]CC"] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B0"] } + } + + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDimuon_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": (variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Kst": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "H1": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "H2": ( + variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +################################################################################################################################ + + +################################################################################### +# B0 -> Pi+ Pi- Mu+ Mu- Line tupling +# https://lhcbdoc.web.cern.ch/lhcbdoc/moore/v55r7/_modules/Hlt2Conf/lines/rd/b_to_xll_hlt2.html#B0ToKpPimMuMu_line +################################################################################### +@bind_string("Hlt2RD_B0ToPipPimMuMu") +def Hlt2RD_B0ToPipPimMuMu(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToPipPimMuMu" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "B0 -> (J/psi(1S) -> mu+ mu-) (rho(770)0-> pi+ pi-)", + "Jpsi": "B0 -> ^(J/psi(1S) -> mu+ mu-) (rho(770)0-> pi+ pi-)", + "L1": "B0 -> (J/psi(1S) -> ^mu+ mu-) (rho(770)0-> pi+ pi-)", + "L2": "B0 -> (J/psi(1S) -> mu+ ^mu-) (rho(770)0-> pi+ pi-)", + "rho": "B0 -> (J/psi(1S) -> mu+ mu-) ^(rho(770)0-> pi+ pi-)", + "H1": "B0 -> (J/psi(1S) -> mu+ mu-) (rho(770)0-> ^pi+ pi-)", + "H2": "B0 -> (J/psi(1S) -> mu+ mu-) (rho(770)0-> pi+ ^pi-)", + } + + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S":{ "substitutions": [ "B0 -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (rho(770)0-> pi+ pi-)" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B0"] } + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDimuon_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "rho": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "H1": ( + variables_DTF_results["finalstates"]+ + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "H2": ( + variables_DTF_results["finalstates"]+ + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +################################################################################################################################ + + +@bind_string("Hlt2RD_B0ToPipPimEE") +def Hlt2RD_B0ToPipPimEE(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToPipPimEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "B0 -> (J/psi(1S) -> e+ e-) (rho(770)0-> pi+ pi-)", + "Jpsi": "B0 -> ^(J/psi(1S) -> e+ e-) (rho(770)0-> pi+ pi-)", + "L1": "B0 -> (J/psi(1S) -> ^e+ e-) (rho(770)0-> pi+ pi-)", + "L2": "B0 -> (J/psi(1S) -> e+ ^e-) (rho(770)0-> pi+ pi-)", + "rho": "B0 -> (J/psi(1S) -> e+ e-) ^(rho(770)0-> pi+ pi-)", + "H1": "B0 -> (J/psi(1S) -> e+ e-) (rho(770)0-> ^pi+ pi-)", + "H2": "B0 -> (J/psi(1S) -> e+ e-) (rho(770)0-> pi+ ^pi-)", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S":{ "substitutions": [ "B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (rho(770)0-> pi+ pi-)" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B0"] } + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "rho": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "H1": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH)+ + make_track_variables(options, data=LINE_DATA)), + "H2": ( variables_DTF_results["finalstates"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH)+ + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + ### I AM HERE + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +################################################################################################################################ + + +################################################################################### +# B0 -> K+ K- E+ E- Line tupling +# https://lhcbdoc.web.cern.ch/lhcbdoc/moore/v55r7/_modules/Hlt2Conf/lines/rd/b_to_xll_hlt2.html +################################################################################### +@bind_string("Hlt2RD_B0ToKpPimEE") +def Hlt2RD_B0ToKpPimEE(options:Options, config: Config): + LINE_NAME = "Hlt2RD_B0ToKpPimEE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B": "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC", + "Jpsi": "[B0 -> ^(J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-)]CC", + "L1": "[B0 -> (J/psi(1S) -> ^e+ e-) (K*(892)0-> K+ pi-)]CC", + "L2": "[B0 -> (J/psi(1S) -> e+ ^e-) (K*(892)0-> K+ pi-)]CC", + "Kst": "[B0 -> (J/psi(1S) -> e+ e-) ^(K*(892)0-> K+ pi-)]CC", + "H1": "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> ^K+ pi-)]CC", + "H2": "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ ^pi-)]CC", + } + + Constraints_Dict = { + "DTF": { "substitutions": [] , "mass_constraints": []}, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S":{ "substitutions": [ "[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-)]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B0"] }, + ###### + "DTF_Pi2K": { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{K-}})]CC" ] , "mass_constraints": [] }, + "DTF_Pi2K_Jpsi" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{K-}})]CC" ] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Pi2K_Psi2S": { "substitutions": [ "[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-{{K-}})]CC" ] , "mass_constraints": ["psi(2S)"] }, + ###### + "DTF_K2Pi": { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{pi+}} pi-)]CC" ] , "mass_constraints": [] }, + "DTF_K2Pi_Jpsi" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{pi+}} pi-)]CC" ] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_K2Pi_Psi2S": { "substitutions": [ "[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+{{pi+}} pi-)]CC" ] , "mass_constraints": ["psi(2S)"] }, + ###### + "DTF_K2P": { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{p+}} pi-)]CC" ] , "mass_constraints": [] }, + "DTF_K2P_Jpsi" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+{{p+}} pi-)]CC" ] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_K2P_Psi2S": { "substitutions": [ "[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+{{p+}} pi-)]CC" ] , "mass_constraints": ["psi(2S)"] }, + ###### + "DTF_Pi2P": { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{p~-}})]CC" ] , "mass_constraints": [] }, + "DTF_Pi2P_Jpsi" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+ e-) (K*(892)0-> K+ pi-{{p~-}})]CC" ] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Pi2P_Psi2S": { "substitutions": [ "[B0 -> (J/psi(1S){{psi(2S)}} -> e+ e-) (K*(892)0-> K+ pi-{{p~-}})]CC" ] , "mass_constraints": ["psi(2S)"] }, + ###### + "DTF_EE2PiPi": { "substitutions": [ "[B0 -> (J/psi(1S) -> e+{{pi+}} e-{{pi-}}) (K*(892)0-> K+ pi-)]CC" ] , "mass_constraints": [] }, + "DTF_EE2KK" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+{{K+}} e-{{K-}} ) (K*(892)0-> K+ pi-)]CC" ] , "mass_constraints": [] }, + "DTF_EE2KPi" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+{{K+}} e-{{pi-}}) (K*(892)0-> K+ pi-)]CC" ] , "mass_constraints": [] }, + "DTF_EE2PiK" : { "substitutions": [ "[B0 -> (J/psi(1S) -> e+{{pi+}} e-{{K-}} ) (K*(892)0-> K+ pi-)]CC" ] , "mass_constraints": [] } + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + + VARIABLES = { + "B": (variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDielectron_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDielectron_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + InclDetDielectron_FourBody_MVA(pvs=V2_PVS, intermediateDiHadron=True) + + make_Isolation_variables(options=options, + bhead_label_decay="B0", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": (variables_DTF_results["intermediate"] + + # InclDetDimuon_MVA( pvs = V2_PVS, DiLeptonFromB=False, DiLeptonChildIdx=1) + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "L1": ( + variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( + variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Kst": (variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, ndau=2)), + "H1": ( + variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "H2": ( + variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +################################################################################################################################ + + +################################################################################################################################ +# B+ -> K+ mu+ mu- Line tuplinggit +################################################################################################################################ +def Hlt2RD_BuToHpMuMu_Incl_Bp( options: Options , config: Config, LINE_DATA_RAW : DataHandle , LINE_NAME : str ) : + # tuple 1 from Hlt2RD_BuToHpMuMu_Incl + LINE_DATA_SUBS = SubstitutePID( + f"Subs_SwapKpi_Hlt2RD_BuToHpMuMu_Incl_Bp", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "[ B+ -> ( J/psi(1S) -> mu+ mu-) pi+{{K+}} ]CC", + ], + ).Particles + ### take the kaon from B-> J/Psi K descriptor... + CHILD_HAD = lambda func: F.CHILD(2, func) + V2_PVS = get_pvs() + LINE_DATA = ParticleFilter( + Input=LINE_DATA_SUBS, + Cut=F.FILTER(F.require_all(F.MASS() > 4800 *MeV, + CHILD_HAD( F.MINIPCHI2(V2_PVS) >9. ) , + CHILD_HAD( F.PID_K>-5. )))) + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + FIELDS = { + "B" : f"[B+ -> (J/psi(1S) -> mu+ mu-) K+]CC", + "Jpsi" : f"[B+ -> ^(J/psi(1S) -> mu+ mu-) K+]CC", + "L1" : f"[B+ -> (J/psi(1S) -> ^mu+ mu-) K+]CC", + "L2" : f"[B+ -> (J/psi(1S) -> mu+ ^mu-) K+]CC", + "K" : f"[B+ -> (J/psi(1S) -> mu+ mu-) ^K+]CC", + } + Constraints_Dict = { + "DTF": { "substitutions" : [] , "mass_constraints": []}, + "DTF_K2Pi" : { "substitutions" : ["[B+ -> (J/psi(1S) -> mu+ mu-) K+{{pi+}} ]CC" ] , "mass_constraints" : [] } , + "DTF_KM2MK" : { "substitutions" : ["[B+ -> (J/psi(1S) -> mu+{{K+}} mu-) K+{{mu+}} ]CC" ], "mass_constraints" : [] } , + "DTF_MuMu2KK" :{ "substitutions" : ["[B+ -> (J/psi(1S) -> mu+{{K+}} mu-{{K-}}) K+ ]CC"] , "mass_constraints" : [] } , + "DTF_MuMu2PiPi" : { "substitutions" : ["[B+ -> (J/psi(1S) -> mu+{{pi+}} mu-{{pi-}}) K+ ]CC"] , "mass_constraints" : [] }, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S": { "substitutions": [ "[B+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) K+]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B+"] }, + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + make_Isolation_variables(options=options, + bhead_label_decay="B+", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": ( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "K": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return FunTuple_no_Filter( + options=options, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}_Bp" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + + + +def Hlt2RD_BuToHpMuMu_Incl_Bc( options: Options , config: Config, LINE_DATA_RAW : DataHandle , LINE_NAME : str ) : + # tuple 2 from Hlt2RD_BuToHpMuMu_Incl + # tuple 1 from Hlt2RD_BuToHpMuMu_Incl + LINE_DATA_SUBS = SubstitutePID( + f"Subs_SwapKpi_Hlt2RD_BuToHpMuMu_Incl_Bc", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "[ B+{{B_c+}} -> ( J/psi(1S) -> mu+ mu-) pi+ ]CC", + ], + ).Particles + # cut + CHILD_HAD = lambda func: F.CHILD(2, func) + LINE_DATA = ParticleFilter( + Input=LINE_DATA_SUBS, + Cut=F.FILTER(F.require_all( F.MASS > 5550 *MeV, CHILD_HAD( F.PID_K <5. ) ) + )) + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + FIELDS = { + "B" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) pi+]CC", + "Jpsi" : f"[B_c+ -> ^(J/psi(1S) -> mu+ mu-) pi+]CC", + "L1" : f"[B_c+ -> (J/psi(1S) -> ^mu+ mu-) pi+]CC", + "L2" : f"[B_c+ -> (J/psi(1S) -> mu+ ^mu-) pi+]CC", + "Pi" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) ^pi+]CC" + } + Constraints_Dict = { + "DTF": { "substitutions" : [] , "mass_constraints": []}, + "DTF_Pi2K" : { "substitutions" : ["[B_c+ -> (J/psi(1S) -> mu+ mu-) pi+{{K+}} ]CC" ] , "mass_constraints" : [] } , + "DTF_PiM2MPi" : { "substitutions" : ["[B_c+ -> (J/psi(1S) -> mu+{{pi+}} mu-) pi+{{mu+}} ]CC" ], "mass_constraints" : [] } , + "DTF_MuMu2KK" :{ "substitutions" : ["[B_c+ -> (J/psi(1S) -> mu+{{K+}} mu-{{K-}}) pi+ ]CC"] , "mass_constraints" : [] } , + "DTF_MuMu2PiPi" : { "substitutions" : ["[B_c+ -> (J/psi(1S) -> mu+{{pi+}} mu-{{pi-}}) pi+ ]CC"] , "mass_constraints" : [] }, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Psi2S": { "substitutions": [ "[B_c+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) pi+]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B_c+"] }, + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + make_Isolation_variables(options=options, + bhead_label_decay="B+", + data=LINE_DATA, + line=LINE_NAME, + header_tes='B', + dr2_angle_list=[ '0.15' ], + max_delta_vertex_chi2_cuts=['9.0'], + filter_tree_name=None + ) + ), + "Jpsi": ( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "Pi": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return FunTuple_no_Filter( + options=options, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}_Bc" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + +@bind_string("Hlt2RD_BuToHpMuMu_Incl") +def Hlt2RD_BuToHpMuMu_Incl(options:Options, config: Config): + LINE_NAME = "Hlt2RD_BuToHpMuMu_Incl" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA_RAW = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # TODO: does it work on data? + filter_line = Filter_Of_FunTuple( options, line_name = LINE_NAME) + fun_tuple_no_filter_Bp = Hlt2RD_BuToHpMuMu_Incl_Bp( options, config, LINE_DATA_RAW=LINE_DATA_RAW, LINE_NAME = LINE_NAME) + fun_tuple_no_filter_Bc = Hlt2RD_BuToHpMuMu_Incl_Bc( options, config, LINE_DATA_RAW=LINE_DATA_RAW, LINE_NAME = LINE_NAME) + algs = [ filter_line, fun_tuple_no_filter_Bp, fun_tuple_no_filter_Bc] + return algs + + +##### +# Sample requested by Niladri +#### +@bind_string( "Hlt2RD_BcToHpHpHmMuMu_Inclusive") +def Hlt2RD_BcToHpHpHmMuMu_Inclusive( options : Options,config: Config): + LINE_NAME = "Hlt2RD_BcToHpHpHmMuMu_Inclusive" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA_RAW = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # TODO: does it work on data? + ### take the kaon from B-> J/Psi K descriptor... + + LINE_DATA = SubstitutePID( + "SubstitutePID_Hlt2RD_BcToHpHpHmMuMu_Inclusive{hash}", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "[B+{{B_c+}} -> (J/psi(1S) -> mu- mu+) (K_2(1770)+ -> K+ K+{{pi+}} K-)]CC", + ] + ).Particles + + V2_PVS = get_pvs() + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + FIELDS = { + "B" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "Jpsi" : f"[B_c+ -> ^(J/psi(1S) -> mu+ mu-) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "L1" : f"[B_c+ -> (J/psi(1S) -> ^mu+ mu-) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "L2" : f"[B_c+ -> (J/psi(1S) -> mu+ ^mu-) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "K2_1770" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) ^(K_2(1770)+ -> K+ pi+ K-) ]CC", + "K1" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) (K_2(1770)+ -> ^K+ pi+ K-) ]CC", + "Pi" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) (K_2(1770)+ -> K+ ^pi+ K-) ]CC", + "K2" : f"[B_c+ -> (J/psi(1S) -> mu+ mu-) (K_2(1770)+ -> K+ pi+ ^K-) ]CC" + } + Constraints_Dict = { + "DTF": { "substitutions" : [] , "mass_constraints": []}, + "DTF_withPV": { "substitutions" : [] , "mass_constraints": [], "withPV": True }, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Jpsi_withPV":{ "substitutions": [] , "mass_constraints": ["J/psi(1S)"], "withPV" : True }, + "DTF_Psi2S": { "substitutions": [ "[B_c+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (K_2(1770)+ -> K+ pi+ K-) ]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_Psi2S_withPV":{ "substitutions": [ "[B_c+ -> (J/psi(1S){{psi(2S)}} -> mu+ mu-) (K_2(1770)+ -> K+ pi+ K-) ]CC" ] , "mass_constraints": ["psi(2S)"] , "withPV" : True }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B_c+"] }, + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + # InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + # InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + # make_Isolation_variables(options=options, + # bhead_label_decay="B_c+", + # data=LINE_DATA, + # line=LINE_NAME, + # header_tes='B', + # dr2_angle_list=[ '0.15' ], + # max_delta_vertex_chi2_cuts=['9.0'], + # filter_tree_name=None + # ) + ), + "Jpsi": ( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "K2_1770" :( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=3)), + "K1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Pi": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +#### +# Sample requested by Niladri +#### +@bind_string("Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign") +def Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign( options : Options,config: Config): + LINE_NAME = "Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA_RAW = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA_RAW = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # TODO: does it work on data? + ### take the kaon from B-> J/Psi K descriptor... + + LINE_DATA = SubstitutePID( + "Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign{hash}", # name of the algorithm + LINE_DATA_RAW, # input particle container + substitutions=[ + "[B+{{B_c+}} -> J/psi(1S) (K_2(1770)+ -> K+ K+{{pi+}} K-)]CC", + ] + ).Particles + + V2_PVS = get_pvs() + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + FIELDS = { + "B" : f"[B_c+ -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "Jpsi" : f"[B_c+ -> ^(J/psi(1S) -> [mu+]CC [mu+]CC ) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "L1" : f"[B_c+ -> (J/psi(1S) -> ^[mu+]CC [mu+]CC ) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "L2" : f"[B_c+ -> (J/psi(1S) -> [mu+]CC ^[mu+]CC ) (K_2(1770)+ -> K+ pi+ K-) ]CC", + "K2_1770" : f"[B_c+ -> (J/psi(1S) -> [mu+]CC [mu+]CC ) ^(K_2(1770)+ -> K+ pi+ K-) ]CC", + "K1" : f"[B_c+ -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (K_2(1770)+ -> ^K+ pi+ K-) ]CC", + "Pi" : f"[B_c+ -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (K_2(1770)+ -> K+ ^pi+ K-) ]CC", + "K2" : f"[B_c+ -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (K_2(1770)+ -> K+ pi+ ^K-) ]CC" + } + Constraints_Dict = { + "DTF": { "substitutions" : [] , "mass_constraints": []}, + "DTF_withPV": { "substitutions" : [] , "mass_constraints": [], "withPV": True }, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Jpsi_withPV":{ "substitutions": [] , "mass_constraints": ["J/psi(1S)"], "withPV" : True }, + "DTF_Psi2S": { "substitutions": [ "[B_c+ -> J/psi(1S){{psi(2S)}} (K_2(1770)+ -> K+ pi+ K-) ]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_Psi2S_withPV":{ "substitutions": [ "[B_c+ -> J/psi(1S){{psi(2S)}} (K_2(1770)+ -> K+ pi+ K-) ]CC" ] , "mass_constraints": ["psi(2S)"] , "withPV" : True }, + "DTF_HEAD": { "substitutions": [] , "mass_constraints": ["B_c+"] }, + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + # InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + # InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + # make_Isolation_variables(options=options, + # bhead_label_decay="B_c+", + # data=LINE_DATA, + # line=LINE_NAME, + # header_tes='B', + # dr2_angle_list=[ '0.15' ], + # max_delta_vertex_chi2_cuts=['9.0'], + # filter_tree_name=None + # ) + ), + "Jpsi": ( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "K2_1770" :( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=3)), + "K1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "K2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Pi": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + +@bind_string("Hlt2RD_BuToL0PmMuMu_LL") +def Hlt2RD_BuToL0PmMuMu_LL( options : Options,config: Config): + LINE_NAME = "Hlt2RD_BuToL0PmMuMu_LL" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # TODO: does it work on data? + ### take the kaon from B-> J/Psi K descriptor... + V2_PVS = get_pvs() + + # LINE_DATA = SubstitutePID( + # "Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign{hash}", # name of the algorithm + # LINE_DATA_RAW, # input particle container + # substitutions=[ + # "[B- -> (J/psi(1S) -> mu+ mu-) (Lambda0 -> p+ pi-) p~- ]CC", + # ] + # ).Particles + + decay = "[B- -> J/psi(1S) Lambda0 p~-]CC" + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + FIELDS = { + "B" : f"[B- -> (J/psi(1S) -> mu+ mu-) (Lambda0 -> p+ pi-) p~- ]CC", + "Jpsi" : f"[B- -> ^(J/psi(1S) -> mu+ mu-) (Lambda0 -> p+ pi-) p~- ]CC", + "L1" : f"[B- -> (J/psi(1S) -> ^mu+ mu-) (Lambda0 -> p+ pi-) p~- ]CC", + "L2" : f"[B- -> (J/psi(1S) -> mu+ ^mu-) (Lambda0 -> p+ pi-) p~- ]CC", + "Lambda" : f"[B- -> (J/psi(1S) -> mu+ mu-) ^(Lambda0 -> p+ pi-) p~- ]CC", + "P" : f"[B- -> (J/psi(1S) -> mu+ mu-) (Lambda0 -> ^p+ pi-) p~- ]CC", + "Pi" : f"[B- -> (J/psi(1S) -> mu+ mu-) (Lambda0 -> p+ ^pi-) p~- ]CC", + "Pbar" : f"[B- -> (J/psi(1S) -> mu+ mu-) (Lambda0 -> p+ pi-) ^p~- ]CC" + } + Constraints_Dict = { + "DTF": { "substitutions" : [] , "mass_constraints": []}, + "DTF_withPV": { "substitutions" : [] , "mass_constraints": [], "withPV": True }, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Jpsi_withPV":{ "substitutions": [] , "mass_constraints": ["J/psi(1S)"], "withPV" : True }, + "DTF_Psi2S": { "substitutions": [ "[B- -> J/psi(1S){{psi(2S)}} (Lambda0 -> p+ pi-) p~- ]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_Psi2S_withPV":{ "substitutions": [ "[B- -> J/psi(1S){{psi(2S)}} (Lambda0 -> p+ pi-) p~- ]CC" ] , "mass_constraints": ["psi(2S)"] , "withPV" : True }, + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=3) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + # InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + # InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + + # make_Isolation_variables(options=options, + # bhead_label_decay="B-", + # data=LINE_DATA, + # line=LINE_NAME, + # header_tes='Bu', + # dr2_angle_list=[ '0.15' ], + # max_delta_vertex_chi2_cuts=['9.0'], + # filter_tree_name=None + # ) + ), + "Jpsi": ( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "L1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Lambda" :( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "P": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Pi": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Pbar": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + +@bind_string("Hlt2RD_BuToL0PmMuMuSS_LL") +def Hlt2RD_BuToL0PmMuMuSS_LL( options : Options,config: Config): + LINE_NAME = "Hlt2RD_BuToL0PmMuMuSS_LL" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + else: raise ValueError("something weird going on") + # TODO: does it work on data? + ### take the kaon from B-> J/Psi K descriptor... + V2_PVS = get_pvs() + + # LINE_DATA = SubstitutePID( + # "Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign{hash}", # name of the algorithm + # LINE_DATA_RAW, # input particle container + # substitutions=[ + # "[B- -> (J/psi(1S) -> mu+ mu-) (Lambda0 -> p+ pi-) p~- ]CC", + # ] + # ).Particles + + decay = "[B- -> J/psi(1S) Lambda0 p~-]CC" + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + FIELDS = { + "B" : f"[B- -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (Lambda0 -> p+ pi-) p~- ]CC", + "Jpsi" : f"[B- -> ^(J/psi(1S) -> [mu+]CC [mu+]CC ) (Lambda0 -> p+ pi-) p~- ]CC", + "L1" : f"[B- -> (J/psi(1S) -> ^[mu+]CC [mu+]CC ) (Lambda0 -> p+ pi-) p~- ]CC", + "L2" : f"[B- -> (J/psi(1S) -> [mu+]CC ^[mu+]CC ) (Lambda0 -> p+ pi-) p~- ]CC", + "Lambda" : f"[B- -> (J/psi(1S) -> [mu+]CC [mu+]CC ) ^(Lambda0 -> p+ pi-) p~- ]CC", + "P" : f"[B- -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (Lambda0 -> ^p+ pi-) p~- ]CC", + "Pi" : f"[B- -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (Lambda0 -> p+ ^pi-) p~- ]CC", + "Pbar" : f"[B- -> (J/psi(1S) -> [mu+]CC [mu+]CC ) (Lambda0 -> p+ pi-) ^p~- ]CC" + } + Constraints_Dict = { + "DTF": { "substitutions" : [] , "mass_constraints": []}, + "DTF_withPV": { "substitutions" : [] , "mass_constraints": [], "withPV": True }, + "DTF_Jpsi": { "substitutions": [] , "mass_constraints": ["J/psi(1S)"] }, + "DTF_Jpsi_withPV":{ "substitutions": [] , "mass_constraints": ["J/psi(1S)"], "withPV" : True }, + "DTF_Psi2S": { "substitutions": [ "[B- -> J/psi(1S){{psi(2S)}} (Lambda0 -> p+ pi-) p~- ]CC" ] , "mass_constraints": ["psi(2S)"] }, + "DTF_Psi2S_withPV":{ "substitutions": [ "[B- -> J/psi(1S){{psi(2S)}} (Lambda0 -> p+ pi-) p~- ]CC" ] , "mass_constraints": ["psi(2S)"] , "withPV" : True }, + } + variables_DTF_results = make_dtf_variables_v2(options, data=LINE_DATA, v2_pvs=V2_PVS , Constraints_Config=Constraints_Dict) + VARIABLES = { + "B": ( variables_DTF_results["mother"] + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=3) + + make_composite_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + # InclDetDimuon_MVA(pvs=V2_PVS, DiLeptonFromB=True, DiLeptonChildIdx=1) + + # InclDetDimuon_ThreeBody_MVA(pvs=V2_PVS, intermediateDiHadron=False) + # make_Isolation_variables(options=options, + # bhead_label_decay="B-", + # data=LINE_DATA, + # line=LINE_NAME, + # header_tes='Bu', + # dr2_angle_list=[ '0.15' ], + # max_delta_vertex_chi2_cuts=['9.0'], + # filter_tree_name=None + # ) + ), + "Jpsi": ( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "L1": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "L2": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_mu, angle_list=['1.0','0.5','0.01'], filter_tree_name='mu+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Lambda" :( variables_DTF_results["intermediate"] + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_intermediate_resonances_variables(options, data=LINE_DATA, v2_pvs=V2_PVS , ndau=2)), + "P": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Pi": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + "Pbar": ( variables_DTF_results["finalstates"] + + # make_ConeIsolation_variables(options, data, line_name, location_list_K, angle_list=['1.0','0.5','0.01'], filter_tree_name='K+') + + make_basic_variables(options, data=LINE_DATA, v2_pvs=V2_PVS, simulation=config.isMC(), MCTRUTH=MCTRUTH) + + make_track_variables(options, data=LINE_DATA)), + # "ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + # FINE OR CRASH + assert(sorted(VARIABLES.keys()) == sorted(FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options=options, + line_name=LINE_NAME, + fields=FIELDS, + variables=VARIABLES, + inputs=LINE_DATA, + name=f"{LINE_NAME}" , + tuple_name="DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) +######################################################################### +TUPLES_ALG_BINDING = {} +# Create a copy of the globals dictionary +globals_copy = dict(globals()) +# Iterate over the copy to avoid modifying the globals dictionary +for name, obj in globals_copy.items(): + if callable(obj) and hasattr(obj, 'name'): + if obj.name not in TUPLES_ALG_BINDING: + TUPLES_ALG_BINDING[obj.name] = obj + +for name, alg in TUPLES_ALG_BINDING.items(): + logger.debug(f"{name} can be bound to its own function, all the rest no. Bounded to {alg}") +######################################################################### diff --git a/rd_ap_2024/tupling/hlt2/b_to_xll_mva.py b/rd_ap_2024/tupling/hlt2/b_to_xll_mva.py new file mode 100644 index 0000000000000000000000000000000000000000..b72337a04c2ed3d17b5e487021f9f5569cb02572 --- /dev/null +++ b/rd_ap_2024/tupling/hlt2/b_to_xll_mva.py @@ -0,0 +1,749 @@ +''' +Module with code needed to ntuple b_to_xll MVA turbo lines: + +Hlt2RD_BuToKpEE_MVA +Hlt2RD_BuToKpEE_MVA_cal +Hlt2RD_BuToKpEE_MVA_misid +Hlt2RD_B0ToKpPimMuMu +Hlt2RD_B0ToKpPimMuMu_MVA +Hlt2RD_BuToKpMuMu +Hlt2RD_BuToKpMuMu_MVA +Hlt2RD_LbTopKMuMu_MVA +Hlt2RD_LbTopKEE_MVA +Hlt2RD_LbTopKEE_MVA_misid +Hlt2RD_BsToPhiMuMu_MVA +Hlt2RD_BsToPhiEE_MVA +Hlt2RD_BsToPhiEE_MVA_misid +Hlt2RD_B0ToKpPimEE +Hlt2RD_B0ToKpPimEE_MVA +Hlt2RD_B0ToKpPimEE_MVA_cal +Hlt2RD_B0ToKpPimEE_MVA_misid +''' + +from dataclasses import dataclass +from typing import Union, Callable +from functools import partial + +import os +import pprint +import yaml + +from PyConf.reading import get_particles, get_pvs +from DaVinci import Options +from DaVinciMCTools import MCTruthAndBkgCat + +from rd_ap_2024.tupling.variables.rd_stream_tupling_functions import ( + make_composite_variables, + make_basic_variables, + make_hlt_event_variables, + make_track_variables, + Funtuple_with_filter, + make_intermediate_resonances_variables, +) + +from rd_ap_2024.tupling.mc.v55r11p5.offline_builders import get_bdkstarmm_candidates +from rd_ap_2024.tupling.mc.v55r11p5.offline_builders import get_bdkstaree_candidates +from rd_ap_2024.tupling.mc.v55r11p5.offline_builders import get_bukpmm_candidates +from rd_ap_2024.tupling.mc.v55r11p5.offline_builders import get_bukpee_candidates + +from rd_ap_2024.tupling.variables.tupling_dtf import make_dtf_variables_v2 as make_dtf_variables +from rd_ap_2024.tupling.variables.rd_stream_isolation_functions import make_Isolation_variables +from rd_ap_2024.utils.log_store import LogStore + +log=LogStore.add_logger('rd_ap_2024:b_to_xll_mva') +#--------------------------------------------------------------------------------- +@dataclass +class Data: + ''' + Class used to store shared data + ''' + cfg : dict + l_custom_lines : list[partial] +#--------------------------------------------------------------------------------- +def bind_string(function_name : str): + ''' + Used to bind string to function + ''' + def wrapper(func): + func.name = function_name + return func + + return wrapper +#--------------------------------------------------------------------------------- +def _get_data(line_name : str, custom_name : Union[str,None]): + ''' + Will take name of Hlt2 line and name of custom line + Will return container with candidates + ''' + if custom_name is None: + return _get_data_from_line(line_name) + + return _get_data_from_builders(line_name, custom_name) +#--------------------------------------------------------------------------------- +def _get_data_from_line(line_name : str): + ''' + Return candidates out of HLT turbo line + ''' + line_path = f'/Event/HLT2/{line_name}/Particles' + line_data = get_particles(line_path) + + return line_data +#--------------------------------------------------------------------------------- +def _get_data_from_builders(line_name : str, custom_name : str): + ''' + Return candidates built using Moore code + ''' + if line_name in ['Hlt2RD_B0ToKpPimMuMu_MVA']: + return get_bdkstarmm_candidates(line_name, custom_name, Data.cfg) + + if line_name in ['Hlt2RD_B0ToKpPimEE_MVA']: + return get_bdkstaree_candidates(line_name, custom_name, Data.cfg) + + if line_name in ['Hlt2RD_BuToKpMuMu_MVA']: + return get_bukpmm_candidates(line_name, custom_name, Data.cfg) + + if line_name in ['Hlt2RD_BuToKpEE_MVA']: + return get_bukpee_candidates(line_name, custom_name, Data.cfg) + + raise NotImplementedError(f'No candidate builder implemented for line: {line_name}') +#--------------------------------------------------------------------------------- +def _run_check(d_var : dict, line_name : str) -> None: + ''' + Checks that dictionary of variables contains the same keys + as dictionary of fields, i.e. same particles in both places + ''' + fields = Data.cfg[line_name]['fields'] + + l_vark = d_var.keys() + l_filk = fields.keys() + + l_varv = d_var.values() + l_filv = fields.values() + + nvarv = len(l_varv) + nfilv = len(l_filv) + + fail_1 = sorted(l_vark) != sorted(l_filk) + fail_2 = nvarv != nfilv + + if fail_1 or fail_2: + log.warning('Fields:') + pprint.pprint(fields.keys()) + log.warning('Variables:') + pprint.pprint(d_var.keys()) + raise RuntimeError(f'Variables-Fields values check failed for line: {line_name}') +#--------------------------------------------------------------------------------- +def _get_b_vars( + cfg = None, + opt = None, + mc_truth = None, + line_data = None, + line_name:Union[str,None] = None): + + head = Data.cfg[line_name]['head'] + header_tes = Data.cfg['isolation']['header'][line_name] + l_angle = Data.cfg['isolation']['angles'] + l_dchi2 = Data.cfg['isolation']['max_delta_chi2'] + + l_pv = get_pvs() + int_vars = make_intermediate_resonances_variables(opt, data = line_data, v2_pvs= l_pv , ndau=2) + cmp_vars = make_composite_variables(opt, data=line_data, v2_pvs= l_pv, simulation=cfg.isMC(), MCTRUTH=mc_truth) + iso_vars = make_Isolation_variables( + data = line_data, + line = line_name, + options = opt, + header_tes = header_tes, + dr2_angle_list = l_angle, + filter_tree_name = None, + bhead_label_decay = head, + max_delta_vertex_chi2_cuts = l_dchi2) + + b_vars = int_vars + cmp_vars + iso_vars + + return b_vars +#--------------------------------------------------------------------------------- +def _get_dtf_vars( + opt : Options = None, + line_data = None, + line_name: Union[str,None]= None): + + l_pv = get_pvs() + d_dtf = Data.cfg[line_name]['substitutions'] + dtf_vars = make_dtf_variables(options = opt, + data = line_data, + v2_pvs = l_pv, + Constraints_Config= d_dtf) + + return dtf_vars +#--------------------------------------------------------------------------------- +# B+ -> K+ Mu+ Mu- +#--------------------------------------------------------------------------------- +def bukmm_alg(options:Options, config, line_name : str, custom_name : Union[str,None] = None): + ''' + Build FunTuple from line names and config, returns FunTuple + ''' + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + l_pv = get_pvs() + + dtf_vars = _get_dtf_vars( + opt = options, + line_data = line_data, + line_name = line_name) + + b_vars = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + d_var = { + "B" : dtf_vars['mother'] + b_vars, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv, ndau=2)), + "L1" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "K" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + } + + _run_check(d_var, line_name) + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_BuToKpMuMu_MVA") +def Hlt2RD_BuToKpMuMu_MVA(options:Options, config) : + return bukmm_alg(options, config, 'Hlt2RD_BuToKpMuMu_MVA') + +@bind_string("Hlt2RD_BuToKpMuMu_SameSign_MVA") +def Hlt2RD_BuToKpMuMu_SameSign_MVA(options:Options, config) : + return bukmm_alg(options, config, 'Hlt2RD_BuToKpMuMu_SameSign_MVA') +#--------------------------------------------------------------------------------- +# B+ -> K+ E+E- +#--------------------------------------------------------------------------------- +def bukee_alg(options:Options, config, line_name : str, custom_name : Union[str,None] = None) : + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_vars = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + l_pv = get_pvs() + d_var = { + "B" : dtf_vars['mother'] + b_vars, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv, ndau=2)), + "K" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L1" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + } + + _run_check(d_var, line_name) + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_BuToKpEE_MVA") +def Hlt2RD_BuToKpEE_MVA(options:Options, config) : + return bukee_alg(options, config, 'Hlt2RD_BuToKpEE_MVA') + +@bind_string("Hlt2RD_BuToKpEE_MVA_cal") +def Hlt2RD_BuToKpEE_MVA_cal(options:Options, config) : + return bukee_alg(options, config, 'Hlt2RD_BuToKpEE_MVA_cal') + +@bind_string("Hlt2RD_BuToKpEE_MVA_misid") +def Hlt2RD_BuToKpEE_MVA_misid(options:Options, config) : + return bukee_alg(options, config, 'Hlt2RD_BuToKpEE_MVA_misid') + +@bind_string("Hlt2RD_BuToKpEE_SameSign_MVA") +def Hlt2RD_BuToKpEE_SameSign_MVA(options:Options, config) : + return bukee_alg(options, config, 'Hlt2RD_BuToKpEE_SameSign_MVA') +#--------------------------------------------------------------------------------- +# B0 -> K+ Pi- Mu+ Mu- +#--------------------------------------------------------------------------------- +def bdkstmm_alg(options:Options, config, line_name : [str,None] = None, custom_name : Union[str,None] = None) : + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_var = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + l_pv = get_pvs() + d_var = { + "B" : dtf_vars['mother'] + b_var, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv, ndau=2)), + "Kst" : ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv, ndau=2)), + "L1": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H1": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H2": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + } + + _run_check(d_var, line_name) + + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp +#--------------------------------------------------------------------------------- +@bind_string("Hlt2RD_B0ToKpPimMuMu_MVA") +def Hlt2RD_B0ToKpPimMuMu_MVA(options:Options, config) : + return bdkstmm_alg(options, config, 'Hlt2RD_B0ToKpPimMuMu_MVA') + +@bind_string("Hlt2RD_B0ToKpPimMuMu_SameSign_MVA") +def Hlt2RD_B0ToKpPimMuMu_SameSign_MVA(options:Options, config) : + return bdkstmm_alg(options, config, 'Hlt2RD_B0ToKpPimMuMu_SameSign_MVA') +#--------------------------------------------------------------------------------- +# B0 -> K+ Pi- E+ E- +#--------------------------------------------------------------------------------- +def bdkstee_alg(options:Options, config, line_name : str, custom_name : Union[str,None] = None) : + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + l_pv = get_pvs() + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_var = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + d_var = { + "B" : dtf_vars['mother'] + b_var, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv, ndau=2)), + "Kst" : ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv, ndau=2)), + "L1" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H1": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H2": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + } + + _run_check(d_var, line_name) + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_B0ToKpPimEE_MVA") +def Hlt2RD_B0ToKpPimEE_MVA(options:Options, config) : + return bdkstee_alg(options, config, 'Hlt2RD_B0ToKpPimEE_MVA') + +@bind_string("Hlt2RD_B0ToKpPimEE_MVA_cal") +def Hlt2RD_B0ToKpPimEE_MVA_cal(options:Options, config) : + return bdkstee_alg(options, config, 'Hlt2RD_B0ToKpPimEE_MVA_cal') + +@bind_string("Hlt2RD_B0ToKpPimEE_MVA_misid") +def Hlt2RD_B0ToKpPimEE_MVA_misid(options:Options, config) : + return bdkstee_alg(options, config, 'Hlt2RD_B0ToKpPimEE_MVA_misid') + +@bind_string("Hlt2RD_B0ToKpPimEE_SameSign_MVA") +def Hlt2RD_B0ToKpPimEE_SameSign_MVA(options:Options, config) : + return bdkstee_alg(options, config, 'Hlt2RD_B0ToKpPimEE_SameSign_MVA') +#--------------------------------------------------------------------------------- +# Lb -> PK MU MU +#--------------------------------------------------------------------------------- +def lbpkmm_alg(options:Options, config, line_name :str, custom_name : Union[str,None] = None): + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + l_pv = get_pvs() + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_var = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + d_var = { + "Lb" : dtf_vars['mother'] + b_var, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "Lz": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "L1": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "P": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "K": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data) ), + } + + _run_check(d_var, line_name) + + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_LbTopKMuMu_MVA") +def Hlt2RD_LbTopKMuMu_MVA(options:Options, config) : + return lbpkmm_alg(options, config, 'Hlt2RD_LbTopKMuMu_MVA') + +@bind_string("Hlt2RD_LbTopKMuMu_SameSign_MVA") +def Hlt2RD_LbTopKMuMu_SameSign_MVA(options:Options, config) : + return lbpkmm_alg(options, config, 'Hlt2RD_LbTopKMuMu_SameSign_MVA') +#--------------------------------------------------------------------------------- +# Lb -> PK EE +#--------------------------------------------------------------------------------- +def lbpkee_alg(options:Options, config, line_name : str, custom_name : Union[str,None]=None): + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + l_pv = get_pvs() + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_var = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data= line_data, + line_name= line_name) + + d_var = { + "Lb" : dtf_vars['mother'] + b_var, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data =line_data, v2_pvs=l_pv , simulation=config.isMC() )+ + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "Lz" : ( + dtf_vars['intermediate'] + + make_basic_variables(options, data =line_data, v2_pvs=l_pv , simulation=config.isMC() ) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "L1": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC() ) + + make_track_variables(options, data=line_data)), + "L2": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC() ) + + make_track_variables(options, data=line_data)), + "P": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC() ) + + make_track_variables(options, data=line_data)), + "K": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC() ) + + make_track_variables(options, data=line_data) ), + } + + _run_check(d_var, line_name) + + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_LbTopKEE_MVA") +def Hlt2RD_LbTopKEE_MVA(options:Options, config) : + return lbpkee_alg(options, config, 'Hlt2RD_LbTopKEE_MVA') + +@bind_string("Hlt2RD_LbTopKEE_MVA_misid") +def Hlt2RD_LbTopKEE_MVA_misid(options:Options, config) : + return lbpkee_alg(options, config, 'Hlt2RD_LbTopKEE_MVA_misid') + +@bind_string("Hlt2RD_LbTopKEE_SameSign_MVA") +def Hlt2RD_LbTopKEE_SameSign_MVA(options:Options, config) : + return lbpkee_alg(options, config, 'Hlt2RD_LbTopKEE_SameSign_MVA') +#--------------------------------------------------------------------------------- +# Bs -> Phi Mu Mu +#--------------------------------------------------------------------------------- +def bsphmm_alg(options:Options, config, line_name :str, custom_name : Union[str,None]=None): + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_var = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + l_pv = get_pvs() + d_var = { + "B" : dtf_vars['mother'] + b_var, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "Phi" : ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "L1" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H1" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H2" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + } + + _run_check(d_var, line_name) + + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_BsToPhiMuMu_MVA") +def Hlt2RD_BsToPhiMuMu_MVA(options:Options, config) : + return bsphmm_alg(options, config, 'Hlt2RD_BsToPhiMuMu_MVA') + +@bind_string("Hlt2RD_BsToPhiMuMu_SameSign_MVA") +def Hlt2RD_BsToPhiMuMu_SameSign_MVA(options:Options, config) : + return bsphmm_alg(options, config, 'Hlt2RD_BsToPhiMuMu_SameSign_MVA') +#--------------------------------------------------------------------------------- +# Bs -> Phi EE +#--------------------------------------------------------------------------------- +def bsphee_alg(options:Options, config, line_name : str, custom_name : Union[str,None]=None) : + ''' + Will return FunTuple according to configuration and for a given HLT2 line + ''' + line_data = _get_data(line_name, custom_name) + mc_truth = MCTruthAndBkgCat(line_data, name="MCTruthAndBkgCat_{hash}") + l_pv = get_pvs() + + dtf_vars = _get_dtf_vars( + opt = options, + line_data= line_data, + line_name= line_name) + + b_var = _get_b_vars( + cfg = config, + opt = options, + mc_truth = mc_truth, + line_data = line_data, + line_name = line_name) + + d_var = { + "B" : dtf_vars['mother'] + b_var, + "Jpsi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "Phi": ( + dtf_vars['intermediate'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_intermediate_resonances_variables(options, data = line_data, v2_pvs= l_pv , ndau=2)), + "L1" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "L2" : ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H1": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + "H2": ( + dtf_vars['finalstates'] + + make_basic_variables(options, data=line_data, v2_pvs=l_pv, simulation=config.isMC(), MCTRUTH=mc_truth) + + make_track_variables(options, data=line_data)), + } + + _run_check(d_var, line_name) + ftp = _get_fun_tuple(options, line_name, custom_name, d_var, line_data) + + return ftp + +@bind_string("Hlt2RD_BsToPhiEE_MVA") +def Hlt2RD_BsToPhiEE_MVA(options:Options, config): + return bsphee_alg(options, config, 'Hlt2RD_BsToPhiEE_MVA') + +@bind_string("Hlt2RD_BsToPhiEE_MVA_misid") +def Hlt2RD_BsToPhiEE_MVA_misid(options:Options, config): + return bsphee_alg(options, config, 'Hlt2RD_BsToPhiEE_MVA_misid') + +@bind_string("Hlt2RD_BsToPhiEE_SameSign_MVA") +def Hlt2RD_BsToPhiEE_SameSign_MVA(options:Options, config): + return bsphee_alg(options, config, 'Hlt2RD_BsToPhiEE_SameSign_MVA') +#--------------------------------------------------------------------------------- +def _get_fun_tuple(options : Options, line_name : str, custom_name : Union[str,None], d_var : dict, line_data): + out_name = line_name if custom_name is None else custom_name + + ftp = Funtuple_with_filter( + options = options, + line_name = line_name if custom_name is None else None, + fields = Data.cfg[line_name]['fields'], + variables = d_var, + inputs = line_data, + name = out_name, + tuple_name = "DecayTree", + event_variables= make_hlt_event_variables(options, line_name), + ) + + return ftp +#--------------------------------------------------------------------------------- +def _get_custom_line(fun : Callable, line_name : str, custom_name : str) -> partial: + pfun = partial(fun, line_name=line_name, custom_name=custom_name) + pfun.name = custom_name + + return pfun +#--------------------------------------------------------------------------------- +def _initialize(): + ap_base = os.environ['ANALYSIS_PRODUCTIONS_BASE'] + yaml_path = f'{ap_base}/rd_ap_2024/tupling/config/b_to_xll_mva.yaml' + with open(yaml_path, encoding='utf-8') as ifile: + Data.cfg = yaml.safe_load(ifile) + + Data.l_custom_lines = [] + Data.l_custom_lines += [ _get_custom_line(bukee_alg , 'Hlt2RD_BuToKpEE_MVA' , custom_name) for custom_name in Data.cfg['Hlt2RD_BuToKpEE_MVA' ]['custom']] + Data.l_custom_lines += [ _get_custom_line(bdkstee_alg, 'Hlt2RD_B0ToKpPimEE_MVA' , custom_name) for custom_name in Data.cfg['Hlt2RD_B0ToKpPimEE_MVA']['custom']] + + Data.l_custom_lines += [ _get_custom_line(bukmm_alg , 'Hlt2RD_BuToKpMuMu_MVA' , custom_name) for custom_name in Data.cfg['Hlt2RD_BuToKpMuMu_MVA' ]['custom']] + Data.l_custom_lines += [ _get_custom_line(bdkstmm_alg, 'Hlt2RD_B0ToKpPimMuMu_MVA', custom_name) for custom_name in Data.cfg['Hlt2RD_B0ToKpPimMuMu_MVA']['custom']] +#--------------------------------------------------------------------------------- +def _get_bound_lines() -> dict[str, Callable]: + globals_copy = dict(globals()) + l_glob = list(globals_copy.values()) + + d_hlt = {} + + log.info('Found default lines:') + d_hlt_def = _lines_from_list(l_glob ) + + log.info('Found custom lines:') + d_hlt_cus = _lines_from_list(Data.l_custom_lines) + + d_hlt.update(d_hlt_def) + d_hlt.update(d_hlt_cus) + + return d_hlt +#--------------------------------------------------------------------------------- +def _lines_from_list(l_line : list) -> dict: + d_hlt = {} + for obj in l_line: + if callable(obj) and hasattr(obj, 'name'): + name = obj.name + if name not in d_hlt: + log.info(f'{"":<4}{name}') + d_hlt[name] = obj + + return d_hlt +#--------------------------------------------------------------------------------- +def _print_lines(d_hlt : dict[str,Callable]) -> None: + log.info(110 * '-') + log.info(f'{"Line":<50}{"":<10}{"Function":<50}') + log.info(110 * '-') + for name, function in d_hlt.items(): + log.info(f'{name:<50}{"->":<10}{str(function):<50}') +#--------------------------------------------------------------------------------- +_initialize() +TUPLES_ALG_BINDING = _get_bound_lines() +_print_lines(TUPLES_ALG_BINDING) diff --git a/rd_ap_2024/tupling/main.py b/rd_ap_2024/tupling/main.py new file mode 100644 index 0000000000000000000000000000000000000000..dee7e432bd8a860bc4fd101bb77f517257d2af67 --- /dev/null +++ b/rd_ap_2024/tupling/main.py @@ -0,0 +1,265 @@ +''' +Script used as entry point for MC production +''' + +import os + +from DaVinci import make_config, Options + +from rd_ap_2024.tupling.Config import Config , get_all_binds_tupling_algs +from rd_ap_2024.tupling.Config import KNOWN_EVENT_TYPES_CONFIG_TO_LINES +from rd_ap_2024.tupling.MCDecayTree import SAMPLE_MCDECAYTREEALG +from rd_ap_2024.utils.log_store import LogStore + +log=LogStore.add_logger('rd_ap_2024:main') +# ------------------------------------------------------ +# import tupling functions to make basics variables for head, composite , intermediate, some more advanced and specific to share among analyses +# ------------------------------------------------------ +def get_known_lines(): + from rd_ap_2024.tupling.Config import _known_event_types_config_lines_ as mapped_event_types_to_config_lines + return mapped_event_types_to_config_lines +# ------------------------------------------------------ +# MCDecayTupling +# ------------------------------------------------------ +def _get_lines(config : Config, sample_id : str) -> dict[str, set[str]]: + if not config.isTurbo(): + raise NotImplementedError('Non Turbo line is not implemented') + + if config.isData(): + log.info("Picking up lines for data") + return { + "Data" : { + "Hlt2RD_B0ToKpKmEE", + "Hlt2RD_B0ToKpKmEE_SameSign", + "Hlt2RD_B0ToKpKmMuMu", + "Hlt2RD_B0ToKpPimEE", + "Hlt2RD_B0ToKpPimMuMu", + "Hlt2RD_B0ToPipPimEE", + "Hlt2RD_B0ToPipPimMuMu", + "Hlt2RD_BToEE", + "Hlt2RD_BToEE_SameSign", + "Hlt2RD_BToHH_Incl", + "Hlt2RD_BToMuE", + "Hlt2RD_BToMuE_SameSign", + "Hlt2RD_BToMuMu", + "Hlt2RD_BToMuMu_SameSign", + "Hlt2RD_BdToKSEE_DD", + "Hlt2RD_BdToKSEE_LL", + "Hlt2RD_BdToKSMuMu_DD", + "Hlt2RD_BdToKSMuMu_LL", + # "Hlt2RD_BdToKstGamma", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEE", + "Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMu", + "Hlt2RD_BsToPhiEMu_PhiToKK", + "Hlt2RD_BsToPhiEMu_SameSign_PhiToKK", + # "Hlt2RD_BsToPhiGamma", + "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToEE", + "Hlt2RD_BsToPhiJpsi_PhiToKK_JpsiToMuMu", + "Hlt2RD_BuToHpMuMu_Incl", + "Hlt2RD_BuToKSPipEE_DD", + "Hlt2RD_BuToKSPipEE_LL", + "Hlt2RD_BuToKSPipMuMu_DD", + "Hlt2RD_BuToKSPipMuMu_LL", + "Hlt2RD_BuToKpEE", + "Hlt2RD_BuToKpJpsi_JpsiToEE", + "Hlt2RD_BuToKpJpsi_JpsiToMuMu", + "Hlt2RD_Displaced4Mu_Incl", + "Hlt2RD_DsToPhiPi_PhiToEE", + "Hlt2RD_DsToPhiPi_PhiToMuMu", + "Hlt2RD_JpsiToEE", + "Hlt2RD_KS0ToEE", + "Hlt2RD_KS0ToEEEE_Loose", + "Hlt2RD_KS0ToMuMu", + "Hlt2RD_KS0ToMuMuEE_Loose", + "Hlt2RD_KS0ToMuMuMuMu_Loose", + "Hlt2RD_KS0ToPiMu", + "Hlt2RD_KS0ToPiMu_Loose", + "Hlt2RD_KS0ToPiMu_Tight", + "Hlt2RD_KS0ToPiPi", + "Hlt2RD_KS0ToPiPiEE_Loose", + "Hlt2RD_KS0ToPiPi_Detached", + "Hlt2RD_KS0ToPiPi_Detached_Tight", + "Hlt2RD_KS0ToPiPi_Loose", + "Hlt2RD_KpToPiPiPi", + "Hlt2RD_Lambda0ToPPi", + "Hlt2RD_Lambda0ToPPi_Downstream", + "Hlt2RD_Lambda0ToPPi_Tight", + "Hlt2RD_Lambda0ToPPi_Tight_Downstream", + "Hlt2RD_LambdabToPKEE", + # "Hlt2RD_LambdabToPKEE_SS", # Found issues, not useful, code not working as well for pK same sign in DTF descriptors , see https://gitlab.cern.ch/lhcb/Moore/-/merge_requests/4022 + "Hlt2RD_LambdabToPKMuMu", + # "Hlt2RD_LambdabToPKMuMu_SS", # Found issues, not useful, code not working as well for pK same sign in DTF descriptors , see https://gitlab.cern.ch/lhcb/Moore/-/merge_requests/4022 + "Hlt2RD_LbToLEE_DD", + "Hlt2RD_LbToLEE_LL", + "Hlt2RD_LbToLMuMu_DD", + "Hlt2RD_LbToLMuMu_LL", + "Hlt2RD_LbToPKJpsi_JpsiToEE", + "Hlt2RD_LbToPKJpsi_JpsiToMuMu", + "Hlt2RD_OmegaMinusToLambdaK", + "Hlt2RD_OmegaMinusToLambdaK_Downstream", + "Hlt2RD_OmegaMinusToLambdaK_Long_Down", + "Hlt2RD_OmegaMinusToLambdaPi", + "Hlt2RD_OmegaMinusToLambdaPi_Downstream", + "Hlt2RD_OmegaMinusToLambdaPi_Long_Down", + "Hlt2RD_OmegaMinusToXiMinusPiPi", + "Hlt2RD_OmegabmToOmegamEE_DDD", + "Hlt2RD_OmegabmToOmegamEE_DDL", + "Hlt2RD_OmegabmToOmegamEE_LLL", + "Hlt2RD_OmegabmToOmegamMuMu_DDD", + "Hlt2RD_OmegabmToOmegamMuMu_DDL", + "Hlt2RD_OmegabmToOmegamMuMu_LLL", + "Hlt2RD_OmegabmToXimEE_DDD", + "Hlt2RD_OmegabmToXimEE_DDL", + "Hlt2RD_OmegabmToXimEE_LLL", + "Hlt2RD_OmegabmToXimMuMu_DDD", + "Hlt2RD_OmegabmToXimMuMu_DDL", + "Hlt2RD_OmegabmToXimMuMu_LLL", + "Hlt2RD_OmegamToXimPiPi_LLL", + "Hlt2RD_PhiToEE", + "Hlt2RD_SigmaPlusToPEE", + "Hlt2RD_SigmaPlusToPMuMu", + "Hlt2RD_SigmaPlusToPPi0Merged", + "Hlt2RD_SigmaPlusToPPi0Merged_Tight", + "Hlt2RD_SigmaPlusToPPi0Resolved", + "Hlt2RD_SigmaPlusToPPi0Resolved_Tight", + "Hlt2RD_TauToMuMuMu", + "Hlt2RD_Upsilon2ToUpsilon1PiPi_Upsilon1ToEE", + "Hlt2RD_Upsilon2ToUpsilon1PiPi_Upsilon1ToMuMu", + "Hlt2RD_UpsilonToEE", + "Hlt2RD_UpsilonToMuMu", + "Hlt2RD_UpsilonToTauTau", + "Hlt2RD_Xi0ToPPi_Tight", + "Hlt2RD_Xi0ToPPi_Tight_Downstream", + "Hlt2RD_XiMinusToAntiLambdaPi_Tight", + "Hlt2RD_XiMinusToAntiLambdaPi_Tight_Downstream", + "Hlt2RD_XiMinusToAntiLambdaPi_Tight_Long_Down", + "Hlt2RD_XiMinusToLambdaPi_Tight", + "Hlt2RD_XiMinusToLambdaPi_Tight_Downstream", + "Hlt2RD_XiMinusToLambdaPi_Tight_Long_Down", + "Hlt2RD_XiMinusToPPiPi_Tight", + "Hlt2RD_XiMinusToPPiPi_Tight_Downstream", + "Hlt2RD_XibmToXimEE_DDD", + "Hlt2RD_XibmToXimEE_DDL", + "Hlt2RD_XibmToXimEE_LLL", + "Hlt2RD_XibmToXimMuMu_DDD", + "Hlt2RD_XibmToXimMuMu_DDL", + "Hlt2RD_XibmToXimMuMu_LLL", + "Hlt2_JpsiToMuMu", + "Hlt2_Psi2SToMuMu", + + "Hlt2RD_BcToHpHpHmMuMu_Inclusive", #niladri + "Hlt2RD_BcToHpHpHmMuMu_Inclusive_SameSign", #niladri + "Hlt2RD_BuToL0PmMuMu_LL", #niladri + "Hlt2RD_BuToL0PmMuMuSS_LL" #niladri + } + } + + if config.isMC(): + log.info("Picking up lines for simulation") + d_evt_line : dict[str,set[str]] = KNOWN_EVENT_TYPES_CONFIG_TO_LINES() + if sample_id not in d_evt_line: + raise ValueError(f'Invalid sample: {sample_id}') + + return { sample_id : d_evt_line[sample_id] } + + raise ValueError('Configuration cannot be used to determine if sample is data or MC') +# ------------------------------------------------------ +def _get_user_algorithms( options : Options, config : Config, _SAMPLEID_ :str) -> dict: + if config.MCDTONLY(): + log.debug( + """ + Short circuit code, this is temporary because we run over digi inputs to make MCDT, once the flagging mode in HLT1,HLT2 will be available we can make this + """ + ) + User_Algorithms = {} + if config.SampleNameID() in SAMPLE_MCDECAYTREEALG: + log.info(f""" + Algorithm for {config.SampleNameID()} will be picked for MCDecayTuple making + 'function.name' = {SAMPLE_MCDECAYTREEALG[config.SampleNameID()].sampleID} + will be used + """) + + mcdecaytuple = SAMPLE_MCDECAYTREEALG[config.SampleNameID()] + User_Algorithms.update( {"MCDecayTuple" : [mcdecaytuple( options, config )] }) + else: + log.info("No MCDecayTuple will be made") + + raise ValueError("USELESS JOB FIX THE JOBS") + + for name, alg in User_Algorithms.items(): + log.debug(name, alg) + + return User_Algorithms + + mydict = _get_lines(config, _SAMPLEID_) + + log.debug(mydict) + + if config.etypename not in mydict : + raise RuntimeError(f"{config} , the eventtypename is not present in {mydict.keys()}") + + User_Algorithms = {} + ALL_ALGS_BINDS = get_all_binds_tupling_algs(hlt2_include = True, turcal_include=True, spruce_include=True) + for line_name in mydict[config.etypename]: + log.debug(line_name) + if line_name not in ALL_ALGS_BINDS: + raise ValueError(f'Line {line_name} not found among binds') + + if ALL_ALGS_BINDS[line_name] is None: + raise ValueError(f'Bind for line {line_name} is None') + + log.debug(f""" + Algorithm for {line_name} will be picked + 'function.name' = {ALL_ALGS_BINDS[line_name].name} + will be used + """) + + log.debug(f"adding {line_name}") + + User_Algorithms.update({line_name : ALL_ALGS_BINDS[line_name]( options, config)}) + + if config.isMC() : + if config.SampleNameID() in SAMPLE_MCDECAYTREEALG: + log.info(f""" + Algorithm for {config.SampleNameID()} will be picked for MCDecayTuple making + 'function.name' = {SAMPLE_MCDECAYTREEALG[config.SampleNameID()].sampleID} + will be used + """) + mcdecaytuple = SAMPLE_MCDECAYTREEALG[config.SampleNameID()] + User_Algorithms.update( {"MCDecayTuple" : [mcdecaytuple( options, config)] }) + else: + log.info("NO MCDECAYTREE WILL BE DONE") + + log.info("Found algorithms:") + for line_name, l_value in User_Algorithms.items(): + log.info(line_name) + for value in l_value: + log.info(f'{"":<4}{value}') + + return User_Algorithms +# ------------------------------------------------------ +# Main Runner, called in info.yaml by the entry point with extra Args options +# ------------------------------------------------------ +def Run(options: Options, _SAMPLE_ID_ : str , _STREAM_ :str , ISMC : str , DataPeriod : str = ""): + """Main executable to Run the tupling + Args: + options (Options): baseline options set for DaVinci + _SAMPLE_ID_ (str): it's a unique Identifier of our dataset under processing [has to be mapped in info.yaml and Config.py] + _STREAM_ (str): this is a flag passed for Data Processing as different streams in data maps to different bkk , see info.yaml + ISMC (str): flag passed to the main runner to set if we are runnning on simulation or real data + Returns: + _type_: configuration of DaVinci with all the tupling algorithms to run + """ + os.environ["THOR_JIT_N_SPLITS"] = "4" + if not isinstance(DataPeriod, str): + raise ValueError('DataPeriod argument is not a string') + + if ISMC not in ['True', 'False']: + raise ValueError('ISMC argument is neither True nor False') + + isMC = ISMC == 'True' + + configuration = Config( _SAMPLE_ID_, _STREAM_, isMC, DataPeriod) + config = _get_user_algorithms( options, configuration , _SAMPLE_ID_ ) + + return make_config(options, config) diff --git a/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_builders.py b/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_builders.py new file mode 100644 index 0000000000000000000000000000000000000000..99cc29a680bf0437184d2fe59c9f985965fbd067 --- /dev/null +++ b/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_builders.py @@ -0,0 +1,269 @@ +############################################################################### +# (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +""" +Definition of the b -> X ll builders + +Includes: + + B+ / B0 -> H J/psi(1S) builder for a hadron H + - A general 2 body combiner for making B+ and B0 + + X -> hhh builder combining 3 hadrons + + K*+ -> K+ pi0 builder + + X -> ppbar builder + X -> Lambda0pbar builder + B(s)0 / B- -> Xpbarll builder + + + +Contact: Richard Williams (rmw68@cam.ac.uk) +""" + +### Builders ### +from Functors.math import in_range +from GaudiKernel.SystemOfUnits import MeV +import Functors as F +from Hlt2Conf.algorithms_thor import ParticleCombiner +from PyConf import configurable + + +@configurable +def make_rd_BToXll( + dileptons, + hadrons, + pvs, + Descriptor, + name='rd_BToXll_{hash}', + am_min=4_500. * MeV, + am_max=7_000. * MeV, + B_pt_min=0. * MeV, + bpvipchi2_max=25., + min_cosine=0.9995, + FDchi2_min=100., + vchi2pdof_max=9., + low_factor=0.5, + high_factor=1.5, +): + + ### Make the Bu or Bs -> hadron l+ l- candidate ### + + combination_code = F.require_all( + in_range(low_factor * am_min, F.MASS, high_factor * am_max), + F.SUM(F.PT) > B_pt_min, + ) + + vertex_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.BPVIPCHI2(pvs) < bpvipchi2_max, + F.BPVDIRA(pvs) > min_cosine, + F.BPVFDCHI2(pvs) > FDchi2_min, + F.CHI2DOF < vchi2pdof_max, + ) + + return ParticleCombiner( + [dileptons, hadrons], + DecayDescriptor=Descriptor, + CombinationCut=combination_code, + name=name, + CompositeCut=vertex_code, + ) + + +def make_rd_XTohhh( + hadron_1, + hadron_2, + hadron_3, + Descriptor, + name='rd_XTohhh_{hash}', + am_min=500. * MeV, + am_max=4200. * MeV, + adocachi2cut=25., + vchi2pdof_max=9., + X_pt_min=500. * MeV, +): + + two_body_combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.MAXSDOCACHI2CUT(adocachi2cut)) + + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2cut), Indices=[2, 3]), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2cut), Indices=[1, 3]), + ) + + vertex_code = F.require_all( + F.PT > X_pt_min, + F.CHI2DOF < vchi2pdof_max, + ) + + return ParticleCombiner([hadron_1, hadron_2, hadron_3], + name=name, + DecayDescriptor=Descriptor, + Combination12Cut=two_body_combination_code, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +def make_rd_KstToKpPi( + kaons, + pions, + Decay_Descriptor="[K*(892)+ -> K+ pi0]cc", + pt_min=400. * MeV, + am_min=600. * MeV, + am_max=1200. * MeV, + adocachi2cut=30., + vchi2pdof_max=9., +): + + ### Make K* -> K+ pi0 candidate ### + + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.SUM(F.PT) > pt_min, + F.MAXSDOCACHI2CUT(adocachi2cut), + ) + + return ParticleCombiner([kaons, pions], + DecayDescriptor=Decay_Descriptor, + CombinationCut=combination_code, + name='My_K_star_plus Maker_{hash}', + ParticleCombiner="ParticleAdder") + + +from RecoConf.reconstruction_objects import make_pvs +from GaudiKernel.SystemOfUnits import GeV +from Hlt2Conf.algorithms_thor import ParticleFilter +from Hlt2Conf.lines.rd.builders.rdbuilder_thor import ( + make_rd_detached_muons, make_detached_dielectron_with_brem) + + +@configurable +def make_dimuon(name='rd_detached_dimuon_{hash}', + pt_dimuon_min=0. * MeV, + pt_muon_min=300. * MeV, + p_muon_min=3000. * MeV, + ipchi2_muon_min=9., + pidmu_muon_min=3., + bpvvdchi2_min=30., + vchi2pdof_max=30., + am_min=0. * MeV, + am_max=6000. * MeV, + same_sign=False): + + muons = make_rd_detached_muons( + name='rd_detached_muons_{hash}', + pt_min=pt_muon_min, + p_min=p_muon_min, + mipchi2dvprimary_min=ipchi2_muon_min, + # pid=F.require_all(F.ISMUON, F.PID_MU > pidmu_muon_min)) + pid=(F.PID_MU > pidmu_muon_min)) # keep the IsMuon out for the moment + + DecayDescriptor = 'J/psi(1S) -> mu+ mu-' + if same_sign: DecayDescriptor = '[J/psi(1S) -> mu+ mu+]cc' + + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.PT > pt_dimuon_min, + ) + + pvs = make_pvs() + vertex_code = F.require_all(F.CHI2DOF < vchi2pdof_max, + F.BPVFDCHI2(pvs) > bpvvdchi2_min) + return ParticleCombiner([muons, muons], + name=name, + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_dielectron(name='rd_detached_dielectron_{hash}', + pid_e_min=2., + pt_e_min=0.35 * GeV, + ipchi2_e_min=9., + parent_id="J/psi(1S)", + opposite_sign=True, + pt_diE_min=0. * MeV, + adocachi2cut_max=169., + bpvvdchi2_min=30., + vfaspfchi2ndof_max=9., + am_min=0. * MeV, + am_max=6000. * MeV): + + dielectrons = make_detached_dielectron_with_brem( + opposite_sign=opposite_sign, + PIDe_min=pid_e_min, + pt_e=pt_e_min, + minipchi2=ipchi2_e_min, + dielectron_ID=parent_id, + pt_diE=pt_diE_min, + m_diE_min=am_min, + m_diE_max=am_max, + adocachi2cut=adocachi2cut_max, + bpvvdchi2=bpvvdchi2_min, + vfaspfchi2ndof=vfaspfchi2ndof_max) + code = F.require_all(F.MASS > am_min, F.MASS < am_max) + return ParticleFilter(dielectrons, F.FILTER(code), name=name) + + +def make_b_to_Xpbar_dilepton( + dileptons, + Xs, + pbars, + pvs, + name="rd_b_to_Xpbar_dilepton", + descriptor="B_s0 -> J/psi(1S) p+ p~-", + # Xpbar intermediate cuts + am_Xpbar_min=1800. * MeV, + am_Xpbar_max=6000. * MeV, + am_Xpbar_scale_min=0.8, + am_Xpbar_scale_max=1.2, + min_Xpbar_pt=0 * MeV, + adocachi2cut_Xpbar_max=30., + # b cuts + am_b_min=4000 * MeV, + am_b_max=6500 * MeV, + am_b_scale_min=0.8, + am_b_scale_max=1.2, + min_b_pt=0 * GeV, + vchi2pdof_b_max=25, + bpvipchi2_b_max=25, + FDchi2_b_min=100, + dira_b_min=0.999): + '''builder for resonant and non-resonant B(s)ppbarmumu and B(s)ppbaree''' + + combination_code = F.require_all( + in_range(am_Xpbar_min * am_Xpbar_scale_min, + F.SUBCOMB(Functor=F.MASS, Indices=[2, 3]), + am_Xpbar_max * am_Xpbar_scale_max), + F.SUBCOMB(Functor=F.PT, Indices=[2, 3]) > min_Xpbar_pt, + F.SUBCOMB( + Functor=F.MAXSDOCACHI2CUT(adocachi2cut_Xpbar_max), Indices=[2, 3]), + in_range(am_b_min * am_b_scale_min, F.MASS, am_b_max * am_b_scale_max), + F.PT > min_b_pt) + + vertex_code = F.require_all( + in_range(am_Xpbar_min, F.SUBCOMB(Functor=F.MASS, Indices=[2, 3]), + am_Xpbar_max), + in_range(am_b_min, F.MASS, am_b_max), + F.BPVIPCHI2(pvs) < bpvipchi2_b_max, + F.BPVDIRA(pvs) > dira_b_min, + F.BPVFDCHI2(pvs) > FDchi2_b_min, + F.CHI2DOF < vchi2pdof_b_max, + ) + + return ParticleCombiner([dileptons, Xs, pbars], + DecayDescriptor=descriptor, + CombinationCut=combination_code, + name=name, + CompositeCut=vertex_code) diff --git a/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_hlt2_mva.py b/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_hlt2_mva.py new file mode 100644 index 0000000000000000000000000000000000000000..1ae747f507b3c82d30435923e25cbb7f5b1d9277 --- /dev/null +++ b/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_hlt2_mva.py @@ -0,0 +1,1090 @@ +############################################################################### +# (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### + +from PyConf import configurable +from GaudiKernel.SystemOfUnits import MeV +from GaudiKernel.SystemOfUnits import GeV + +from rd_ap_2024.tupling.mc.v55r11p5 import b_to_xll_tmva_builder +from rd_ap_2024.tupling.mc.v55r11p5 import b_to_xll_builders +from rd_ap_2024.tupling.mc.v55r11p5 import rdbuilder_thor + +from Moore.lines import Hlt2Line +from Moore.config import register_line_builder +from RecoConf.reconstruction_objects import make_pvs + +from Hlt2Conf.lines.rd.builders import rd_isolation +from Hlt2Conf.lines.rd.builders import rad_incl_builder +from Hlt2Conf.lines.rd.builders.RpK_builders import make_lambdab_to_pkll +from Hlt2Conf.lines.rd.builders.RpK_builders import make_dihadron_from_pK +from Hlt2Conf.lines.rd.builders.rd_prefilters import rd_prefilter, _RD_MONITORING_VARIABLES + +import Functors as F + +from Hlt2Conf.algorithms_thor import ParticleFilter + +#---------------------------------------- +class llx_mva_options: + ''' + Numbers taken from: + Bs: http://lhcbdoc.web.cern.ch/lhcbdoc/stripping/config/stripping34r0p1/leptonic/strippingb2llxbdt_bs2eephiline.html + Lb: http://lhcbdoc.web.cern.ch/lhcbdoc/stripping/config/stripping34r0p1/leptonic/strippingb2llxbdt_lb2eepkline.html + Bd: http://lhcbdoc.web.cern.ch/lhcbdoc/stripping/config/stripping34r0p1/leptonic/strippingb2llxbdt_bd2eekstarline.html + Bp: http://lhcbdoc.web.cern.ch/lhcbdoc/stripping/config/stripping34r0p1/leptonic/strippingb2llxbdt_bu2eek + ''' + + @classmethod + def __class_getitem__(cls, key : str) -> dict: + if key == 'dielectron_tight': + d_opt = cls.get_dielectron() + d_opt['pid_e_min'] = +1. + elif key == 'dielectron_loose': + d_opt = cls.get_dielectron() + d_opt['pid_e_min'] = -1. + elif key == 'dielectron_nopid': + d_opt = cls.get_dielectron() + d_opt['pid_e_min'] = -999. + elif key == 'dielectron_nopid_jpsi': + d_opt = cls.get_dielectron() + d_opt['pid_e_min'] = -999. + d_opt['am_min'] = 2_500. * MeV + d_opt['am_max'] = 3_500. * MeV + #---------------------------- + elif key == 'dimuon': + d_opt = cls.get_dimuon() + #---------------------------- + elif key == 'kaon': + d_opt = cls.get_kaon() + elif key == 'Kst0s': + d_opt = cls.get_kstar0s() + elif key == 'phi': + d_opt = cls.get_phi() + elif key == 'pk': + d_opt = cls.get_lambda() + #---------------------------- + elif key == 'lb': + d_opt = cls.get_lb() + elif key == 'bs': + d_opt = cls.get_bs() + elif key == 'bp': + d_opt = cls.get_bp() + elif key == 'bd': + d_opt = cls.get_bd() + #---------------------------- + else: + raise ValueError + + return d_opt + + #---------------------------- + @classmethod + def get_dielectron(cls): + d_opt = dict() + d_opt['adocachi2cut_max'] = 10. + d_opt['ipchi2_e_min'] = 1. + d_opt['pt_diE_min'] = 0. * MeV + d_opt['pt_e_min'] = 200. * MeV + d_opt['p_e_min'] = 0. * GeV + d_opt['vfaspfchi2ndof_max'] = 16. + d_opt['am_min'] = 0. * MeV + d_opt['am_max'] = 5_500. * MeV + d_opt['bpvvdchi2_min'] = 0. + d_opt['parent_id'] = "J/psi(1S)" + d_opt['opposite_sign'] = True + d_opt['with_brem'] = True + + return d_opt + + #---------------------------- + @classmethod + def get_dimuon(cls): + d_opt = dict() + d_opt['am_min'] = 0. * MeV + d_opt['am_max'] = 6000. * MeV + d_opt['pidmu_muon_min'] = 0 + d_opt['ipchi2_muon_min'] = 3. + d_opt['pt_muon_min'] = 0.250 * GeV + d_opt['parent_id'] = 'J/psi(1S)' + d_opt['pt_dimuon_min'] = 0. * MeV + d_opt['bpvvdchi2_min'] = 0. + d_opt['adocachi2cut_max'] = 30. + d_opt['vchi2pdof_max'] = 16. + d_opt['p_muon_min'] = 2_000 * MeV + d_opt['same_sign'] = False + + return d_opt + + #---------------------------- + @classmethod + def get_kaon(cls): + d_opt = dict() + d_opt['name'] = 'rd_detached_kaons_{hash}' + d_opt['pt_min'] = 250. * MeV + d_opt['mipchi2dvprimary_min'] = 4. #TBC + d_opt['p_min'] = 0. * GeV + d_opt['pid'] = (F.PID_K > -2.) + + return d_opt + + #---------------------------- + @classmethod + def get_kstar0s(cls): + d_opt = dict() + d_opt['vchi2pdof_max'] = 16. + d_opt['am_min'] = 592. * MeV + d_opt['am_max'] = 1192. * MeV + d_opt['pi_p_min'] = 2. * GeV + d_opt['pi_pt_min'] = 250. * MeV + d_opt['pi_ipchi2_min'] = 4. + d_opt['pi_pid'] = (F.PID_K < 1e-5) + d_opt['k_p_min'] = 2. * GeV + d_opt['k_pt_min'] = 250. * MeV + d_opt['k_ipchi2_min'] = 4. + d_opt['k_pid'] = (F.PID_K > 0.) + d_opt['kstar0_pt_min'] = 0. * MeV + d_opt['adocachi2cut'] = 30. + d_opt['vchi2pdof_max'] = 16. + d_opt['bpvipchi2_min'] = None + d_opt['same_sign'] = False + + return d_opt + + #---------------------------- + @classmethod + def get_lambda(cls): + d_opt = dict() + d_opt['max_mass'] = 5600 * MeV + d_opt['min_pt'] = 0 * MeV + d_opt['max_vtxchi2dof'] = 25 + d_opt['max_docachi2'] = 30.0 + d_opt['same_sign'] = False + + return d_opt + + #---------------------------- + @classmethod + def get_phi(cls): + d_opt = dict() + d_opt['vchi2pdof_max'] = 25. + d_opt['am_min'] = 950. * MeV + d_opt['am_max'] = 1100. * MeV + d_opt['phi_pt_min'] = 0. * MeV + d_opt['adocachi2cut'] = 30. + + d_opt['k_p_min'] = 0. * GeV + d_opt['k_pt_min'] = 200. * MeV + d_opt['k_ipchi2_min'] = 2. + d_opt['k_pid'] = (F.PID_K > 0.) + + return d_opt + + #---------------------------- + @classmethod + def get_bs(cls): + d_opt = cls.get_bx() + d_opt['name'] = 'bsphill_mva_maker_{hash}' + d_opt['Descriptor'] = '[B_s0 -> J/psi(1S) phi(1020)]cc' + + return d_opt + + #---------------------------- + @classmethod + def get_bp(cls): + d_opt = cls.get_bx() + d_opt['name'] = 'bpkll_mva_maker_{hash}' + d_opt['Descriptor'] = '[B+ -> J/psi(1S) K+]cc' + + return d_opt + + #---------------------------- + @classmethod + def get_bd(cls): + d_opt = cls.get_bx() + d_opt['name'] = 'bdkstll_mva_maker_{hash}' + d_opt['Descriptor'] = '[B0 -> J/psi(1S) K*(892)0]cc' + + return d_opt + + #---------------------------- + @classmethod + def get_lb(cls): + d_opt = dict() + d_opt['name'] = 'lbpkll_mva_maker_{hash}' + d_opt['descriptor'] = '[Lambda_b0 -> J/psi(1S) Lambda(1520)0]cc' + d_opt['min_mass'] = 3700 * MeV + d_opt['max_mass'] = 7100 * MeV + d_opt['min_dira'] = 0.999 + d_opt['min_flightdist'] = 0 + d_opt['max_vtxchi2dof'] = 25 + d_opt['max_ipchi2'] = 400 + + return d_opt + + #---------------------------- + @classmethod + def get_bx(cls): + d_opt = dict() + d_opt['am_min'] = 4_500. * MeV + d_opt['am_max'] = 7_000. * MeV + d_opt['B_pt_min'] = 0 * MeV + d_opt['FDchi2_min'] = 50. + d_opt['vchi2pdof_max'] = 9. + d_opt['bpvipchi2_max'] = 25. + d_opt['min_cosine'] = 0.9995 + d_opt['low_factor'] = 0.5 + d_opt['high_factor'] = 1.5 + + return d_opt + + +#---------------------------- +def get_isolations(d_part): + l_iso = [] + for name, (part, dr) in d_part.items(): + iso_parts = rd_isolation.select_parts_for_isolation( + names=[name], + candidates=[part], + cut=F.require_all(F.DR2 < dr, ~F.FIND_IN_TREE())) + + l_iso += iso_parts + + return l_iso + + +#---------------------------- +def add_mva(bmeson, pvs, mva_name, line_name, mva_wp): + b = b_to_xll_tmva_builder.make_b2( + bmeson, + pvs, + mva_name, + mva_wp, + filter_name=f'{mva_name}_{line_name}_{hash}') + bdt_moni = rad_incl_builder.make_monitor( + f"{line_name}_BDT_output", bmeson, + b_to_xll_tmva_builder.xll_BDT_functor(pvs, mva_name)) + + return b, bdt_moni + + +#---------------------------- +def filter_tracks(tracks, line_name, ghst_prob=0.5, trchi2dof_max=3.0): + code = F.require_all(F.GHOSTPROB < ghst_prob, F.CHI2DOF < trchi2dof_max) + tracks = ParticleFilter(tracks, Cut=F.FILTER(code)) + + return tracks + + +#---------------------------- +def filter_dileptons(dilepton, line_name, ghst_prob=0.5, trchi2dof_max=3.0): + code_1 = (F.CHILD(1, F.GHOSTPROB) < ghst_prob) & (F.CHILD(2, F.GHOSTPROB) < + ghst_prob) + code_2 = (F.CHILD(1, F.CHI2DOF) < trchi2dof_max) & (F.CHILD(2, F.CHI2DOF) < + trchi2dof_max) + code = code_1 & code_2 + + flt = ParticleFilter(dilepton, Cut=F.FILTER(code)) + + return flt + + +#---------------------------- +def tag_dielectron_pid(dielectrons, name, pid_tag=4.0): + code = (F.CHILD(1, F.PID_E) > pid_tag) | (F.CHILD(2, F.PID_E) > pid_tag) + + flt = ParticleFilter(dielectrons, Cut=F.FILTER(code)) + + return flt + + +#---------------------------- +def filter_anti_pid_e(dielectrons, name, pid_low=-1.0, pid_hig=+1.0): + code_1 = (F.CHILD(1, F.PID_E) > pid_low) & (F.CHILD(2, F.PID_E) > pid_low) + code_2 = (F.CHILD(1, F.PID_E) < pid_hig) | (F.CHILD(2, F.PID_E) < pid_hig) + code = code_1 & code_2 + + flt = ParticleFilter(dielectrons, Cut=F.FILTER(code)) + + return flt + + +#---------------------------- +all_lines = {} + + +######################################## +# Bp -> K+ ll HLT2 lines # +######################################## +@register_line_builder(all_lines) +@configurable +def bp2kpee_mva_line(name='Hlt2RD_BuToKpEE_MVA', prescale=1, mva_wp=0.06): + d_opt = llx_mva_options['dielectron_tight'] + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + pvs = make_pvs() + + d_opt = llx_mva_options['kaon'] + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, name) + + d_opt = llx_mva_options['bp'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = kaons + d_opt['pvs'] = pvs + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bp, pvs, 'bullx', name, mva_wp) + + d_iso = {'bp': (bp, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bp2kpmumu_mva_line(name='Hlt2RD_BuToKpMuMu_MVA', prescale=1, mva_wp=0.15): + d_opt = llx_mva_options['dimuon'] + detached_dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + detached_dimuons = filter_dileptons(detached_dimuons, name) + pvs = make_pvs() + + d_opt = llx_mva_options['kaon'] + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, name) + + d_opt = llx_mva_options['bp'] + d_opt['dileptons'] = detached_dimuons + d_opt['hadrons'] = kaons + d_opt['pvs'] = make_pvs() + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bp, pvs, 'bullx', name, mva_wp) + + d_iso = {'bp': (bp, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dimuons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bp2kpee_ss_mva_line(name='Hlt2RD_BuToKpEE_SameSign_MVA', + prescale=1, + mva_wp=0.06): + d_opt = llx_mva_options['dielectron_tight'] + d_opt['opposite_sign'] = False + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + pvs = make_pvs() + + d_opt = llx_mva_options['kaon'] + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, name) + + d_opt = llx_mva_options['bp'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = kaons + d_opt['pvs'] = pvs + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bp, pvs, 'bullx', name, mva_wp) + + d_iso = {'bp': (bp, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bp2kpmumu_ss_mva_line(name='Hlt2RD_BuToKpMuMu_SameSign_MVA', + prescale=1, + mva_wp=0.20): + d_opt = llx_mva_options['dimuon'] + d_opt['same_sign'] = True + detached_dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + detached_dimuons = filter_dileptons(detached_dimuons, name) + pvs = make_pvs() + + d_opt = llx_mva_options['kaon'] + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, name) + + d_opt = llx_mva_options['bp'] + d_opt['dileptons'] = detached_dimuons + d_opt['hadrons'] = kaons + d_opt['pvs'] = make_pvs() + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bp, pvs, 'bullx', name, mva_wp) + + d_iso = {'bp': (bp, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dimuons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bp2kpee_mva_line_misid(name='Hlt2RD_BuToKpEE_MVA_misid', + prescale=0.1, + mva_wp=0.06): + d_opt = llx_mva_options['dielectron_nopid'] + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + detached_dielectrons = filter_anti_pid_e(detached_dielectrons, name) + + pvs = make_pvs() + + d_opt = llx_mva_options['kaon'] + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, name) + + d_opt = llx_mva_options['bp'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = kaons + d_opt['pvs'] = pvs + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bp, pvs, 'bullx', name, mva_wp) + + d_iso = {'bp': (bp, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bp2kpee_mva_line_cal(name='Hlt2RD_BuToKpEE_MVA_cal', + prescale=1, + mva_wp=0.08): + d_opt = llx_mva_options['dielectron_nopid_jpsi'] + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + detached_dielectrons = tag_dielectron_pid(detached_dielectrons, name) + + pvs = make_pvs() + + d_opt = llx_mva_options['kaon'] + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, name) + + d_opt = llx_mva_options['bp'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = kaons + d_opt['pvs'] = pvs + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bp, pvs, 'bullx', name, mva_wp) + + d_iso = {'bp': (bp, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +######################################## +# B0 -> K+ pi- ll HLT2 lines # +######################################## +@register_line_builder(all_lines) +@configurable +def bd2kpiee_mva_line(name="Hlt2RD_B0ToKpPimEE_MVA", prescale=1, mva_wp=0.02): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_tight'] + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + + d_opt = llx_mva_options['Kst0s'] + Kst0s = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + Kst0s = filter_dileptons(Kst0s, name) + + d_opt = llx_mva_options['bd'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = Kst0s + d_opt['pvs'] = pvs + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bd, pvs, 'bullx', name, mva_wp) + + d_iso = {'bd': (bd, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bd2kpimm_mva_line(name="Hlt2RD_B0ToKpPimMuMu_MVA", prescale=1, + mva_wp=0.25): + pvs = make_pvs() + + d_opt = llx_mva_options['dimuon'] + detached_dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + detached_dimuons = filter_dileptons(detached_dimuons, name) + + d_opt = llx_mva_options['Kst0s'] + Kst0s = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + Kst0s = filter_dileptons(Kst0s, name) + + d_opt = llx_mva_options['bd'] + d_opt['dileptons'] = detached_dimuons + d_opt['hadrons'] = Kst0s + d_opt['pvs'] = pvs + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bd, pvs, 'bullx', name, mva_wp) + + d_iso = {'bd': (bd, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dimuons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bd2kpiee_ss_mva_line(name="Hlt2RD_B0ToKpPimEE_SameSign_MVA", + prescale=1, + mva_wp=0.02): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_tight'] + d_opt['opposite_sign'] = False + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + + d_opt = llx_mva_options['Kst0s'] + Kst0s = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + Kst0s = filter_dileptons(Kst0s, name) + + d_opt = llx_mva_options['bd'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = Kst0s + d_opt['pvs'] = pvs + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bd, pvs, 'bullx', name, mva_wp) + + d_iso = {'bd': (bd, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bd2kpimm_ss_mva_line(name="Hlt2RD_B0ToKpPimMuMu_SameSign_MVA", + prescale=1, + mva_wp=0.25): + pvs = make_pvs() + + d_opt = llx_mva_options['dimuon'] + d_opt['same_sign'] = True + detached_dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + detached_dimuons = filter_dileptons(detached_dimuons, name) + + d_opt = llx_mva_options['Kst0s'] + Kst0s = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + Kst0s = filter_dileptons(Kst0s, name) + + d_opt = llx_mva_options['bd'] + d_opt['dileptons'] = detached_dimuons + d_opt['hadrons'] = Kst0s + d_opt['pvs'] = pvs + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bd, pvs, 'bullx', name, mva_wp) + + d_iso = {'bd': (bd, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dimuons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bd2kpiee_mva_line_misid(name="Hlt2RD_B0ToKpPimEE_MVA_misid", + prescale=0.03, + mva_wp=0.02): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_nopid'] + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + detached_dielectrons = filter_anti_pid_e(detached_dielectrons, name) + + d_opt = llx_mva_options['Kst0s'] + Kst0s = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + Kst0s = filter_dileptons(Kst0s, name) + + d_opt = llx_mva_options['bd'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = Kst0s + d_opt['pvs'] = pvs + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bd, pvs, 'bullx', name, mva_wp) + + d_iso = {'bd': (bd, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def bd2kpiee_mva_line_cal(name="Hlt2RD_B0ToKpPimEE_MVA_cal", + prescale=1, + mva_wp=0.25): + d_opt = llx_mva_options['dielectron_nopid_jpsi'] + detached_dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectrons = filter_dileptons(detached_dielectrons, name) + detached_dielectrons = tag_dielectron_pid(detached_dielectrons, name) + + pvs = make_pvs() + + d_opt = llx_mva_options['Kst0s'] + Kst0s = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + Kst0s = filter_dileptons(Kst0s, name) + + d_opt = llx_mva_options['bd'] + d_opt['dileptons'] = detached_dielectrons + d_opt['hadrons'] = Kst0s + d_opt['pvs'] = pvs + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bd, pvs, 'bullx', name, mva_wp) + + d_iso = {'bd': (bd, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [detached_dielectrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +######################################## +# Lb -> Lambda pK ll +######################################## +@register_line_builder(all_lines) +@configurable +def lb2pkee_mva_line(name="Hlt2RD_LbTopKEE_MVA", prescale=1, mva_wp=0.05): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_tight'] + dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + dielectrons = filter_dileptons(dielectrons, name) + + d_opt = llx_mva_options['pk'] + dihadrons = make_dihadron_from_pK() + dihadrons = filter_dileptons(dihadrons, name) + + d_opt = llx_mva_options['lb'] + d_opt['dileptons'] = dielectrons + d_opt['dihadrons'] = dihadrons + lb = make_lambdab_to_pkll(**d_opt) + + d_iso = {'Lb': (lb, 0.25)} + l_iso = get_isolations(d_iso) + b, bdt_moni = add_mva(lb, pvs, 'bullx', name, mva_wp) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dielectrons, dihadrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def lb2pkmm_mva_line(name="Hlt2RD_LbTopKMuMu_MVA", prescale=1, mva_wp=0.50): + pvs = make_pvs() + + d_opt = llx_mva_options['dimuon'] + dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + dimuons = filter_dileptons(dimuons, name) + + d_opt = llx_mva_options['pk'] + dihadrons = make_dihadron_from_pK() + dihadrons = filter_dileptons(dihadrons, name) + + d_opt = llx_mva_options['lb'] + d_opt['dileptons'] = dimuons + d_opt['dihadrons'] = dihadrons + lb = make_lambdab_to_pkll(**d_opt) + + d_iso = {'Lb': (lb, 0.25)} + l_iso = get_isolations(d_iso) + b, bdt_moni = add_mva(lb, pvs, 'bullx', name, mva_wp) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dimuons, dihadrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def lb2pkee_ss_mva_line(name="Hlt2RD_LbTopKEE_SameSign_MVA", + prescale=1, + mva_wp=0.05): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_tight'] + d_opt['opposite_sign'] = False + dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + dielectrons = filter_dileptons(dielectrons, name) + + d_opt = llx_mva_options['pk'] + dihadrons = make_dihadron_from_pK() + dihadrons = filter_dileptons(dihadrons, name) + + d_opt = llx_mva_options['lb'] + d_opt['dileptons'] = dielectrons + d_opt['dihadrons'] = dihadrons + lb = make_lambdab_to_pkll(**d_opt) + + d_iso = {'Lb': (lb, 0.25)} + l_iso = get_isolations(d_iso) + b, bdt_moni = add_mva(lb, pvs, 'bullx', name, mva_wp) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dielectrons, dihadrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def lb2pkmm_ss_mva_line(name="Hlt2RD_LbTopKMuMu_SameSign_MVA", + prescale=0.1, + mva_wp=0.05): + pvs = make_pvs() + + d_opt = llx_mva_options['dimuon'] + d_opt['same_sign'] = True + dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + dimuons = filter_dileptons(dimuons, name) + + d_opt = llx_mva_options['pk'] + dihadrons = make_dihadron_from_pK() + dihadrons = filter_dileptons(dihadrons, name) + + d_opt = llx_mva_options['lb'] + d_opt['dileptons'] = dimuons + d_opt['dihadrons'] = dihadrons + lb = make_lambdab_to_pkll(**d_opt) + + d_iso = {'Lb': (lb, 0.25)} + l_iso = get_isolations(d_iso) + b, bdt_moni = add_mva(lb, pvs, 'bullx', name, mva_wp) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dimuons, dihadrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def lb2pkee_mva_line_misid(name="Hlt2RD_LbTopKEE_MVA_misid", + prescale=0.1, + mva_wp=0.05): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_nopid'] + dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + dielectrons = filter_dileptons(dielectrons, name) + dielectrons = filter_anti_pid_e(dielectrons, name) + + d_opt = llx_mva_options['pk'] + dihadrons = make_dihadron_from_pK() + dihadrons = filter_dileptons(dihadrons, name) + + d_opt = llx_mva_options['lb'] + d_opt['dileptons'] = dielectrons + d_opt['dihadrons'] = dihadrons + lb = make_lambdab_to_pkll(**d_opt) + + d_iso = {'Lb': (lb, 0.25)} + l_iso = get_isolations(d_iso) + b, bdt_moni = add_mva(lb, pvs, 'bullx', name, mva_wp) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dielectrons, dihadrons, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +######################################## +# Bs -> phi ll +######################################## +@register_line_builder(all_lines) +@configurable +def BsToPhiEE_MVA(name="Hlt2RD_BsToPhiEE_MVA", prescale=1, mva_wp=-0.10): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_tight'] + dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + dielectrons = filter_dileptons(dielectrons, name) + + d_opt = llx_mva_options['phi'] + phis = rdbuilder_thor.make_rd_detached_phis(**d_opt) + phis = filter_dileptons(phis, name) + + d_opt = llx_mva_options['bs'] + d_opt['dileptons'] = dielectrons + d_opt['hadrons'] = phis + d_opt['pvs'] = pvs + bs = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bs, pvs, 'bullx', name, mva_wp) + + d_iso = {'B': (bs, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dielectrons, phis, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def BsToPhiMuMu_MVA(name="Hlt2RD_BsToPhiMuMu_MVA", prescale=1, mva_wp=-0.10): + pvs = make_pvs() + + d_opt = llx_mva_options['dimuon'] + dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + dimuons = filter_dileptons(dimuons, name) + + d_opt = llx_mva_options['phi'] + phis = rdbuilder_thor.make_rd_detached_phis(**d_opt) + phis = filter_dileptons(phis, name) + + d_opt = llx_mva_options['bs'] + d_opt['dileptons'] = dimuons + d_opt['hadrons'] = phis + d_opt['pvs'] = pvs + bs = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bs, pvs, 'bullx', name, mva_wp) + + d_iso = {'B': (bs, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dimuons, phis, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def BsToPhiEE_ss_MVA(name="Hlt2RD_BsToPhiEE_SameSign_MVA", + prescale=1, + mva_wp=-0.10): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_tight'] + d_opt['opposite_sign'] = False + dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + dielectrons = filter_dileptons(dielectrons, name) + + d_opt = llx_mva_options['phi'] + phis = rdbuilder_thor.make_rd_detached_phis(**d_opt) + phis = filter_dileptons(phis, name) + + d_opt = llx_mva_options['bs'] + d_opt['dileptons'] = dielectrons + d_opt['hadrons'] = phis + d_opt['pvs'] = pvs + bs = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bs, pvs, 'bullx', name, mva_wp) + + d_iso = {'B': (bs, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dielectrons, phis, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def BsToPhiMuMu_ss_MVA(name="Hlt2RD_BsToPhiMuMu_SameSign_MVA", + prescale=1, + mva_wp=-0.10): + pvs = make_pvs() + + d_opt = llx_mva_options['dimuon'] + d_opt['same_sign'] = True + dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + dimuons = filter_dileptons(dimuons, name) + + d_opt = llx_mva_options['phi'] + phis = rdbuilder_thor.make_rd_detached_phis(**d_opt) + phis = filter_dileptons(phis, name) + + d_opt = llx_mva_options['bs'] + d_opt['dileptons'] = dimuons + d_opt['hadrons'] = phis + d_opt['pvs'] = pvs + bs = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bs, pvs, 'bullx', name, mva_wp) + + d_iso = {'B': (bs, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dimuons, phis, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- +@register_line_builder(all_lines) +@configurable +def BsToPhiEE_MVA_misid(name="Hlt2RD_BsToPhiEE_MVA_misid", + prescale=0.01, + mva_wp=-0.10): + pvs = make_pvs() + + d_opt = llx_mva_options['dielectron_nopid'] + dielectrons = rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + dielectrons = filter_dileptons(dielectrons, name) + dielectrons = filter_anti_pid_e(dielectrons, name) + + d_opt = llx_mva_options['phi'] + phis = rdbuilder_thor.make_rd_detached_phis(**d_opt) + phis = filter_dileptons(phis, name) + + d_opt = llx_mva_options['bs'] + d_opt['dileptons'] = dielectrons + d_opt['hadrons'] = phis + d_opt['pvs'] = pvs + bs = b_to_xll_builders.make_rd_BToXll(**d_opt) + b, bdt_moni = add_mva(bs, pvs, 'bullx', name, mva_wp) + + d_iso = {'B': (bs, 0.25)} + l_iso = get_isolations(d_iso) + + return Hlt2Line( + name=name, + algs=rd_prefilter() + [dielectrons, phis, bdt_moni, b], + extra_outputs=l_iso, + prescale=prescale, + persistreco=True, + monitoring_variables=_RD_MONITORING_VARIABLES) + + +#---------------------------- diff --git a/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_tmva_builder.py b/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_tmva_builder.py new file mode 100644 index 0000000000000000000000000000000000000000..47913d9d0b290a8cf9502d6b4a2df7d891021636 --- /dev/null +++ b/rd_ap_2024/tupling/mc/v55r11p5/b_to_xll_tmva_builder.py @@ -0,0 +1,69 @@ +############################################################################### +# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +"""Definition of MVA tools for XLL lines +""" +from PyConf import configurable + +import Functors as F +from Functors.math import log +from Hlt2Conf.algorithms_thor import ParticleFilter + + +@configurable +def xll_BDT_functor(pvs, line): + bullx_vars = { + 'min_ll_pt': + F.MINTREE(((F.IS_ID('e+')) | (F.IS_ID('e-'))), F.PT), + 'max_ll_pt': + F.MAXTREE(((F.IS_ID('e+')) | (F.IS_ID('e-'))), F.PT), + 'min_log_ll_ipchi2': + F.MINTREE(((F.IS_ID('e+')) | (F.IS_ID('e-'))), log(F.MINIPCHI2(pvs))), + 'max_log_ll_ipchi2': + F.MAXTREE(((F.IS_ID('e+')) | (F.IS_ID('e-'))), log(F.MINIPCHI2(pvs))), + #-------------------- + 'b_pt': + F.PT, + 'j_pt': + F.CHILD(1, F.PT), + 'h_pt': + F.CHILD(2, F.PT), + #-------------------- + 'dira': + F.BPVDIRA(pvs), + 'b_vtx_chi2': + log(F.CHI2DOF), + 'log_b_fdchi2': + log(F.BPVFDCHI2(pvs)), + 'log_b_ipchi2': + log(F.BPVIPCHI2(pvs)), + 'log_j_ipchi2': + log(F.CHILD(1, F.BPVIPCHI2(pvs))), + 'log_h_ipchi2': + log(F.CHILD(2, F.BPVIPCHI2(pvs))) + } + + bdt_vars = {'bullx': bullx_vars} + + xml_files = {"bullx": 'paramfile://data/Hlt2_RD_llk.xml'} + + return F.MVA( + MVAType='TMVA', + Config={ + 'XMLFile': xml_files[line], + 'Name': 'BDT', + }, + Inputs=bdt_vars[line]) + + +@configurable +def make_b2(presel_b, pvs, line, bdt_cut, filter_name="rd_xll_mva_B_{hash}"): + code = xll_BDT_functor(pvs, line) > bdt_cut + return ParticleFilter(presel_b, F.FILTER(code), name=filter_name) diff --git a/rd_ap_2024/tupling/mc/v55r11p5/offline_builders.py b/rd_ap_2024/tupling/mc/v55r11p5/offline_builders.py new file mode 100644 index 0000000000000000000000000000000000000000..13df548eee683f4ccc247df961e4c0074b83b048 --- /dev/null +++ b/rd_ap_2024/tupling/mc/v55r11p5/offline_builders.py @@ -0,0 +1,149 @@ +''' +Module with functions used to retrieve B candidates +''' + +import Functors as F +from PyConf.reading import get_pvs + +from rd_ap_2024.tupling.mc.v55r11p5.b_to_xll_hlt2_mva import llx_mva_options +from rd_ap_2024.tupling.mc.v55r11p5 import rdbuilder_thor +from rd_ap_2024.tupling.mc.v55r11p5 import b_to_xll_builders +from rd_ap_2024.tupling.mc.v55r11p5.b_to_xll_hlt2_mva import add_mva +from rd_ap_2024.tupling.mc.v55r11p5.b_to_xll_hlt2_mva import filter_dileptons +from rd_ap_2024.tupling.mc.v55r11p5.b_to_xll_hlt2_mva import filter_tracks +from rd_ap_2024.utils.log_store import LogStore + +log=LogStore.add_logger('rd_ap_2024:offline_builder') +#--------------------------------------------------------------------------------- +def _replace_with_functors(name : str, cut_value : float): + ''' + This is needed to replace cuts like + + pid < 0.9 + + with functors like + + F.PID_K < 0.9 + ''' + if name not in ['pi_pid', 'k_pid', 'pid']: + return cut_value + + if name == 'pi_pid': + return F.PID_K < cut_value + + return F.PID_K > cut_value +#--------------------------------------------------------------------------------- +def _get_selection(line_name : str, custom_name : str, particle : str, cfg : dict) -> dict: + ''' + Will pick up the HLT2 line name, the variation of it (noPID, etc) and + the particle (dimuon, etc) If for this line, and customization, the + particle is overriden in the YAML file, the selection will be updated + ''' + d_opt : dict = llx_mva_options[particle] + + if particle not in cfg[line_name]['custom'][custom_name]: + log.debug(f'Not overriding selection for {custom_name}:{line_name}/{particle}') + return d_opt + + log.info(f'Change for {line_name} -> {custom_name}[{particle}]') + + d_cut_particle = cfg[line_name]['custom'][custom_name][particle] + d_cut_replaced = { particle : _replace_with_functors(particle, cut) for particle, cut in d_cut_particle.items() } + + d_opt.update(d_cut_replaced) + + return d_opt +#--------------------------------------------------------------------------------- +def get_bdkstarmm_candidates(line_name : str, custom_name : str, cfg : dict): + ''' + Returns B candidates for Bd muon + ''' + + d_opt = _get_selection(line_name, custom_name, 'dimuon', cfg) + detached_dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + detached_dimuons = filter_dileptons(detached_dimuons, line_name) + + d_opt = _get_selection(line_name, custom_name, 'Kst0s', cfg) + hh = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + hh = filter_dileptons(hh, line_name) + + d_opt = _get_selection(line_name, custom_name, 'bd', cfg) + d_opt['dileptons'] = detached_dimuons + d_opt['hadrons'] = hh + d_opt['pvs'] = get_pvs() + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + + line_name = f'mva_{custom_name}' + bd, _ = add_mva(bd, get_pvs(), 'bullx', line_name, 0.25) + + return bd +#--------------------------------------------------------------------------------- +def get_bukpmm_candidates(line_name : str, custom_name : str, cfg : dict): + ''' + Returns B candidates for B+ muon + ''' + d_opt = _get_selection(line_name, custom_name, 'dimuon', cfg) + detached_dimuons = rdbuilder_thor.make_rd_detached_dimuon(**d_opt) + detached_dimuons = filter_dileptons(detached_dimuons, line_name) + + d_opt = _get_selection(line_name, custom_name, 'kaon', cfg) + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, line_name) + + d_opt = _get_selection(line_name, custom_name, 'bp', cfg) + d_opt['dileptons'] = detached_dimuons + d_opt['hadrons'] = kaons + d_opt['pvs'] = get_pvs() + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + + line_name = f'mva_{custom_name}' + bp, _ = add_mva(bp, get_pvs(), 'bullx', line_name, 0.15) + + return bp +#--------------------------------------------------------------------------------- +def get_bukpee_candidates(line_name : str, custom_name : str, cfg : dict): + ''' + Returns B candidates for B+ electron + ''' + d_opt = _get_selection(line_name, custom_name, 'dielectron_tight', cfg) + detached_dielectron= rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectron= filter_dileptons(detached_dielectron, line_name) + + d_opt = _get_selection(line_name, custom_name, 'kaon', cfg) + kaons = rdbuilder_thor.make_rd_detached_kaons(**d_opt) + kaons = filter_tracks(kaons, line_name) + + d_opt = _get_selection(line_name, custom_name, 'bp', cfg) + d_opt['dileptons'] = detached_dielectron + d_opt['hadrons'] = kaons + d_opt['pvs'] = get_pvs() + bp = b_to_xll_builders.make_rd_BToXll(**d_opt) + + line_name = f'mva_{custom_name}' + bp, _ = add_mva(bp, get_pvs(), 'bullx', line_name, 0.06) + + return bp +#--------------------------------------------------------------------------------- +def get_bdkstaree_candidates(line_name : str, custom_name : str, cfg : dict): + ''' + Returns B candidates for Bd electron + ''' + + d_opt = _get_selection(line_name, custom_name, 'dielectron_tight', cfg) + detached_dielectron= rdbuilder_thor.make_rd_detached_dielectron(**d_opt) + detached_dielectron= filter_dileptons(detached_dielectron, line_name) + + d_opt = _get_selection(line_name, custom_name, 'Kst0s', cfg) + hh = rdbuilder_thor.make_rd_detached_kstar0s(**d_opt) + hh = filter_dileptons(hh, line_name) + + d_opt = _get_selection(line_name, custom_name, 'bd', cfg) + d_opt['dileptons'] = detached_dielectron + d_opt['hadrons'] = hh + d_opt['pvs'] = get_pvs() + bd = b_to_xll_builders.make_rd_BToXll(**d_opt) + + line_name = f'mva_{custom_name}' + bd, _ = add_mva(bd, get_pvs(), 'bullx', line_name, 0.02) + + return bd diff --git a/rd_ap_2024/tupling/mc/v55r11p5/rdbuilder_thor.py b/rd_ap_2024/tupling/mc/v55r11p5/rdbuilder_thor.py new file mode 100644 index 0000000000000000000000000000000000000000..c655b780571714d445157eb27040e17d5e79d875 --- /dev/null +++ b/rd_ap_2024/tupling/mc/v55r11p5/rdbuilder_thor.py @@ -0,0 +1,1499 @@ +############################################################################## +# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +""" +Definition of the common RD builders in the ThOr framework. + +** The list of currently available filters and builders: ** + +-- Charged tracks -- +make_filter_tracks : generic builder of long (pion) tracks +make_rd_prompt_{muons,electrons,pions,kaons,protons} - generic filters for each charged particle (long tracks) +make_rd_prompt_pions_no_rich - generic filter for pions without requiring RICH +make_rd_detached_{muons,electrons,pions,kaons,protons} - generic filters for each charged particle (long tracks) +make_rd_has_rich_detached_{pions,kaons,protons} – long-track hadron filters with RICH info +make_rd_detached_down_{pions,kaons,protons} - downstream-track hadron filters for V0 and hyperon candidates + +-- Neutrals -- only dummy selections for the moment! +make_rd_photons +make_rd_resolved_pi0s +make_rd_merged_pi0s + +-- V0 particles -- +make_rd_ks0_lls - KS0 builder from long-track pions +make_rd_ks0_dds - KS0 builder from downstream-track pions +make_rd_lambda_lls - Lambda0 builder from long tracks +make_rd_lambda_dds - Lambda0 builder from downstream tracks + +-- Popular intermediate hadrons -- +make_rd_detached_kstar0s - K*->K+pi- builder +make_rd_detached_phis - phi->K+K- builder +make_rd_detached_rho0 - rho->pi+pi- builder +make_rd_detached_etaprime - eta'->pi+pi-gamma builder +make_rd_detached_k1 - K1(1270)+->K+pi+pi- builder + +-- Dileptons -- +make_rd_{prompt,detached}_dimuon - mu+mu- combination +make_rd_{prompt,detached}_dielectron - e+e- combination with the proper brem recovery +make_rd_{prompt,detached}_mue - mue (same- or opposite-sign) combination + +-- Other -- +make_rd_tauons_hadronic_decay - tau->3pi builder +make_rd_detached_dihadron - hh builder (same- or opposite-sign) +""" +from GaudiKernel.SystemOfUnits import GeV, MeV, ps, micrometer +from RecoConf.reconstruction_objects import make_pvs + +import Functors as F +from Functors.math import in_range + +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleFilter + +from PyConf import configurable + +from Hlt2Conf.standard_particles import ( + make_has_rich_long_pions, + make_has_rich_long_kaons, + make_has_rich_long_protons, + make_long_pions, + make_long_kaons, + make_long_protons, + #make_has_rich_down_pions, make_has_rich_down_kaons, make_has_rich_down_protons, # we don't usually need RICH info in fact for D tracks + make_down_pions, + make_down_kaons, + make_down_protons, + #make_KsLL, make_KsDD, make_LambdaLL, make_LambdaDD, # we build our own versions below + make_long_muons, + make_long_electrons_with_brem, + make_long_electrons_no_brem, + make_long_and_upstream_electrons_no_brem, + make_photons, + make_resolved_pi0s, + make_merged_pi0s, + # make_detached_mumu, + make_detached_dielectron, + _make_dielectron_with_brem, + make_detached_dielectron_with_brem, + make_detached_mue_with_brem) + +#################################### +# Charged hadron selections # +#################################### + + +@configurable +def make_filter_tracks( + make_particles=make_has_rich_long_pions, + make_pvs=make_pvs, + name="rd_has_rich_long_pions", + pt_min=250. * MeV, + p_min=2.0 * GeV, + trchi2dof_max=3, #TBC with Reco + trghostprob_max=0.4, #TBC with Reco + mipchi2dvprimary_min=None, + pid=None): + """ + Build generic long tracks. + """ + code = F.require_all( + F.PT > pt_min, + F.P > p_min, + #F.CHI2DOF < trchi2dof_max, # <- removed for the early data taking in 2022 + #F.GHOSTPROB < trghostprob_max # <- removed for the early data taking in 2022 + ) + + if pid is not None: + code &= pid + + if mipchi2dvprimary_min is not None: + pvs = make_pvs() + code &= F.MINIPCHI2(pvs) > mipchi2dvprimary_min + + return ParticleFilter(make_particles(), name=name, Cut=F.FILTER(code)) + + +#################################### +# Detached # +#################################### + + +@configurable +def make_rd_detached_muons( + name="rd_detached_muons_{hash}", + pt_min=250. * MeV, + p_min=3000. * MeV, + mipchi2dvprimary_min=3., #TBC + pid=F.require_all(F.ISMUON, F.PID_MU > 0.)): + """ + Return RD detached muons. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_muons, + pt_min=pt_min, + p_min=p_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +@configurable +def make_rd_detached_electrons( + name="rd_detached_electrons_{hash}", + pt_min=250. * MeV, + p_min=3000. * MeV, + mipchi2dvprimary_min=3., #TBC + pid=(F.PID_E > 0.)): + """ + Return RD detached electrons with brem recovery. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_electrons_with_brem, + pt_min=pt_min, + p_min=p_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +@configurable +def make_rd_detached_pions( + name="rd_detached_pions_{hash}", + p_min=2. * GeV, + pt_min=250. * MeV, + mipchi2dvprimary_min=4., #TBC + pid=(F.PID_K <= 1e-5)): + """ + Return RD detached pions. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_pions, + p_min=p_min, + pt_min=pt_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +@configurable +def make_rd_detached_kaons( + name="rd_detached_kaons_{hash}", + p_min=2. * GeV, + pt_min=250. * MeV, + mipchi2dvprimary_min=4., #TBC + pid=(F.PID_K > -2.)): + """ + Return RD detached kaons. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_kaons, + p_min=p_min, + pt_min=pt_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +@configurable +def make_rd_detached_protons( + name="rd_detached_protons_{hash}", + p_min=2. * GeV, + pt_min=250. * MeV, + mipchi2dvprimary_min=4., #TBC + pid=(F.PID_P > -2.)): + """ + Return RD detached protons. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_protons, + p_min=p_min, + pt_min=pt_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +# has_rich versions + + +@configurable +def make_rd_has_rich_detached_pions( + name="rd_has_rich_detached_pions_{hash}", + p_min=2. * GeV, + pt_min=250. * MeV, + mipchi2dvprimary_min=4., #TBC + pid=(F.PID_K <= 0.)): + """ + Return RD detached pions with hasRich. + """ + return make_filter_tracks( + name=name, + make_particles=make_has_rich_long_pions, + p_min=p_min, + pt_min=pt_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +@configurable +def make_rd_has_rich_detached_kaons( + name="rd_has_rich_detached_kaons_{hash}", + p_min=2. * GeV, + pt_min=250. * MeV, + mipchi2dvprimary_min=4., #TBC + pid=(F.PID_K > 0.)): + """ + Return RD detached kaons with hasRich. + """ + return make_filter_tracks( + name=name, + make_particles=make_has_rich_long_kaons, + p_min=p_min, + pt_min=pt_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +@configurable +def make_rd_has_rich_detached_protons( + name="rd_has_rich_detached_protons_{hash}", + p_min=8.5 * + GeV, #kaon RICH threshold below which we have no p-K separation + pt_min=250. * MeV, + mipchi2dvprimary_min=4., #TBC + pid=F.require_all(F.PID_P > 0., F.PID_P - F.PID_K > -2.)): + """ + Return RD detached protons with hasRich. + """ + return make_filter_tracks( + name=name, + make_particles=make_has_rich_long_protons, + p_min=p_min, + pt_min=pt_min, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pid=pid) + + +#################################### +# Prompt # +#################################### + + +@configurable +def make_rd_prompt_muons( + name="rd_prompt_muons_{hash}", + pt_min=250. * MeV, + p_min=3000. * MeV, + pid=F.require_all(F.PID_MU > 3.)): #F.ISMUON, F.PID_MU > 3. + """ + Return RD prompt muons. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_muons, + pt_min=pt_min, + p_min=p_min, + pid=pid) + + +@configurable +def make_rd_prompt_electrons(name="rd_prompt_electrons_{hash}", + pt_min=250. * MeV, + p_min=3000. * MeV, + pid=(F.PID_E > 6.)): + """ + Return RD prompt electrons with brem recovery. + """ + return make_filter_tracks( + name=name, + make_particles=make_long_electrons_with_brem, + pt_min=pt_min, + p_min=p_min, + pid=pid) + + +@configurable +def make_rd_prompt_pions(name="rd_prompt_pions_{hash}", pid=(F.PID_K < 0.)): + """ + Return RD prompt pions. + """ + return make_filter_tracks( + make_particles=make_has_rich_long_pions, name=name, pid=pid) + + +@configurable +def make_rd_prompt_pions_no_rich(name="rd_prompt_pions_{hash}", pid=None): + """ + Return RD prompt pions without RICH requirement. + """ + return make_filter_tracks( + make_particles=make_long_pions, name=name, pid=pid) + + +@configurable +def make_rd_prompt_kaons(name="rd_prompt_kaons_{hash}", pid=(F.PID_K > 0.)): + """ + Return RD prompt kaons. + """ + return make_filter_tracks( + make_particles=make_has_rich_long_kaons, name=name, pid=pid) + + +@configurable +def make_rd_prompt_protons(name="rd_prompt_protons_{hash}", + p_min=10. * GeV, + pid=(F.PID_P > 0.)): + """ + Return RD prompt protons. + """ + return make_filter_tracks( + make_particles=make_has_rich_long_protons, + name=name, + p_min=p_min, + pid=pid) + + +#################################### +# Downstream tracks # +#################################### + + +def make_rd_detached_down_pions( + name="rd_detached_down_pions_{hash}", + mipchi2dvprimary_min=4., #this does not work + pt_min=0. * MeV, + p_min=0. * GeV, + pid=None): + """ + Return RD downstream hadrons with pion mass hypothesis. + """ + return make_filter_tracks( + make_particles=make_down_pions, + name=name, + #mipchi2dvprimary_min=mipchi2dvprimary_min, + pt_min=pt_min, + p_min=pt_min, + pid=pid) + + +def make_rd_detached_down_kaons( + name="rd_detached_down_kaons_{hash}", + mipchi2dvprimary_min=4., #TBC + pt_min=0. * MeV, + p_min=0. * GeV, + pid=None): + """ + Return RD downstream hadrons with kaon mass hypothesis. + """ + return make_filter_tracks( + make_particles=make_down_kaons, + name=name, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pt_min=pt_min, + p_min=pt_min, + pid=pid) + + +def make_rd_detached_down_protons( + name="rd_detached_down_protons_{hash}", + mipchi2dvprimary_min=4., #TBC + pt_min=0. * MeV, + p_min=0. * GeV, + pid=None): + """ + Return RD downstream hadrons with proton mass hypothesis. + """ + return make_filter_tracks( + make_particles=make_down_protons, + name=name, + mipchi2dvprimary_min=mipchi2dvprimary_min, + pt_min=pt_min, + p_min=pt_min, + pid=pid) + + +################################### +# Neutral particles # +################################### + + +@configurable +def make_rd_photons(name="rd_photons_{hash}", + make_particles=make_photons, + IsPhoton_min=0.5, + IsNotH_min=0.3, + E19_min=0.2, + e_min=50. * MeV, + et_min=250. * MeV): + """For the time being just a preliminary selection while the neutrals calibration in progress""" + + code = F.require_all(F.PT > et_min, F.P > e_min, + F.IS_PHOTON > IsPhoton_min, F.IS_NOT_H > IsNotH_min, + F.CALO_NEUTRAL_1TO9_ENERGY_RATIO > E19_min) + return ParticleFilter(make_particles(), F.FILTER(code), name=name) + + +@configurable +def make_rd_resolved_pi0s( + name="rd_resolved_pi0s_{hash}", + make_particles=make_resolved_pi0s, + pt_min=250. * MeV, + is_photon_max=0.5, + is_not_h_min=0.5, + # photon_args={ + # 'ConfLevelCut': 0.1, + # 'PtCut': 250. * MeV + # }, +): + """For the time being just a dummy selection""" + + # code =F.require_all('PT > {pt_min}', 'P > {p_min}').format( + # pt_min=pt_min, p_min=p_min) + # + # return ParticleFilter( + # make_particles(photon_args=photon_args), Code=code, name=name) + code = F.require_all(F.PT > pt_min, F.IS_PHOTON < is_photon_max, + F.IS_NOT_H > is_not_h_min) + return ParticleFilter(make_particles(), F.FILTER(code)) + + +@configurable +def make_rd_merged_pi0s(name="rd_merged_pi0s_{hash}", + make_particles=make_merged_pi0s, + pt_min=250. * MeV, + cl_min=0.): + """For the time being just a dummy selection""" + + code = F.PT > pt_min + return ParticleFilter(make_particles(), F.FILTER(code), name=name) + + +#################################### +# V0 particles and alike # +#################################### +# they are in principle defined in the Hlt2 standard_particles, however there is no way to tune IPCHI2 cuts on their children with the current ThOr framework. + + +@configurable +def make_rd_ks0_lls( + name="rd_ks0_lls_{hash}", + make_pions=make_rd_detached_pions, + make_pvs=make_pvs, + mass_window_comb=50. * MeV, + mass_window=35. * MeV, + pi_p_min=2. * GeV, + pi_pt_min=0. * GeV, # has to be 0 !!! + pi_ipchi2_min=16., + pt_min=0 * MeV, + adocachi2cut=30., + bpvvdchi2_min=4., + bpvltime_min=1. * ps, + vchi2pdof_max=25.): + ''' + Build Long-Long KS0 candidates. Approximately corresponding to the Run2 + "StdVeryLooseKsLL" cuts. + ''' + + pions = make_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=None) # important to get rid of any PID cuts! + descriptor = 'KS0 -> pi+ pi-' + combination_code = F.require_all( + F.ABS_DELTA_MASS("KS0") < mass_window_comb, + F.MAXDOCACHI2CUT(adocachi2cut)) + pvs = make_pvs() + vertex_code = F.require_all( + F.ABS_DELTA_MASS("KS0") < mass_window, F.PT > pt_min, + F.CHI2DOF < vchi2pdof_max, + F.BPVLTIME(pvs) > bpvltime_min, + F.BPVFDCHI2(pvs) > bpvvdchi2_min) + return ParticleCombiner([pions, pions], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_ks0_dds( + name="rd_ks0_dds_{hash}", + make_pions=make_rd_detached_down_pions, + make_pvs=make_pvs, + mass_window_comb=80. * MeV, + mass_window=64. * MeV, + pi_p_min=2. * GeV, + pi_pt_min=0., # has to be 0 !!! + #pi_ipchi2_min=4, + adocachi2cut=30., + bpvvdchi2_min=4., + bpvltime_min=1. * ps, + vchi2pdof_max=25.): + ''' + Build Down-Down KS0 candidates. Approximately corresponding to the Run2 + "StdLooseKsDD" cuts. + ''' + + pions = make_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + #mipchi2dvprimary_min=pi_ipchi2_min, + pid=None) + descriptor = 'KS0 -> pi+ pi-' + combination_code = F.require_all( + F.ABS_DELTA_MASS("KS0") < mass_window_comb, + F.MAXDOCACHI2CUT(adocachi2cut)) + pvs = make_pvs() + vertex_code = F.require_all( + F.ABS_DELTA_MASS("KS0") < mass_window, F.CHI2DOF < vchi2pdof_max, + F.BPVLTIME(pvs) > bpvltime_min, + F.BPVFDCHI2(pvs) > bpvvdchi2_min) + return ParticleCombiner([pions, pions], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_lambda_lls( + name="rd_lambda_lls_{hash}", + make_protons=make_rd_detached_protons, + make_pions=make_rd_detached_pions, + make_pvs=make_pvs, + mass_window_comb=50. * MeV, + mass_window=35. * MeV, + lambda_pt_min=0. * MeV, + pi_p_min=2. * GeV, + p_p_min=2. * GeV, + p_pt_min=0., # recommended to be small + pi_pt_min=0., # has to be 0 !!! + pi_ipchi2_min=6., + p_ipchi2_min=16., + adocachi2cut=30., + bpvvdchi2_min=4., + bpvltime_min=1. * ps, + vchi2pdof_max=25.): + ''' + Build Long-Long Lambda candidates. Approximately corresponding to the Run2 + "StdVeryLooseLambdaLL" cuts. + ''' + + protons = make_protons( + p_min=p_p_min, + pt_min=p_pt_min, + mipchi2dvprimary_min=p_ipchi2_min, + pid=None) # important to get rid of any PID cuts! + pions = make_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=None) + descriptor = '[Lambda0 -> p+ pi-]cc' + combination_code = F.require_all( + F.ABS_DELTA_MASS("Lambda0") < mass_window_comb, + F.MAXDOCACHI2CUT(adocachi2cut)) + pvs = make_pvs() + vertex_code = F.require_all( + F.ABS_DELTA_MASS("Lambda0") < mass_window, F.CHI2DOF < vchi2pdof_max, + F.BPVLTIME(pvs) > bpvltime_min, + F.BPVFDCHI2(pvs) > bpvvdchi2_min, F.PT > lambda_pt_min) + return ParticleCombiner([protons, pions], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_lambda_dds( + name="rd_lambda_dds_{hash}", + make_protons=make_rd_detached_down_protons, + make_pions=make_rd_detached_down_pions, + make_pvs=make_pvs, + mass_window_comb=80. * MeV, + mass_window=64. * MeV, + lambda_pt_min=0. * MeV, + pi_p_min=2. * GeV, + p_p_min=2. * GeV, + p_pt_min=0., # recommended to be small + pi_pt_min=0., # has to be 0 !!! + pi_ipchi2_min=6, + p_ipchi2_min=16, + adocachi2cut=30., + bpvvdchi2_min=4., + bpvltime_min=1. * ps, + vchi2pdof_max=25., +): + ''' + Build Down-Down Lambda candidates. Approximately corresponding to the Run2 + "StdLooseLambdaDD" cuts. + ''' + + protons = make_protons( + p_min=p_p_min, + pt_min=p_pt_min, + mipchi2dvprimary_min=p_ipchi2_min, + pid=None) # important to get rid of any PID cuts! + pions = make_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=None) + descriptor = '[Lambda0 -> p+ pi-]cc' + combination_code = F.require_all( + F.ABS_DELTA_MASS("Lambda0") < mass_window_comb, + F.MAXDOCACHI2CUT(adocachi2cut)) + pvs = make_pvs() + vertex_code = F.require_all( + F.ABS_DELTA_MASS("Lambda0") < mass_window, F.CHI2DOF < vchi2pdof_max, + F.BPVLTIME(pvs) > bpvltime_min, + F.BPVFDCHI2(pvs) > bpvvdchi2_min, F.PT > lambda_pt_min) + return ParticleCombiner([protons, pions], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +#################################### +# 2-body hadron combinations # +#################################### + + +@configurable +def make_Kstps_with_pi0s( + name="Kstp_Maker_resolved_Pi0s_{hash}", + min_ipchi2_k=4., + Kstp_PT=0., + Kstp_max_vtxchi2=36., + PIDK_K_min=0., + pt_K_min=250. * MeV, + p_K_min=1_000. * MeV, + pt_pi_min=250. * MeV, + am_min=600. * MeV, + am_max=1_200. * MeV, + low_factor=0.5, + high_factor=1.5, + pi0_type="resolved", # either "resolved" or "merged". +): + + ### make K*+ -> K+ pi0 candidate ### + + kaons = make_rd_detached_kaons( + mipchi2dvprimary_min=min_ipchi2_k, + pid=(F.PID_K > PIDK_K_min), + pt_min=pt_K_min, + p_min=p_K_min) + + if pi0_type == "resolved": + pions = make_rd_resolved_pi0s(pt_min=pt_pi_min) + + elif pi0_type == "merged": + pions = make_rd_merged_pi0s(pt_min=pt_pi_min) + + else: + raise Exception( + f"Error: argument pi0_type was {pi0_type}, pi0_type argument can be either: 'resolved' or 'merged'" + ) + + combination_code = F.require_all( + in_range(low_factor * am_min, F.MASS, high_factor * am_max), + F.SUM(F.PT) > Kstp_PT * MeV, + ) + + vertex_code = F.require_all(in_range(am_min, F.MASS, am_max)) + + return ParticleCombiner([kaons, pions], + DecayDescriptor="[K*(892)+ -> K+ pi0]cc", + CombinationCut=combination_code, + name=name, + ParticleCombiner="ParticleAdder", + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_kstar0s( + name="rd_detached_kstar0s_{hash}", + make_rd_detached_pions=make_rd_has_rich_detached_pions, + make_rd_detached_kaons=make_rd_has_rich_detached_kaons, + make_pvs=make_pvs, + am_min=0 * MeV, + am_max=2600. * MeV, + pi_p_min=2. * GeV, + pi_pt_min=250. * MeV, + pi_ipchi2_min=9., + # if the RICH can not distinguish between kaons and pions then + # the PID will be set to zero, and most often these will correspond + # to real pions + pi_pid=F.PID_K < 1e-5, + k_p_min=2. * GeV, + k_pt_min=250. * MeV, + k_ipchi2_min=9., + k_pid=(F.PID_K > 2.), + kstar0_pt_min=400. * MeV, + adocachi2cut=30., + maxdoca=500 * micrometer, + vchi2pdof_max=16., + bpvipchi2_min=None, + same_sign=False): + ''' + Build Kstar0 candidates. Approximately corresponding to the Run2 + "StdVeryLooseDetachedKstar" cuts. + ''' + + pions = make_rd_detached_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=pi_pid) + kaons = make_rd_detached_kaons( + p_min=k_p_min, + pt_min=k_pt_min, + mipchi2dvprimary_min=k_ipchi2_min, + pid=k_pid) + descriptor = '[K*(892)0 -> K+ pi-]cc' + if same_sign: descriptor = '[K*(892)0 -> K+ pi+]cc' + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.MAXSDOCACHI2CUT(adocachi2cut), + F.MAXSDOCACUT(maxdoca)) + vertex_code = F.require_all(F.CHI2DOF < vchi2pdof_max, + F.PT > kstar0_pt_min) + + if bpvipchi2_min is not None: + pvs = make_pvs() + vertex_code &= (F.BPVIPCHI2(pvs) > bpvipchi2_min) + + return ParticleCombiner([kaons, pions], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_phis( + name="rd_detached_phis_{hash}", + make_rd_detached_kaons=make_rd_has_rich_detached_kaons, + make_pvs=make_pvs, + am_min=950. * MeV, #the real min is the di-kaon threshold + am_max=1100. * MeV, + k_p_min=2. * GeV, + k_pt_min=100. * MeV, + k_ipchi2_min=4., + k_pid=(F.PID_K > 0.), + phi_pt_min=400. * MeV, + adocachi2cut=30., + vchi2pdof_max=25.): + ''' + Build phi(1020) candidates. Approximately corresponding to the Run2 + "StdLooseDetachedPhi2KK" cuts. + ''' + + kaons = make_rd_detached_kaons( + p_min=k_p_min, + pt_min=k_pt_min, + mipchi2dvprimary_min=k_ipchi2_min, + pid=k_pid) + descriptor = 'phi(1020) -> K+ K-' + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.MAXSDOCACHI2CUT(adocachi2cut)) + #pvs = make_pvs() + vertex_code = F.require_all(F.CHI2DOF < vchi2pdof_max, F.PT > phi_pt_min) + return ParticleCombiner([kaons, kaons], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_rho0( + name="rd_detached_rho0_{hash}", + make_rd_detached_pions=make_rd_has_rich_detached_pions, + pi_pt_min=250. * MeV, + pi_p_min=0. * MeV, + pi_ipchi2_min=9.0, + # if the RICH can not distinguish between kaons and pions then + # the PID will be set to zero, and most often these will correspond + # to real pions + pi_pid=F.PID_K < 1e-5, + pt_min=600. * MeV, + am_min=0. * MeV, + am_max=2600. * MeV, + adocachi2cut=10., + maxdocacut=500 * micrometer, + vchi2pdof_max=16., +): + ''' + Build pi+pi- candidates. Approximately corresponding to the Run2 + "StdLooseRho0" cuts but more flexible. + ''' + pions = make_rd_detached_pions( + pt_min=pi_pt_min, + p_min=pi_p_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=pi_pid, + ) + DecayDescriptor = 'rho(770)0 -> pi+ pi-' + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.PT > pt_min, + F.MAXSDOCACHI2CUT(adocachi2cut), F.MAXSDOCACUT(maxdocacut)) + + vertex_code = (F.CHI2DOF < vchi2pdof_max) + return ParticleCombiner([pions, pions], + name=name, + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_etaprime( + name='rd_detached_etaprime_{hash}', + make_rd_detached_pions=make_rd_has_rich_detached_pions, + pi_p_min=1. * GeV, + pi_pt_min=150. * MeV, + pi_ipchi2_min=4.0, + pi_pid=(F.PID_K < 2.), + pt_min=500. * MeV, + am_min=700. * MeV, + am_max=1300. * MeV, + am12_min=500 * MeV, + am12_max=1200 * MeV, + e_gamma_min=100 * MeV, + et_gamma_min=400 * GeV, + adocachi2_cut=10.): + """ + Build pi+pi-gamma candidates. + """ + pions = make_rd_detached_pions( + p_min=pi_pt_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=pi_pid) + photons = make_rd_photons(et_min=et_gamma_min, e_min=e_gamma_min) + descriptor = '[eta_prime -> pi+ pi- gamma]cc' + combination_code = in_range(am_min, F.MASS, am_max) + combination12_code = in_range(am12_min, F.MASS, am12_max) + vertex_code = F.require_all(F.PT > pt_min) + + return ParticleCombiner( + Inputs=[pions, pions, photons], + ParticleCombiner="ParticleAdder", + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + Combination12Cut=combination12_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_k1(name='rd_detached_k1_{hash}', + make_rd_detached_pions=make_rd_has_rich_detached_pions, + make_rd_detached_kaons=make_rd_has_rich_detached_kaons, + pi_p_min=1. * GeV, + pi_pt_min=150. * MeV, + pi_ipchi2_min=9.0, + pi_pid=(F.PID_K < 0.), + k_p_min=1. * GeV, + k_pt_min=150. * MeV, + k_ipchi2_min=9.0, + k_pid=(F.PID_K > -2.), + pt_min=500. * MeV, + am_kpi_max=1450 * MeV, + am_2pi_max=1450 * MeV, + am_min=0. * MeV, + am_max=4200. * MeV, + adocachi2_cut=10., + vchi2pdof_max=16): + """ + Build K1(1270)->Kpipi candidates + """ + pions = make_rd_detached_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=pi_pid) + kaons = make_rd_detached_kaons( + p_min=k_p_min, + pt_min=k_pt_min, + mipchi2dvprimary_min=k_ipchi2_min, + pid=k_pid) + descriptor = '[K_1(1270)+ -> K+ pi+ pi-]cc' + combination12_code = (F.MAXSDOCACHI2CUT(adocachi2_cut)) + combination_code = F.require_all( + F.SUBCOMB(Functor=(F.MASS < am_kpi_max), Indices=[1, 3]), + F.SUBCOMB(Functor=(F.MASS < am_2pi_max), Indices=[2, 3]), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_cut), Indices=[2, 3]), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_cut), Indices=[1, 3]), + in_range(am_min, F.MASS, am_max), F.MAXSDOCACHI2CUT(adocachi2_cut)) + vertex_code = F.require_all(F.PT > pt_min, F.CHI2DOF < vchi2pdof_max) + + return ParticleCombiner( + Inputs=[kaons, pions, pions], + name=name, + DecayDescriptor=descriptor, + Combination12Cut=combination12_code, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +#################################### +# Dileptons # +#################################### + + +@configurable +def make_prompt_dielectron_with_brem( + name="prompt_dielectron_with_brem_builder_{hash}", + electron_maker=make_long_electrons_no_brem, + opposite_sign=True, + PIDe_min=5., + pt_e=0.25 * GeV, + trghostprob=0.3, + dielectron_ID="J/psi(1S)", + pt_diE=0. * MeV, + m_diE_min=0. * MeV, + m_diE_max=6000. * MeV, + vchi2pdof_max=10.): + """Make prompt Jpsi -> e+ e- or [Jpsi -> e+ e+ ]cc candidates adding bremsstrahlung correction to the + electrons. The selection follows make_detached_dielectron_with_brem but without displacement cuts. + """ + #pvs = make_pvs() + particles = electron_maker() + + code_e = F.require_all( + F.PID_E > PIDe_min, + F.PT > pt_e, + #F.GHOSTPROB < trghostprob # <- removed for the early data taking in 2022 + ) + + prompt_e = ParticleFilter( + particles, F.FILTER(code_e), name=name + "_electron_{hash}") + prompt_dielectron_with_brem = _make_dielectron_with_brem( + prompt_e, + pt_diE=pt_diE, + m_diE_min=m_diE_min, + m_diE_max=m_diE_max, + m_diE_ID=dielectron_ID, + opposite_sign=opposite_sign) + + code_dielectron = F.require_all(F.CHI2DOF < vchi2pdof_max) + return ParticleFilter( + prompt_dielectron_with_brem, + F.FILTER(code_dielectron), + name=name + "_{hash}") + + +@configurable +def make_rd_prompt_dielectrons( + name="rd_prompt_dielectrons_{hash}", + # opposite_sign=True, + same_sign=False, + PIDe_min=5., + pt_e_min=0.25 * GeV, + trghostprob=0.25, + parent_id="omega(782)", + min_dilepton_pt=0 * MeV, + min_dilepton_mass=0 * MeV, + max_dilepton_mass=12000 * MeV, + max_vchi2ndof=9.): + """ + Make the prompt dielectron pair, opposite-sign or same-sign. + """ + #pvs = make_pvs() + dileptons = make_prompt_dielectron_with_brem( + opposite_sign=not same_sign, + PIDe_min=PIDe_min, + pt_e=pt_e_min, + dielectron_ID=parent_id, + pt_diE=min_dilepton_pt, + m_diE_min=min_dilepton_mass, + m_diE_max=max_dilepton_mass, + vchi2pdof_max=max_vchi2ndof) + code = F.require_all( + in_range(min_dilepton_mass, F.MASS, max_dilepton_mass), + F.PT > min_dilepton_pt) + return ParticleFilter(dileptons, F.FILTER(code), name=name) + + +@configurable +def make_rd_prompt_dimuons( + name="rd_prompt_dimuons_{hash}", + parent_id='rho(770)0', + pt_dimuon_min=0. * MeV, + pt_muon_min=250. * MeV, + p_muon_min=3000. * MeV, + pid=F.require_all(F.PID_MU > 3.), #F.ISMUON, F.PID_MU > 3. + pid_best=6, + pt_best=0.5 * GeV, + p_best=5. * GeV, + adocachi2cut_max=30., + vchi2pdof_max=16., + am_min=0. * MeV, + am_max=12000. * MeV, + same_sign=False): + """ + Make the prompt dimuon, opposite-sign or same-sign. + """ + muons = make_rd_prompt_muons(pt_min=pt_muon_min, p_min=p_muon_min, pid=pid) + + DecayDescriptor = f'{parent_id} -> mu+ mu-' + if same_sign: DecayDescriptor = f'[{parent_id} -> mu+ mu+]cc' + + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.PT > pt_dimuon_min, + F.MAX(F.PT) > pt_best, + F.MAX(F.P) > p_best, + F.MAX(F.PID_MU) > pid_best, F.MAXSDOCACHI2CUT(adocachi2cut_max)) + #pvs = make_pvs() + vertex_code = F.require_all(F.CHI2DOF < vchi2pdof_max) + return ParticleCombiner([muons, muons], + name=name + "_combiner_{hash}", + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_prompt_mue( + name="rd_prompt_mue_{hash}", + parent_id='f_0(980)', + pt_dilepton_min=0. * MeV, + pt_muon_min=300. * MeV, + p_muon_min=3000. * MeV, + pt_electron_min=300. * MeV, + p_electron_min=3000. * MeV, + pid_muon=F.require_all(F.PID_MU > 3.), #F.ISMUON, F.PID_MU > 3. + pid_electron=(F.PID_E > 5.), + pt_best=0.5 * GeV, + p_best=5. * GeV, + adocachi2cut_max=30., + vchi2pdof_max=16., + am_min=0. * MeV, + am_max=12000. * MeV, + same_sign=False): + """ + Make the prompt dimuon, opposite-sign or same-sign. + """ + muons = make_rd_prompt_muons( + pt_min=pt_muon_min, p_min=p_muon_min, pid=pid_muon) + + electrons = make_rd_prompt_electrons( + # name="rd_prompt_electrons_for" + name, + pt_min=pt_electron_min, + p_min=p_electron_min, + pid=pid_electron) + + DecayDescriptor = f'{parent_id} -> mu- e+' + if same_sign: DecayDescriptor = f'[{parent_id} -> mu+ e+]cc' + + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.PT > pt_dilepton_min, + F.MAX(F.PT) > pt_best, + F.MAX(F.P) > p_best, F.MAXSDOCACHI2CUT(adocachi2cut_max)) + #pvs = make_pvs() + vertex_code = F.require_all(F.CHI2DOF < vchi2pdof_max) + return ParticleCombiner([muons, electrons], + name=name + "_combiner_{hash}", + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_dimuon(name="rd_detached_dimuon_{hash}", + parent_id='J/psi(1S)', + pt_dimuon_min=0. * MeV, + pt_muon_min=300. * MeV, + p_muon_min=3000. * MeV, + ipchi2_muon_min=9., + pidmu_muon_min=3., + adocachi2cut_max=30., + bpvvdchi2_min=30., + vchi2pdof_max=30., + am_min=0. * MeV, + am_max=6000. * MeV, + same_sign=False): + """ + Make the detached dimuon, opposite-sign or same-sign. + """ + muons = make_rd_detached_muons( + name="rd_detached_muons_{hash}", + pt_min=pt_muon_min, + p_min=p_muon_min, + mipchi2dvprimary_min=ipchi2_muon_min, + pid=F.require_all(F.ISMUON, F.PID_MU > pidmu_muon_min)) + + DecayDescriptor = f'{parent_id} -> mu+ mu-' + if same_sign: DecayDescriptor = f'[{parent_id} -> mu+ mu+]cc' + + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.PT > pt_dimuon_min, + F.MAXDOCACHI2CUT(adocachi2cut_max)) + pvs = make_pvs() + vertex_code = F.require_all(F.CHI2DOF < vchi2pdof_max, + F.BPVFDCHI2(pvs) > bpvvdchi2_min) + return ParticleCombiner([muons, muons], + name=name, + DecayDescriptor=DecayDescriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_dielectron(name="rd_detached_dielectron_{hash}", + pid_e_min=2., + pt_e_min=0.25 * GeV, + p_e_min=0. * GeV, + ipchi2_e_min=9., + parent_id="J/psi(1S)", + opposite_sign=True, + pt_diE_min=0. * MeV, + adocachi2cut_max=30., + bpvvdchi2_min=30., + vfaspfchi2ndof_max=10., + am_min=0. * MeV, + am_max=6000. * MeV, + with_brem=True, + with_upstream=False, + only_LU_for_upstream=True): + """ + Make the detached e+e- pair with/without the proper bremsstrahlung correction handling. + """ + electron_maker = make_long_and_upstream_electrons_no_brem if with_upstream else make_long_electrons_no_brem + dielectrons = None + + # only allow LL or LU combinations if asked (UU adds very little to e.g. J/psi mode) + code = (F.CHILD(1, F.TRACKISLONG @ F.TRACK) + | F.CHILD(2, F.TRACKISLONG @ F.TRACK) + ) if with_upstream and only_LU_for_upstream else None + + if with_brem: + dielectrons = make_detached_dielectron_with_brem( + electron_maker=electron_maker, + opposite_sign=opposite_sign, + PIDe_min=pid_e_min, + pt_e=pt_e_min, + p_e=p_e_min, + minipchi2=ipchi2_e_min, + dielectron_ID=parent_id, + pt_diE=pt_diE_min, + m_diE_min=am_min, + m_diE_max=am_max, + adocachi2cut=adocachi2cut_max, + bpvvdchi2=bpvvdchi2_min, + vfaspfchi2ndof=vfaspfchi2ndof_max) + else: + dielectrons = make_detached_dielectron( + electron_maker=electron_maker, + opposite_sign=opposite_sign, + dilepton_ID=parent_id, + pid_e=pid_e_min, + pt_e=pt_e_min, + minipchi2=ipchi2_e_min, + adocachi2cut=adocachi2cut_max, + bpvvdchi2=bpvvdchi2_min, + vfaspfchi2ndof=vfaspfchi2ndof_max) + + code = F.require_all( + code if code is not None else F.ALL, + F.PT > pt_diE_min, + F.MASS > am_min, + F.MASS < am_max, + ) + return ParticleFilter( + dielectrons, F.FILTER(code), + name=name) if code is not None else dielectrons + + +@configurable +def make_rd_detached_mue( + name="rd_detached_mue_{hash}", + min_dilepton_mass=0. * MeV, + max_dilepton_mass=6000. * MeV, + parent_id='J/psi(1S)', + min_probnn_mu=None, # DISABLED per Moore issue 759 + min_PIDmu=0., + IsMuon=False, + min_PIDe=2., + min_pt_e=0.25 * GeV, + min_pt_mu=0.25 * GeV, + min_bpvvdchi2=30., + max_vchi2ndof=10., + same_sign=False): + """ + Make the detached muon-electron pair, opposite-sign or same-sign. + """ + dileptons = make_detached_mue_with_brem( + dilepton_ID=parent_id, + min_probnn_mu=min_probnn_mu, + min_PIDmu=min_PIDmu, + IsMuon=False, + min_PIDe=min_PIDe, + opposite_sign=not same_sign, + min_pt_e=min_pt_e, + min_pt_mu=min_pt_mu, + min_bpvvdchi2=min_bpvvdchi2, + max_vchi2ndof=max_vchi2ndof) + code = F.require_all( + in_range(min_dilepton_mass, F.MASS, max_dilepton_mass)) + return ParticleFilter(dileptons, F.FILTER(code), name=name) + + +#################################### +# Tau builders # +#################################### + + +@configurable +def make_rd_tauons_hadronic_decay( + name="rd_tauons_hadronic_decay_{hash}", + make_pions=make_rd_detached_pions, + descriptor="[tau+ -> pi- pi+ pi+]cc", + pi_pt_min=150. * MeV, + pi_p_min=1000. * MeV, + pi_ipchi2_min=4.0, + pi_pid=(F.PID_K < 8.), + best_pi_pt_min=300. * MeV, + best_pi_ipchi2_min=5., + pt_max=300. * MeV, + am_min=400. * MeV, + am_max=3500. * MeV, + make_pvs=make_pvs, + # adoca_max=0.15 * mm, + adocachi2_max=6., + am_2pi_min=0. * MeV, + am_2pi_max=1670. * MeV, + vchi2pdof_max=25., + bpvdira_min=0.99, +): + ''' + Build tau->3pi candidates. Approximately corresponding to the Run2 + "StdLooseDetachedTau" cuts. + ''' + + pions = make_pions( + pt_min=pi_pt_min, + p_min=pi_p_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=pi_pid) + + combination12_code = F.require_all( + in_range(am_2pi_min, F.MASS, am_2pi_max), + F.MAXSDOCACHI2CUT(adocachi2_max), + ) + + pvs = make_pvs() + combination_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.SUBCOMB( + Functor=in_range(am_2pi_min, F.MASS, am_2pi_max), Indices=(1, 3)), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_max), Indices=(2, 3)), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_max), Indices=(1, 3)), + F.SUM(F.PT > best_pi_pt_min) >= 1, + F.SUM(F.MINIPCHI2(pvs) > best_pi_ipchi2_min) >= 1, + ) + + vertex_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.CHI2DOF < vchi2pdof_max, + F.BPVDIRA(pvs) > bpvdira_min, + ) + return ParticleCombiner([pions, pions, pions], + name=name, + DecayDescriptor=descriptor, + Combination12Cut=combination12_code, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +#################################### +# Dihadron # +#################################### + + +@configurable +def make_rd_detached_dihadron(name="make_rd_detached_dihadrons_{hash}", + parent_id='B_s0', + same_sign=False, + pid=None, + min_pt_track=500 * MeV, + min_p_track=3000 * MeV, + min_ipchi2_track=25., + max_adocachi2=30., + max_vchi2ndof=9.0, + am_min=4500 * MeV, + am_max=6000 * MeV, + min_bpvvdchi2=225., + max_ipchi2_dihadron=25., + min_pt_dihadron=1000 * MeV, + min_DIRA_dihadron=0.999): + """ + Make the detached dihadron, opposite-sign or same-sign. + """ + descriptor = f'{parent_id} -> pi+ pi-' + if same_sign: descriptor = f'[{parent_id} -> pi+ pi+]cc' + pvs = make_pvs() + pions = make_rd_detached_pions( + mipchi2dvprimary_min=min_ipchi2_track, + pt_min=min_pt_track, + p_min=min_p_track, + pid=pid) + combination_code = F.MAXSDOCACHI2CUT(max_adocachi2) + vertex_code = F.require_all( + in_range(am_min, F.MASS, am_max), F.CHI2DOF < max_vchi2ndof, + F.BPVFDCHI2(pvs) > min_bpvvdchi2, + F.BPVIPCHI2(pvs) < max_ipchi2_dihadron, + F.BPVDIRA(pvs) > min_DIRA_dihadron, F.PT > min_pt_dihadron) + return ParticleCombiner( + Inputs=[pions, pions], + name=name, + DecayDescriptor=descriptor, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +#################################### +# Trihadron # +#################################### + + +@configurable +def make_rd_detached_K1( + name="make_rd_detached_K_1_{hash}", + Descriptor="[K_1(1270)+ -> K+ pi- pi+]cc", + adocachi2_max=25., + am_min=500. * MeV, + am_max=4200. * MeV, + low_factor=0.5, + high_factor=1.5, + pi_p_min=1_000. * MeV, + pi_pt_min=400. * MeV, + pi_ipchi2_min=25., + pi_PIDK_max=-2., + K_p_min=1_000. * MeV, + K_pt_min=400. * MeV, + K_ipchi2_min=25., + K_PIDK_min=2., + K_1_min_bpvfdchi2=0., + K_1_pt_min=0. * MeV, + vchi2pdof_max=25., + K_1_min_DIRA=None, + bpvipchi2_min=9., +): + """ + make K_1(1270) -> K+ pi+ pi- + """ + + kaons = make_rd_detached_kaons( + p_min=K_p_min, + pt_min=K_pt_min, + mipchi2dvprimary_min=K_ipchi2_min, + pid=(F.PID_K > K_PIDK_min), + ) + pions = make_rd_detached_pions( + p_min=pi_p_min, + pt_min=pi_pt_min, + mipchi2dvprimary_min=pi_ipchi2_min, + pid=(F.PID_K <= pi_PIDK_max), + ) + + two_body_combination_code = F.require_all( + in_range(low_factor * am_min, F.MASS, high_factor * am_max), + F.MAXSDOCACHI2CUT(adocachi2_max), + ) + + combination_code = F.require_all( + in_range(low_factor * am_min, F.MASS, high_factor * am_max), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_max), Indices=[2, 3]), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_max), Indices=[1, 3]), + ) + + pvs = make_pvs() + vertex_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.PT > K_1_pt_min, + F.CHI2DOF < vchi2pdof_max, + F.BPVFDCHI2(pvs) > K_1_min_bpvfdchi2, + F.BPVIPCHI2(pvs) > bpvipchi2_min, + ) + + if K_1_min_DIRA is not None: + vertex_code &= (F.BPVDIRA(pvs) > K_1_min_DIRA) + + return ParticleCombiner([kaons, pions, pions], + name=name, + DecayDescriptor=Descriptor, + Combination12Cut=two_body_combination_code, + CombinationCut=combination_code, + CompositeCut=vertex_code) + + +@configurable +def make_rd_detached_K2( + name="make_rd_detached_K_2_{hash}", + Descriptor="[K_2(1770)+ -> K+ K+ K-]cc", + adocachi2_max=16., + maxdoca=300 * micrometer, + am_min=0. * MeV, + am_max=4200. * MeV, + low_factor=0.8, + high_factor=1.2, + K_p_min=2_000. * MeV, + K_pt_min=400. * MeV, + K_ipchi2_min=9., + K_PIDK=(F.PID_K > 5.), + K_2_min_bpvfdchi2=0., + K_2_pt_min=0. * MeV, + vchi2pdof_max=12., + K_2_min_DIRA=None, + bpvipchi2_min=9., +): + """ + make K_2(1770) -> K+ K+ K- + """ + + kaons = make_rd_detached_kaons( + p_min=K_p_min, + pt_min=K_pt_min, + mipchi2dvprimary_min=K_ipchi2_min, + pid=K_PIDK, + ) + + two_body_combination_code = F.require_all( + in_range(low_factor * am_min, F.MASS, high_factor * am_max), + F.MAXSDOCACHI2CUT(adocachi2_max), F.MAXSDOCACUT(maxdoca)) + + combination_code = F.require_all( + in_range(low_factor * am_min, F.MASS, high_factor * am_max), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_max), Indices=[2, 3]), + F.SUBCOMB(Functor=F.MAXSDOCACHI2CUT(adocachi2_max), Indices=[1, 3]), + ) + + pvs = make_pvs() + vertex_code = F.require_all( + in_range(am_min, F.MASS, am_max), + F.PT > K_2_pt_min, + F.CHI2DOF < vchi2pdof_max, + F.BPVFDCHI2(pvs) > K_2_min_bpvfdchi2, + F.BPVIPCHI2(pvs) > bpvipchi2_min, + ) + + if K_2_min_DIRA is not None: + vertex_code &= (F.BPVDIRA(pvs) > K_2_min_DIRA) + + return ParticleCombiner([kaons, kaons, kaons], + name=name, + DecayDescriptor=Descriptor, + Combination12Cut=two_body_combination_code, + CombinationCut=combination_code, + CompositeCut=vertex_code) diff --git a/rd_ap_2024/tupling/template.py b/rd_ap_2024/tupling/template.py new file mode 100644 index 0000000000000000000000000000000000000000..e835fbdc16b8c5ea8671f89af9517029e228711a --- /dev/null +++ b/rd_ap_2024/tupling/template.py @@ -0,0 +1,150 @@ + +from rd_ap_2024.utils.log_store import LogStore +from rd_ap_2024.tupling.Config import Config +from rd_ap_2024.tupling.variables.rd_stream_tupling_functions import ( + make_composite_variables, + make_basic_variables, + make_hlt_event_variables, + make_track_variables, + Funtuple_with_filter, + make_intermediate_resonances_variables, + make_truth_variables, + make_variables_with_swapped_mass_hypothesis +) + +from rd_ap_2024.tupling.variables.inclusive_detached_dilepton_mvas import( + #dimuons + InclDetDimuon_MVA, + InclDetDimuon_ThreeBody_MVA, + InclDetDimuon_FourBody_MVA, + InclDetDimuon_neutral_MVA, + #dielectrons + InclDetDielectron_MVA, + InclDetDielectron_ThreeBody_MVA, + InclDetDielectron_FourBody_MVA, + InclDetDielectron_neutral_MVA, + #di electron/muon + InclDetElectronMuon_MVA, + InclDetElectronMuon_ThreeBody_MVA, + InclDetElectronMuon_FourBody_MVA, + InclDetElectronMuon_neutral_MVA +) + +from rd_ap_2024.tupling.variables.tupling_dtf import ( + make_dtf_variables_v2, +) +from DaVinciTools import SubstitutePID + + +from rd_ap_2024.tupling.variables.rd_stream_isolation_functions import ( + make_Isolation_variables +) + +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) +import Functors as F +import FunTuple.functorcollections as FC +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +from PyConf.Algorithms import AdvancedCloneKiller, Run2SSPionTagger +from GaudiKernel.SystemOfUnits import GeV +from Hlt2Conf.algorithms_thor import ParticleFilter +from Hlt2Conf.standard_particles import ( # type: ignore[import] + make_long_pions, + make_long_kaons, + make_long_muons, + standard_protoparticle_filter, +) +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +from DaVinciMCTools import MCTruthAndBkgCat +from FunTuple.functorcollections import SelectionInfo +from DecayTreeFitter import DecayTreeFitter +# specific for the B2OC SigmaNet +import Functors.math as fmath + + +log=LogStore.add_logger('rd_ap_2024:tupling.template') + +def bind_string(name): + def decorator(func): + func.name = name + return func + return decorator + + +# Lines from "TEMPLATE" module tupling here +# b_to_xll_hlt2.py tupling lines +# Algorithms for those Lines covered : +# - Hlt2RD_BToHH_Incl +# - Hlt2RD_BToMuMu +# - Hlt2RD_BToEE +# - Hlt2RD_BToMuMuGamma [ not yet in ] +# - Hlt2RD_BToEEGamma [ not yet in ] +# - Hlt2RD_BToMuEGamma [ not yet in ] + + + +################### +# B0 -> H+H- Line tupling algorithm +# https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r7/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_ll_hlt2.py?ref_type=tags#L153 +################### +@bind_string("MYLINE") +def MYLINE(options:Options, config : Config) : + # extra_outputs=parent_isolation_output("B", dihadrons), in lines allow to do isolation + LINE_NAME = "MYLINE" + logger.debug(f"--------- Will tuple {LINE_NAME} ----------------") + if config.isTurbo() or config.isMC(): + LINE_DATA = get_particles(f"/Event/HLT2/{LINE_NAME}/Particles") + elif config.isFull() or config.isTurCal(): + LINE_DATA = get_particles(f"/Event/Spruce/{LINE_NAME}/Particles") + + MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + V2_PVS = get_pvs() + DECAY_DESCRIPTOR = 'MYDECAY' + HEAD = "HEAD_PARTICLE_NAME" + FIELDS = { + "B" : "DECDESCRIPTOR", + # .... + } + VARIABLES = { + "B" : None , #list of functor tuples + # "...": (les(options, data=LINE_DATA) ), + #"ALL": make_variables_with_swapped_mass_hypothesis(options, substitution_dict, v2_pvs), + } + + # FINE OR CRASH + assert( sorted( VARIABLES.keys()) == sorted( FIELDS.keys())), f"Check VARIABLES and FIELDS keys of line {LINE_NAME}" + assert len(FIELDS.values()) == len(set(FIELDS.values())), f"Check decay descriptors in FIELDS of line {LINE_NAME} for correctness" + # define FunTuple instance + return Funtuple_with_filter( + options =options, + line_name = LINE_NAME, + fields = FIELDS, + variables = VARIABLES, + inputs = LINE_DATA, + name= f"{LINE_NAME}" , + tuple_name = "DecayTree", + event_variables=make_hlt_event_variables(options, LINE_NAME), + ) + +######################################################################### +######################################################################### +######################################################################### +TUPLES_ALG_BINDING = {} +# Create a copy of the globals dictionary +globals_copy = dict(globals()) +# Iterate over the copy to avoid modifying the globals dictionary +for name, obj in globals_copy.items(): + if callable(obj) and hasattr(obj, 'name'): + if obj.name not in TUPLES_ALG_BINDING : + TUPLES_ALG_BINDING[obj.name] = obj +for k in TUPLES_ALG_BINDING.keys() : + logger.debug(f"{k} can be bound to its own function, all the rest no. Bounded to {TUPLES_ALG_BINDING[k]}") +######################################################################### +######################################################################### +######################################################################### diff --git a/rd_ap_2024/tupling/variables/flavour_tagging_variables.py b/rd_ap_2024/tupling/variables/flavour_tagging_variables.py new file mode 100644 index 0000000000000000000000000000000000000000..148af42df00afa193296b27b4f57c978bbcebe08 --- /dev/null +++ b/rd_ap_2024/tupling/variables/flavour_tagging_variables.py @@ -0,0 +1,113 @@ +# for debugging purpose +ENABLE_FT = True + +from rd_ap_2024.utils.log_store import LogStore +from PyConf.components import force_location +from Gaudi.Configuration import INFO +import Functors as F +from Functors.math import log +from PyConf.dataflow import DataHandle # type: ignore[import] +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) +from DecayTreeFitter import DecayTreeFitter +from FunTuple import FunctorCollection + +# check here, for the DV version in use what can be imported / modified +# https://gitlab.cern.ch/lhcb/DaVinci/-/blob/v64r4/Phys/FunTuple/python/FunTuple/functorcollections.py?ref_type=tags#L1281 +# +from FunTuple.functorcollections import ( + Kinematics, + SelectionInfo, + MCVertexInfo, + MCKinematics, + MCPromptDecay, + MCHierarchy, + MCPromptDecay, + MCReconstructed, + MCReconstructible, + MCPrimaries, + MCPrimaryVertexInfo, + EventInfo, + ParticleID, + ChargedCaloInfo, + NeutralCaloInfo, + VertexIsolation, + ConeIsolation, + ParticleIsolation, + DecayTreeFitterResults, + ParticlePVInfo, + HltTisTos, + LHCInfo +) +from FunTuple import FunTuple_Particles as Funtuple +from PyConf.application import metainfo_repos + +from DaVinci.algorithms import create_lines_filter +from PyConf.reading import ( + get_pvs, + get_rec_summary, + ) +from PyConf.Algorithms import ( + WeightedRelTableAlg, + Hlt1TisTosAlg, + Hlt2TisTosAlg, + ThOrParticleSelection + ) +from Hlt2Conf.flavourTagging import run2_all_taggers + +import FunTuple.functorcollections as FC +from GaudiConf.LbExec import HltSourceID +from PyConf.reading import get_decreports, get_hlt1_selreports, get_particles +from PyConf.dataflow import DataHandle +#swaps +from DaVinciTools import SubstitutePID +from PyConf.Algorithms import ParticleContainerMerger +import numpy as np + + +logger=LogStore.add_logger('rd_ap_2024:flavour_tagging_variables') + +################################################################################# +# Flavour Tagging Variables maker [not always available for a given line... some care] +# TODO : document functionality and use - case +################################################################################# +def make_ft_variables(data): + logger.debug("---------- make_ft_variables -------------") + if ENABLE_FT == False : + return FunctorCollection() + all_tagging = run2_all_taggers(data) + variables = FC.FlavourTaggingResults(all_tagging) + + return variables + + +# def make_ft_variables(options, data): +# logger.debug("---------- make_ft_variables -------------") +# from PyConf.Algorithms import ParticleTaggerAlg, ParticleContainerMerger +# from PyConf.Algorithms import FunctionalSSPionTagger +# # from DaVinci.common_particles import make_long_pions +# from Hlt2Conf.standard_particles import make_long_pions +# tagging_pion = make_long_pions() +# MCTRUTH = MCTruthAndBkgCat(LINE_DATA, name="MCTruthAndBkgCat_{hash}") + # V2_PVS = get_pvs() + +# sspion_tagging = FunctionalSSPionTagger( +# BCandidates = data, +# TaggingPions = tagging_pion, +# PrimaryVertices = v2_pvs, +# OutputLevel=3 +# ) +# tagging_container = ParticleContainerMerger( InputContainers = [tagging_pion]).OutputContainer +# tagAlg = ParticleTaggerAlg(Input = data, TaggingContainer = tagging_container, OutputLevel=3) +# tagAlg_rels = tagAlg.OutputRelations +# variables = FunctorCollection({ +# "SSPionBDT_DEC": F.SSPionBDT_Decision(sspion_tagging.OutputFlavourTags), +# "SSPionBDT_ETA": F.SSPionBDT_Mistag(sspion_tagging.OutputFlavourTags), +# "TagTr_P" : F.MAP_INPUT_ARRAY(Functor=F.P, Relations=tagAlg_rels), +# }) +# return variables diff --git a/rd_ap_2024/tupling/variables/inclusive_detached_dilepton_mvas.py b/rd_ap_2024/tupling/variables/inclusive_detached_dilepton_mvas.py new file mode 100644 index 0000000000000000000000000000000000000000..806322b1b2a650dd1de4888e79cad397e164a5f2 --- /dev/null +++ b/rd_ap_2024/tupling/variables/inclusive_detached_dilepton_mvas.py @@ -0,0 +1,759 @@ +############################################################################### +# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### + +# For Debugging Purpose +MVA_ENABLE = True +from rd_ap_2024.utils.log_store import LogStore + +""" +Author: Leon Carus (leon.david.carus@cern.ch) +Taken from https://gitlab.cern.ch/lhcb/Moore/-/blob/master/Hlt/Hlt2Conf/python/Hlt2Conf/lines/inclusive_detached_dilepton/dilepton_mva_builder.py?ref_type=heads#L748 +Only MVA variables creator Parked out +Date: 22.06.2023 + +Guidelines to attach the variables on few examples +- B0s -> mu mu: Twobody MVA [to the B var] + +- B+ ->Jpsi K+: Twobody MVA + Threebody MVA + Twobody from J/Psi , 3 Body from B+ with child logic here + +- B0 -> Jpsi K*0 : Twobody MVA + Threebody MVA + Fourbody MVA + Twobody from J/Psi , 3/4 Body from B+ with child logic here [ intermediate resonant = True] + +- B0 -> Jpsi L0 : Twobody MVA + NeutralMVA + Twobody from J/Psi , 3/4 Body from B+ with child logic here [ intermediate resonant = True] + +For +- InclDetDimuon_MVA +- InclDetDielectron_MVA +- InclDetElectronMuon_MVA +If you attach to a particle going to 2mu, 2e, or emu , or hh , + - DiLeptonFromB =False +If you attach at the head particle of the decay where + B -> J/Psi(ee,mm,em) X + - DiLeptonFromB = True, DiLeptonChildIdx =1 [mapping to the children of the B] + +For + - InclDet*_ThreeBody_MVA + - InclDet*_FourBody_MVA + - InclDet*_neutral_MVA + +- The MVA was trained originally with a 3 body product, 4 body product or a J/Psi Kshort +Your third body can be nested in a intermediate resonance, in this case likely the variables won't make much sense +because the ThreeBody we compute is actually on a fully reconstructed B +So the 3body,4body and neutral works as it should for the following cases: + J/Psi H+/- [ 3 Body OK] + J/Psi H+ H- [ 4 Body Case], if your HH is from a + resonance then you need to make the call with + intermediateDiHadron = True so it deep navigate the X(->HH) + Neutral NOT YET TESTED + +If you attach functors +""" +from PyConf.dataflow import DataHandle # type: ignore[import] +import Functors as F +import Functors.math as fmath +from FunTuple import FunctorCollection +from PyConf import configurable +from GaudiKernel.SystemOfUnits import GeV, MeV, ps +from Hlt2Conf.lines.rd.builders.rdbuilder_thor import make_rd_detached_dielectron, make_rd_detached_pions, make_rd_detached_muons +from Hlt2Conf.standard_particles import make_detached_mue_with_brem +from RecoConf.reconstruction_objects import make_pvs +from Functors.math import in_range +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleFilter + +#### +# Functions supported : +# Di-Muon +# - InclDetDimuon_MVA ---> to attach to JPsi intermediate status +# - InclDetDimuon_ThreeBody_MVA ---> to attach to any decay having B -> JPsi H +# - InclDetDimuon_FourBody_MVA ---> to attach to any decay having B -> JPsi H H +# - InclDetDimuon_neutral_MVA +# Di-Electron +# - InclDetDielectron_MVA ---> to attach to JPsi intermediate status +# - InclDetDielectron_ThreeBody_MVA ---> to attach to any decay having B -> JPsi H [if a decay B is made in 4 body, the 3 body object info are wrong] +# - InclDetDielectron_FourBody_MVA ---> to attach to any decay having B -> JPsi H H +# - InclDetDielectron_neutral_MVA +# Di-Electron/Muon +# - InclDetElectronMuon_MVA +# - InclDetElectronMuon_ThreeBody_MVA +# - InclDetElectronMuon_FourBody_MVA +# - InclDetElectronMuon_neutral_MVA + +logger=LogStore.add_logger('rd_ap_2024:inclusive_detached_dilepton') + +def _remove_paranthesis_functors_( input_dict : dict , prefix: str = "")-> dict : + new_dict = {} + for key, value in input_dict.items(): + new_key = key.replace("log(","log_").replace( ")","") + if prefix != "" : + new_key = f"{prefix}_{new_key}" + new_dict[new_key] = value + return new_dict +def InclDetDimuon_MVA(pvs :DataHandle =None, DiLeptonFromB : bool = False , DiLeptonChildIdx : int = 1) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + """ + In decays where X -> Y ( mu mu ) L L + DiLeptonFromB has to be True, so the DiLeptonChildIdx is used to grab the mu+ mu- pair + DiLeptonFromB = True --> use child(dileptonchildidx) -> track1,track2 + DiLeptonFromB = False --> use child(1,2) for track1.2 + + With X -> Y( mu mu ) LL : + -> DiLeptonFromB = True + With X-> mu mu + -> DiLeptonFromB = False + + DiLeptonFromB = False --> + use THIS->PT (di-lepton) + use THIS->CHILD(1) = mu1 + DiLeptonFromB = True --> + use THIS->CHIL(1)->PT + use THIS->CHILD(DiLeptonChildIdx)->CHILD(1) -> PT + """ + Inputs = { + "TwoBody_LoKi_DIRA_OWNPV": F.BPVDIRA(pvs) if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.BPVDIRA(pvs)) , + "log(TwoBody_LoKi_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHI2DOF)) , + "log(TwoBody_LoKi_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.BPVFDCHI2(pvs))), + "log(TwoBody_LoKi_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.BPVIPCHI2(pvs))), + "TwoBody_LoKi_Mcorr": F.BPVCORRM(pvs) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.BPVCORRM(pvs)) / GeV , + "TwoBody_LoKi_PT": F.PT / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.PT) / GeV, + "log(Track1_LoKi_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_LoKi_PT": F.CHILD(1, F.PT) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.CHILD(1, F.PT)) / GeV, + "log(Track2_LoKi_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_LoKi_PT": F.CHILD(2, F.PT) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.CHILD(2, F.PT)) / GeV, + } + mva_2body = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDimuon_weights_202304.json", + 'Name': + "SigmaNet_mumu", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "10", + 'Monotone_Constraints': + '[0,0,1,0,0,1,0,1,0,1]', + 'Variables': + 'TwoBody_LoKi_DIRA_OWNPV,log(TwoBody_LoKi_ENDVERTEX_CHI2),log(TwoBody_LoKi_FDCHI2_OWNPV),log(TwoBody_LoKi_MINIPCHI2),TwoBody_LoKi_Mcorr,TwoBody_LoKi_PT,log(Track1_LoKi_MINIPCHI2),Track1_LoKi_PT,log(Track2_LoKi_MINIPCHI2),Track2_LoKi_PT', + }, + Inputs=Inputs + ) + return_variables = FunctorCollection({ + "InclDetDimuon_MVA": mva_2body + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetDimuon_MVA") ) + return return_variables + +############################################################### +def InclDetDielectron_MVA(pvs :DataHandle =None , DiLeptonFromB : bool = False , DiLeptonChildIdx : int = 1) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + Inputs = { + "TwoBody_LoKi_DIRA_OWNPV": F.BPVDIRA(pvs) if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.BPVDIRA(pvs)) , + "log(TwoBody_LoKi_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHI2DOF)) , + "log(TwoBody_LoKi_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.BPVFDCHI2(pvs))), + "log(TwoBody_LoKi_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.BPVIPCHI2(pvs))), + "TwoBody_LoKi_Mcorr": F.BPVCORRM(pvs) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.BPVCORRM(pvs)) / GeV , + "TwoBody_LoKi_PT": F.PT / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.PT) / GeV, + "log(Track1_LoKi_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_LoKi_PT": F.CHILD(1, F.PT) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.CHILD(1, F.PT)) / GeV, + "log(Track2_LoKi_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_LoKi_PT": F.CHILD(2, F.PT) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.CHILD(2, F.PT)) / GeV + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDielectron_weights_202304.json", + 'Name': + "SigmaNet_ee", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "10", + 'Monotone_Constraints': + '[0,0,1,0,0,1,0,1,0,1]', + 'Variables': + 'TwoBody_LoKi_DIRA_OWNPV,log(TwoBody_LoKi_ENDVERTEX_CHI2),log(TwoBody_LoKi_FDCHI2_OWNPV),log(TwoBody_LoKi_MINIPCHI2),TwoBody_LoKi_Mcorr,TwoBody_LoKi_PT,log(Track1_LoKi_MINIPCHI2),Track1_LoKi_PT,log(Track2_LoKi_MINIPCHI2),Track2_LoKi_PT', + }, + Inputs=Inputs + ) + return_variables = FunctorCollection({ + "InclDetDielectron_MVA": mva + }) + return_variables+= FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetDielectron_MVA")) + return return_variables + +############################################################### +def InclDetElectronMuon_MVA( pvs : DataHandle = None , DiLeptonFromB : bool = False , DiLeptonChildIdx : int = 1) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + Inputs = { + "TwoBody_LoKi_DIRA_OWNPV": F.BPVDIRA(pvs) if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.BPVDIRA(pvs)) , + "log(TwoBody_LoKi_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHI2DOF)) , + "log(TwoBody_LoKi_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.BPVFDCHI2(pvs))), + "log(TwoBody_LoKi_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.BPVIPCHI2(pvs))), + "TwoBody_LoKi_Mcorr": F.BPVCORRM(pvs) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.BPVCORRM(pvs)) / GeV , + "TwoBody_LoKi_PT": F.PT / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.PT) / GeV, + "log(Track1_LoKi_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_LoKi_PT": F.CHILD(1, F.PT) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.CHILD(1, F.PT)) / GeV, + "log(Track2_LoKi_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(DiLeptonFromB) else fmath.log(F.CHILD(DiLeptonChildIdx,F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_LoKi_PT": F.CHILD(2, F.PT) / GeV if not(DiLeptonFromB) else F.CHILD(DiLeptonChildIdx,F.CHILD(2, F.PT)) / GeV, + } + mva_mue = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetElectronMuon_weights_202304.json", + 'Name': + "SigmaNet_mue", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "10", + 'Monotone_Constraints': + '[0,0,1,0,0,1,0,1,0,1]', + 'Variables': + 'TwoBody_LoKi_DIRA_OWNPV,log(TwoBody_LoKi_ENDVERTEX_CHI2),log(TwoBody_LoKi_FDCHI2_OWNPV),log(TwoBody_LoKi_MINIPCHI2),TwoBody_LoKi_Mcorr,TwoBody_LoKi_PT,log(Track1_LoKi_MINIPCHI2),Track1_LoKi_PT,log(Track2_LoKi_MINIPCHI2),Track2_LoKi_PT', + }, + Inputs=Inputs) + return_variables = FunctorCollection({ + "InclDetElectronMuon_MVA": mva_mue + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetElectronMuon_MVA")) + return return_variables + + +############################################################### +def InclDetDimuon_ThreeBody_MVA(pvs : DataHandle =None , intermediateDiHadron : bool = False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + Inputs={ + "ThreeBody_DIRA_OWNPV":F.BPVDIRA(pvs), + "log(ThreeBody_ENDVERTEX_CHI2)":fmath.log(F.CHI2DOF), + "log(ThreeBody_FDCHI2_OWNPV)":fmath.log(F.BPVFDCHI2(pvs)), + "log(ThreeBody_MINIPCHI2)":fmath.log(F.BPVIPCHI2(pvs)), + "ThreeBody_PT":F.PT / GeV, + "TwoBody_DIRA_OWNPV":F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)":fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_FDCHI2_OWNPV)":fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(TwoBody_MINIPCHI2)":fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "TwoBody_Mcorr":F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "TwoBody_PT":F.CHILD(1, F.PT) / GeV, + "log(Track1_MINIPCHI2)":fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT":F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)":fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT":F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)":fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track3_PT":F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2,F.CHILD(1, F.PT)) / GeV, + } + mva_3b = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDimuon_3B_weights_202304.json", + 'Name': + "SigmaNet_mumu_plus_track", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "17", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0]', + 'Variables': + 'ThreeBody_DIRA_OWNPV,log(ThreeBody_ENDVERTEX_CHI2),log(ThreeBody_FDCHI2_OWNPV),log(ThreeBody_MINIPCHI2),ThreeBody_PT,TwoBody_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_FDCHI2_OWNPV),log(TwoBody_MINIPCHI2),TwoBody_Mcorr,TwoBody_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT', + }, + Inputs=Inputs) + return_variables = FunctorCollection({ + "InclDetDimuon_ThreeBody_MVA": mva_3b + }) + return_variables+= FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix = "InclDetDimuon_ThreeBody_MVA")) + return return_variables + +############################################################### +def InclDetDielectron_ThreeBody_MVA(pvs : DataHandle =None,intermediateDiHadron :bool = False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + if intermediateDiHadron : + logger.debug(f""" + WARNING FOR CONFIGURATION InclDetDielectron_ThreeBody_MVA functors, + YOU HAVE AN INTERMEDIATE RESONANCE FOR THE THIRD HADRON, but input vars [most of them] are computed + """) + Inputs = { + "ThreeBody_DIRA_OWNPV":F.BPVDIRA(pvs), + "log(ThreeBody_ENDVERTEX_CHI2)":fmath.log(F.CHI2DOF), + "log(ThreeBody_FDCHI2_OWNPV)":fmath.log(F.BPVFDCHI2(pvs)), + "log(ThreeBody_MINIPCHI2)":fmath.log(F.BPVIPCHI2(pvs)), + "ThreeBody_PT":F.PT / GeV, + "TwoBody_DIRA_OWNPV":F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)":fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_FDCHI2_OWNPV)":fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(TwoBody_MINIPCHI2)":fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "TwoBody_Mcorr":F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "TwoBody_PT":F.CHILD(1, F.PT) / GeV, + "log(Track1_MINIPCHI2)":fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT":F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)":fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT":F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)":fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1,F.BPVIPCHI2(pvs)))) , + "Track3_PT":F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.PT))/ GeV, + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDielectron_3B_weights_202304.json", + 'Name': + "SigmaNet_ee_plus_track", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "17", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0]', + 'Variables': + 'ThreeBody_DIRA_OWNPV,log(ThreeBody_ENDVERTEX_CHI2),log(ThreeBody_FDCHI2_OWNPV),log(ThreeBody_MINIPCHI2),ThreeBody_PT,TwoBody_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_FDCHI2_OWNPV),log(TwoBody_MINIPCHI2),TwoBody_Mcorr,TwoBody_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT', + }, + Inputs=Inputs) + + + return_variables = FunctorCollection({ + "InclDetDielectron_ThreeBody_MVA": mva + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetDielectron_ThreeBody_MVA")) + return return_variables + +############################################################### +def InclDetElectronMuon_ThreeBody_MVA(pvs : DataHandle=None, intermediateDiHadron :bool =False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + #### if we have B-> JPsi(emu) Phi(KK), the 3body DIRA should not be the one from the B but from JPsi + K , we need to think a bit how to compute it. + if intermediateDiHadron : + logger.debug(f""" + WARNING FOR CONFIGURATION InclDetElectronMuon_ThreeBody_MVA functors, + YOU HAVE AN INTERMEDIATE RESONANCE FOR THE THIRD HADRON, but input vars [most of them] are computed + """) + Inputs = { + "ThreeBody_DIRA_OWNPV": F.BPVDIRA(pvs), + "log(ThreeBody_ENDVERTEX_CHI2)":fmath.log(F.CHI2DOF), + "log(ThreeBody_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)), + "log(ThreeBody_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)), + "ThreeBody_PT": F.PT / GeV, + "TwoBody_DIRA_OWNPV": F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)": fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_FDCHI2_OWNPV)": fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(TwoBody_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "TwoBody_Mcorr": F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "TwoBody_PT": F.CHILD(1, F.PT) / GeV, + "log(Track1_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT": F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT": F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track3_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.PT)) / GeV + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetElectronMuon_3B_weights_202304.json", + 'Name': + "SigmaNet_mue_plus_track", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "17", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0]', + 'Variables': + 'ThreeBody_DIRA_OWNPV,log(ThreeBody_ENDVERTEX_CHI2),log(ThreeBody_FDCHI2_OWNPV),log(ThreeBody_MINIPCHI2),ThreeBody_PT,TwoBody_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_FDCHI2_OWNPV),log(TwoBody_MINIPCHI2),TwoBody_Mcorr,TwoBody_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT', + }, + Inputs= Inputs) + return_variables = FunctorCollection({ + "InclDetElectronMuon_ThreeBody_MVA": mva + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetElectronMuon_ThreeBody_MVA" ) ) + return return_variables + +############################################################### +def InclDetDimuon_FourBody_MVA(pvs : DataHandle =None, intermediateDiHadron :bool =False) -> FunctorCollection: + + logger.debug(f""" + WARNING FOR CONFIGURATION InclDetDimuon_FourBody_MVA functors, + If you have >4 final states the FourBody object is computed on the fully reconstructed + candidates, and not pickling and vertexing the dilepton + 2 and only 2 final states + from the hadronic part + """) + if MVA_ENABLE == False : + return FunctorCollection() + # this is ok, but again for a 5 body decay we need to pick a FourBody_ENDVERTEX_CHI2 from the sub-decaying particle list, + # not the full candidate + Inputs = { + "FourBody_DIRA_OWNPV": F.BPVDIRA(pvs), + "log(FourBody_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF), + "log(FourBody_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)), + "log(FourBody_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)), + "FourBody_PT": F.PT / GeV, + "TwoBody_DIRA_OWNPV": F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)": fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_FDCHI2_OWNPV)": fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(TwoBody_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "TwoBody_Mcorr": F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "TwoBody_PT": F.CHILD(1, F.PT) / GeV, + "log(Track1_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT": F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT": F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD( 2,F.CHILD( 1, F.BPVIPCHI2(pvs)))), + "Track3_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD( 2,F.CHILD( 1, F.PT) )/ GeV, + "log(Track4_MINIPCHI2)": fmath.log(F.CHILD(3, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD( 2,F.CHILD( 2, F.BPVIPCHI2(pvs)))), + "Track4_PT": F.CHILD(3, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD( 2,F.CHILD( 2, F.PT) )/ GeV, + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDimuon_4B_weights_202304.json", + 'Name': + "SigmaNet_mumu_plus_2track", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "19", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0]', + 'Variables': + 'FourBody_DIRA_OWNPV,log(FourBody_ENDVERTEX_CHI2),log(FourBody_FDCHI2_OWNPV),log(FourBody_MINIPCHI2),FourBody_PT,TwoBody_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_FDCHI2_OWNPV),log(TwoBody_MINIPCHI2),TwoBody_Mcorr,TwoBody_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT,log(Track4_MINIPCHI2),Track4_PT', + }, + Inputs=Inputs) + return_variables = FunctorCollection({ + "InclDetDimuon_FourBody_MVA": mva + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetDimuon_FourBody_MVA") ) + return return_variables + +############################################################### +def InclDetDielectron_FourBody_MVA(pvs : DataHandle =None, intermediateDiHadron: bool =False) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + logger.debug(f""" + WARNING FOR CONFIGURATION InclDetDielectron_FourBody_MVA functors, + If you have >4 final states the FourBody object is computed on the fully reconstructed + candidates, and not pickling and vertexing the dilepton + 2 and only 2 final states + from the hadronic part + """) + Inputs={ + "FourBody_DIRA_OWNPV":F.BPVDIRA(pvs), + "log(FourBody_ENDVERTEX_CHI2)":fmath.log(F.CHI2DOF), + "log(FourBody_FDCHI2_OWNPV)":fmath.log(F.BPVFDCHI2(pvs)), + "log(FourBody_MINIPCHI2)":fmath.log(F.BPVIPCHI2(pvs)), + "FourBody_PT":F.PT / GeV, + "TwoBody_DIRA_OWNPV":F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)":fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_FDCHI2_OWNPV)":fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(TwoBody_MINIPCHI2)":fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "TwoBody_Mcorr":F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "TwoBody_PT":F.CHILD(1, F.PT) / GeV, + "log(Track1_MINIPCHI2)":fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT":F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)":fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT":F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track3_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2,F.CHILD(1, F.PT)) / GeV, + "log(Track4_MINIPCHI2)": fmath.log(F.CHILD(3, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track4_PT": F.CHILD(3, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2,F.CHILD(2, F.PT)) / GeV + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDielectron_4B_weights_202304.json", + 'Name': + "SigmaNet_ee_plus_2track", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "19", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0]', + 'Variables': + 'FourBody_DIRA_OWNPV,log(FourBody_ENDVERTEX_CHI2),log(FourBody_FDCHI2_OWNPV),log(FourBody_MINIPCHI2),FourBody_PT,TwoBody_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_FDCHI2_OWNPV),log(TwoBody_MINIPCHI2),TwoBody_Mcorr,TwoBody_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT,log(Track4_MINIPCHI2),Track4_PT', + }, + Inputs=Inputs) + return_variables = FunctorCollection({ + "InclDetDielectron_FourBody_MVA": mva + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetDielectron_FourBody_MVA") ) + return return_variables + +############################################################### +def InclDetElectronMuon_FourBody_MVA(pvs : DataHandle =None, intermediateDiHadron: bool = False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + logger.debug(f""" + WARNING FOR CONFIGURATION InclDetElectronMuon_FourBody_MVA functors, + If you have >4 final states the FourBody object is computed on the fully reconstructed + candidates, and not pickling and vertexing the dilepton + 2 and only 2 final states + from the hadronic part + """) + Inputs = {"FourBody_DIRA_OWNPV":F.BPVDIRA(pvs), + "log(FourBody_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF), + "log(FourBody_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)), + "log(FourBody_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)), + "FourBody_PT": F.PT / GeV, + "TwoBody_DIRA_OWNPV": F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)": fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_FDCHI2_OWNPV)": fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(TwoBody_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "TwoBody_Mcorr": F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "TwoBody_PT": F.CHILD(1, F.PT) / GeV, + "log(Track1_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT": F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT": F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.BPVIPCHI2(pvs)))) , + "Track3_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.PT)) / GeV , + "log(Track4_MINIPCHI2)": fmath.log(F.CHILD(3, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(2, F.BPVIPCHI2(pvs)))) , + "Track4_PT": F.CHILD(3, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(2, F.PT)) / GeV , + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetElectronMuon_4B_weights_202304.json", + 'Name': + "SigmaNet_mue_plus_2track", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "19", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0]', + 'Variables': + 'FourBody_DIRA_OWNPV,log(FourBody_ENDVERTEX_CHI2),log(FourBody_FDCHI2_OWNPV),log(FourBody_MINIPCHI2),FourBody_PT,TwoBody_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_FDCHI2_OWNPV),log(TwoBody_MINIPCHI2),TwoBody_Mcorr,TwoBody_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT,log(Track4_MINIPCHI2),Track4_PT', + }, + Inputs=Inputs) + return_variables = FunctorCollection({ + "InclDetElectronMuon_FourBody_MVA": mva + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetElectronMuon_FourBody_MVA") ) + return return_variables + +############################################################### +def InclDetDimuon_neutral_MVA(pvs : DataHandle =None, intermediateDiHadron= False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + """ + For B -> J/Psi Ks + For B -> J/Psi Lambda + OR + For B -> J/Psi X(-> Ks Y) + For B -> J/Psi X(-> Lambda Y) + + If J/Psi K*+(Ks pi+) then intermediateDiHadron= True, but the FoudBody is actually the full 5 body recoed object. + """ + Inputs = { + "FourBody_DIRA_OWNPV": F.BPVDIRA(pvs), + "log(FourBody_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF), + "log(FourBody_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)), + "log(FourBody_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)), + "FourBody_PT": F.PT / GeV, + "FourBody_CHILD_DIRA_OWNPV": F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)": fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_pion_ENDVERTEX_CHI2)": fmath.log(F.CHILD(2, F.CHI2DOF)) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1,F.CHI2DOF))), + "log(FourBody_CHILD_FDCHI2_OWNPV)": fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(FourBody_CHILD_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "FourBody_CHILD_Mcorr": F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "log(FourBody_CHILD2_FDCHI2_OWNPV)":fmath.log(F.CHILD(2, F.BPVFDCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVFDCHI2(pvs)))), + "log(FourBody_CHILD2_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "TwoBody_PT": F.CHILD(1, F.PT) / GeV, + "TwoBody_pion_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.PT)) / GeV, + "log(Track1_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT": F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT": F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.CHILD(1, F.BPVIPCHI2(pvs)))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs))))), + "Track3_PT": F.CHILD(2, F.CHILD(1, F.PT)) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.CHILD(1, F.PT))) / GeV, + "log(Track4_MINIPCHI2)": fmath.log(F.CHILD(2, F.CHILD(2, F.BPVIPCHI2(pvs)))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs))))), + "Track4_PT": F.CHILD(2, F.CHILD(2, F.PT)) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.CHILD(2, F.PT))) / GeV, + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDimuon_neutral_weights_202304.json", + 'Name': + "SigmaNet_mumu_plus_neutral", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "23", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,1,0,0,0,0]', + 'Variables': + 'FourBody_DIRA_OWNPV,log(FourBody_ENDVERTEX_CHI2),log(FourBody_FDCHI2_OWNPV),log(FourBody_MINIPCHI2),FourBody_PT,FourBody_CHILD_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_pion_ENDVERTEX_CHI2),log(FourBody_CHILD_FDCHI2_OWNPV),log(FourBody_CHILD_MINIPCHI2),FourBody_CHILD_Mcorr,log(FourBody_CHILD2_FDCHI2_OWNPV),log(FourBody_CHILD2_MINIPCHI2),TwoBody_PT,TwoBody_pion_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT,log(Track4_MINIPCHI2),Track4_PT', + }, + Inputs=Inputs) + return_variables = FunctorCollection({ + "InclDetDimuon_neutral_MVA": mva + }) + return_variables += FunctorCollection( _remove_paranthesis_functors_(Inputs, prefix="InclDetDimuon_neutral_MVA")) + return return_variables + +############################################################### +def InclDetDielectron_neutral_MVA(pvs : DataHandle =None , intermediateDiHadron: bool = False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + """ + For B -> J/Psi Ks + For B -> J/Psi Lambda + OR + For B -> J/Psi X(-> Ks Y) + For B -> J/Psi X(-> Lambda Y) + + If J/Psi K*+(Ks pi+) then intermediateDiHadron= True, but the FoudBody is actually the full 5 body recoed object, inconsistency to expect + """ + Inputs = { + "FourBody_DIRA_OWNPV": F.BPVDIRA(pvs), + "log(FourBody_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF), + "log(FourBody_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)), + "log(FourBody_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)), + "FourBody_PT": F.PT / GeV, + "FourBody_CHILD_DIRA_OWNPV": F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)": fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_pion_ENDVERTEX_CHI2)": fmath.log(F.CHILD(2, F.CHI2DOF)) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1,F.CHI2DOF))), + "log(FourBody_CHILD_FDCHI2_OWNPV)": fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(FourBody_CHILD_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "FourBody_CHILD_Mcorr": F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "log(FourBody_CHILD2_FDCHI2_OWNPV)":fmath.log(F.CHILD(2, F.BPVFDCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVFDCHI2(pvs)))), + "log(FourBody_CHILD2_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "TwoBody_PT": F.CHILD(1, F.PT) / GeV, + "TwoBody_pion_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.PT)) / GeV, + "log(Track1_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT": F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT": F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.CHILD(1, F.BPVIPCHI2(pvs)))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs))))), + "Track3_PT": F.CHILD(2, F.CHILD(1, F.PT)) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.CHILD(1, F.PT))) / GeV, + "log(Track4_MINIPCHI2)": fmath.log(F.CHILD(2, F.CHILD(2, F.BPVIPCHI2(pvs)))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs))))), + "Track4_PT": F.CHILD(2, F.CHILD(2, F.PT)) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.CHILD(2, F.PT))) / GeV, + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetDielectron_neutral_weights_202304.json", + 'Name': + "SigmaNet_ee_plus_neutral", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "23", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,1,0,0,0,0]', + 'Variables': + 'FourBody_DIRA_OWNPV,log(FourBody_ENDVERTEX_CHI2),log(FourBody_FDCHI2_OWNPV),log(FourBody_MINIPCHI2),FourBody_PT,FourBody_CHILD_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_pion_ENDVERTEX_CHI2),log(FourBody_CHILD_FDCHI2_OWNPV),log(FourBody_CHILD_MINIPCHI2),FourBody_CHILD_Mcorr,log(FourBody_CHILD2_FDCHI2_OWNPV),log(FourBody_CHILD2_MINIPCHI2),TwoBody_PT,TwoBody_pion_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT,log(Track4_MINIPCHI2),Track4_PT', + }, + Inputs = Inputs) + + return_variables = FunctorCollection({ + "InclDetDielectron_neutral_MVA": mva + }) + return_variables+= FunctorCollection(_remove_paranthesis_functors_(Inputs, prefix="InclDetDielectron_neutral_MVA")) + return return_variables + +############################################################### +def InclDetElectronMuon_neutral_MVA(pvs : DataHandle =None , intermediateDiHadron: bool = False ) -> FunctorCollection: + if MVA_ENABLE == False : + return FunctorCollection() + """ + For B -> J/Psi Ks + For B -> J/Psi Lambda + OR + For B -> J/Psi X(-> Ks Y) + For B -> J/Psi X(-> Lambda Y) + + If J/Psi K*+(Ks pi+) then intermediateDiHadron= True, but the FoudBody is actually the full 5 body recoed object, inconsistency to expect + """ + Inputs = { + "FourBody_DIRA_OWNPV": F.BPVDIRA(pvs), + "log(FourBody_ENDVERTEX_CHI2)": fmath.log(F.CHI2DOF), + "log(FourBody_FDCHI2_OWNPV)": fmath.log(F.BPVFDCHI2(pvs)), + "log(FourBody_MINIPCHI2)": fmath.log(F.BPVIPCHI2(pvs)), + "FourBody_PT": F.PT / GeV, + "FourBody_CHILD_DIRA_OWNPV": F.CHILD(1, F.BPVDIRA(pvs)), + "log(TwoBody_ENDVERTEX_CHI2)": fmath.log(F.CHILD(1, F.CHI2DOF)), + "log(TwoBody_pion_ENDVERTEX_CHI2)": fmath.log(F.CHILD(2, F.CHI2DOF)) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1,F.CHI2DOF))), + "log(FourBody_CHILD_FDCHI2_OWNPV)": fmath.log(F.CHILD(1, F.BPVFDCHI2(pvs))), + "log(FourBody_CHILD_MINIPCHI2)": fmath.log(F.CHILD(1, F.BPVIPCHI2(pvs))), + "FourBody_CHILD_Mcorr": F.CHILD(1, F.BPVCORRM(pvs)) / GeV, + "log(FourBody_CHILD2_FDCHI2_OWNPV)":fmath.log(F.CHILD(2, F.BPVFDCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVFDCHI2(pvs)))), + "log(FourBody_CHILD2_MINIPCHI2)": fmath.log(F.CHILD(2, F.BPVIPCHI2(pvs))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2,F.CHILD(1, F.BPVIPCHI2(pvs)))), + "TwoBody_PT": F.CHILD(1, F.PT) / GeV, + "TwoBody_pion_PT": F.CHILD(2, F.PT) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.PT)) / GeV, + "log(Track1_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs)))), + "Track1_PT": F.CHILD(1, F.CHILD(1, F.PT)) / GeV, + "log(Track2_MINIPCHI2)": fmath.log(F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs)))), + "Track2_PT": F.CHILD(1, F.CHILD(2, F.PT)) / GeV, + "log(Track3_MINIPCHI2)": fmath.log(F.CHILD(2, F.CHILD(1, F.BPVIPCHI2(pvs)))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.CHILD(1, F.BPVIPCHI2(pvs))))), + "Track3_PT": F.CHILD(2, F.CHILD(1, F.PT)) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.CHILD(1, F.PT))) / GeV, + "log(Track4_MINIPCHI2)": fmath.log(F.CHILD(2, F.CHILD(2, F.BPVIPCHI2(pvs)))) if not(intermediateDiHadron) else fmath.log(F.CHILD(2, F.CHILD(1, F.CHILD(2, F.BPVIPCHI2(pvs))))), + "Track4_PT": F.CHILD(2, F.CHILD(2, F.PT)) / GeV if not(intermediateDiHadron) else F.CHILD(2, F.CHILD(1, F.CHILD(2, F.PT))) / GeV, + } + mva = F.MVA( + MVAType='SigmaNet', + Config={ + 'File': + "paramfile://data/Upgrade_InclDetElectronMuon_neutral_weights_202304.json", + 'Name': + "SigmaNet_mue_plus_neutral", + 'Lambda': + "2.0", + 'NLayers': + "5", + 'InputSize': + "23", + 'Monotone_Constraints': + '[0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,1,0,0,0,0]', + 'Variables': + 'FourBody_DIRA_OWNPV,log(FourBody_ENDVERTEX_CHI2),log(FourBody_FDCHI2_OWNPV),log(FourBody_MINIPCHI2),FourBody_PT,FourBody_CHILD_DIRA_OWNPV,log(TwoBody_ENDVERTEX_CHI2),log(TwoBody_pion_ENDVERTEX_CHI2),log(FourBody_CHILD_FDCHI2_OWNPV),log(FourBody_CHILD_MINIPCHI2),FourBody_CHILD_Mcorr,log(FourBody_CHILD2_FDCHI2_OWNPV),log(FourBody_CHILD2_MINIPCHI2),TwoBody_PT,TwoBody_pion_PT,log(Track1_MINIPCHI2),Track1_PT,log(Track2_MINIPCHI2),Track2_PT,log(Track3_MINIPCHI2),Track3_PT,log(Track4_MINIPCHI2),Track4_PT', + }, + Inputs = Inputs) + return_variables = FunctorCollection({ + "InclDetElectronMuon_neutral_MVA": mva + }) + return_variables+= FunctorCollection(_remove_paranthesis_functors_(Inputs, prefix="InclDetElectronMuon_neutral_MVA")) + return return_variables diff --git a/rd_ap_2024/tupling/variables/rd_stream_isolation_functions.py b/rd_ap_2024/tupling/variables/rd_stream_isolation_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..d99ce8d6971fb4eea98fe9e185e4cd410a73c212 --- /dev/null +++ b/rd_ap_2024/tupling/variables/rd_stream_isolation_functions.py @@ -0,0 +1,250 @@ + +############################################################################### +# (c) Copyright 2022-2023 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +""" +Option file with functions to implement cone isolation and vertex isolation variables in AP +""" +from rd_ap_2024.utils.log_store import LogStore + +# For Debug Memory consumption +ISOLATION_ENABLED = True + +from typing import Tuple + +from PyConf.Algorithms import ThOrParticleSelection +from PyConf.dataflow import DataHandle # type: ignore[import] +import Functors as F +import Functors.math as fmath +from IsolationTools import VertexAndConeIsolation +#https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Phys/RelatedInfoTools/python/IsolationTools/IsolationTools.py?ref_type=heads +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleContainersMerger +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +import FunTuple.functorcollections as FC +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +import math +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) + +logger=LogStore.add_logger('rd_ap_2024:rd_stream_isolation_functions') + +def get_process_dependent_flags(options: Options) -> Tuple[str, str] : + logger.debug(options) + try: + if options.input_process == 'Spruce': + return 'Spruce', 'Spruce' + elif options.input_process == 'Hlt2': + return 'Hlt2', 'HLT2' + elif options.input_process == 'TurboPass' : + return 'Hlt2', 'HLT2' + else: + raise RuntimeError("`input_process` does not correspond to `Spruce` or `Hlt2`") + except: + raise RuntimeError("`input_process` not found in option dictionary") + + +LOG10_E = math.log10(math.e) +def make_OneTrack_TwoTrack_ForIsolation(candidate : DataHandle, + tes_name : str , + extra_particles : DataHandle, + use_fiducial_cut: bool = False, + can_reco_vertex : bool = True, + bhead_label_decay : str = None + ) -> Tuple[ParticleContainersMerger, ParticleContainersMerger]: + assert( bhead_label_decay != None ) + candidate_charged = ("+" in bhead_label_decay) or ("-" in bhead_label_decay) + """ + Make two body combination of B0 and extra particles (long tracks without pion id). + + Args: + candidate: Containers of reference particles + use_fiducial_cut(bool): Use preselection requirement for the combination (default value False) + can_reco_vertex(bool): Choose algorithm for the combination. + ParticleVertexFitter if True, + ParticleAdder otherwise (default value True) + Returns: TES location of two body combination of candidate and extra_particles + """ + # need substitute PID to attach tracks to the B-decay vertex position + #fiducial cut on pv distance + # pv_dist_min = -3. #mm + # fiducial_cut = F.ALL + # if use_fiducial_cut: + # log_ipchi2_wrtSV_max = 5 + # Head_child = F.CHILD(1, F.FORWARDARGS) + # ExtraParticle_child = F.CHILD(2, F.FORWARDARGS) + # fiducial_cut_sv_ipchi2 = fmath.log( + # F.IPCHI2.bind( + # F.ENDVERTEX @ Head_child, + # ExtraParticle_child)) * LOG10_E < log_ipchi2_wrtSV_max + # fiducial_cut = fiducial_cut_sv_ipchi2 + #first combiner: X pi+ + + if candidate_charged ==True : + DecayDescriptorOneTrack = f"[B*0 -> {bhead_label_decay} pi-]cc" + DecayDescriptorOneTrack_pi_Plus = f"[B*0 -> {bhead_label_decay} pi+]cc" #not used + DecayDescriptorTwoTrack = f"[B*+ -> {bhead_label_decay} rho(770)0]cc" + else : + DecayDescriptorOneTrack = f"[B*+ -> {bhead_label_decay} pi+]cc" + DecayDescriptorOneTrack_pi_Minus = f"[B*+ -> {bhead_label_decay} pi+]cc" #not used + DecayDescriptorTwoTrack = f"[B*0 -> {bhead_label_decay} rho(770)0]cc" + dihadron = ParticleCombiner( + Inputs = [ extra_particles, extra_particles], + DecayDescriptor = "rho(770)0 -> pi+ pi-", + CombinationCut = F.ALL , + CompositeCut = F.ALL + ) + + comb_OneTrack = ParticleCombiner( + Inputs=[candidate, extra_particles], + name='rd_vtxiso_combiner_onetrack_1_{hash}', + # ParticleCombiner=('ParticleVertexFitter' if can_reco_vertex else 'ParticleAdder'), + # # TODO : check what to do here / what's more proper? + DecayDescriptor=DecayDescriptorOneTrack, + CombinationCut=F.ALL, + CompositeCut=F.ALL) + #second combiner: X pi- + comb_TwoTrack = ParticleCombiner( + Inputs=[candidate, dihadron], + name='rd_vtxiso_combiner_twotrack_2_{hash}', + # ParticleCombiner=('ParticleVertexFitter' if can_reco_vertex else 'ParticleAdder'), + # # TODO : check what to do here / what's more proper? + DecayDescriptor=DecayDescriptorTwoTrack, + CombinationCut=F.ALL, + CompositeCut=F.ALL) + #merge two combiners + combOneTrack = ParticleContainersMerger([comb_OneTrack],name=tes_name + '_OneTrack_{hash}') + combTwoTrack = ParticleContainersMerger([comb_TwoTrack],name=tes_name + '_TwoTrack_{hash}') + + return combOneTrack, combTwoTrack + +def make_Isolation_variables(options : Options, + data : DataHandle , + line : str , + header_tes : str , + dr2_angle_list : list = None , + max_delta_vertex_chi2_cuts : list = None , + filter_tree_name : str =None, + bhead_label_decay : str = None + ): + assert( bhead_label_decay is not None ) # NOT OPTIONAL , MUST BE SUPPLIED ! + logger.debug("#### make_Isolation_variables ####") + logger.debug(f"# line : {line}") + logger.debug(f"# header_tes : {header_tes}") + logger.debug(f"# dr2_angle_list : {dr2_angle_list}") + logger.debug(f"# max_delta_vertex_chi2_cuts : {max_delta_vertex_chi2_cuts}") + logger.debug(f"# filter_tree_name : {filter_tree_name}") + logger.debug(f"# bhead_label_decay : {bhead_label_decay}") + """ + This function Is an Helper for the tupling of Isolation Variables. + Adds ConeIsolation, VertexIsolation functor collections for branches. + Parameters: + - options : generic davinci Options setup + - data : the data (i.e get_particles from a line output) + - header_tes : string to map whatever the line had stored for input + When you see this piece of code in the line from RD it means that we store extra particles having a DR2 < 0.25 + iso_parts = rd_isolation.select_parts_for_isolation( + names=["B"], + candidates=[B], + cut=F.require_all(F.DR2 < 0.25, ~F.FIND_IN_TREE())) + iso_parts += rd_isolation.select_parts_for_isolation( + names=['pi+', 'e+', 'e-'], + candidates=[pi_p_child, e_p_child, e_m_child], + cut=F.require_all(F.DR2 < 0.25, ~F.SHARE_TRACKS())) + - angle_list : a list of cone angles to check for tupling , DR2 < Values applied before cone isolation stored. + - max_delta_vertex_cut : later on for vertex isolation + max_delta_vertex_cut=(F.ABS @ (F.CHI2() @ F.FORWARDARG1() - F.CHI2() @ F.FORWARDARG0()) < max_vertex_cut) + Used in https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Phys/RelatedInfoTools/python/IsolationTools/IsolationTools.py?ref_type=heads + - filter_tree_name : sting for the isolation particle to store + """ + + #inspired to https://lhcb-davinci.docs.cern.ch/examples/tupling/option_davinci_tupling_relation_isovariables.html + variables_all = FunctorCollection({}) + if ISOLATION_ENABLED == False : + logger.debug("Isolation tupling disabled, return nothing") + return variables_all + #All RD lines are filtering out the signal from the cone online so we can avoid this additional check + #stable_particles = ['L1','L2','mu','K','Pi',"H","Hp",'Hm'] # Do we need to add other stable particles? + + _, process_line = get_process_dependent_flags(options) + FILTER_TREE = lambda id: F.FILTER(F.IS_ABS_ID(id)) @ F.GET_ALL_DESCENDANTS() + charged_tes = f"/Event/{process_line}/{line}/{header_tes}_LongTrackIsolation/Particles" + neutral_tes = f"/Event/{process_line}/{line}/{header_tes}_NeutralIsolation/Particles" + charged_tracks = get_particles(charged_tes) + neutrals = get_particles(neutral_tes) + if filter_tree_name is None: + # using head of decay as reference + track_data = data + else: + ### it is needed to access the daughter + track_data = ThOrParticleSelection(InputParticles=data, Functor=FILTER_TREE(filter_tree_name)).OutputSelection + + if len(dr2_angle_list) == 0 : + raise RuntimeError("dr2_angle_list must be defined with some angle content value , for example ['1.0' ,...]") + for angle2 in dr2_angle_list: + cone_cut=( (F.DR2 < float(angle2)) & ~F.FIND_IN_TREE() ) #redoundant probably, but needed whenever dealing with more tracks in container. Do Not re-use same tracks as decay products + str_angle2 = angle2.replace(".","p") + charged_iso = VertexAndConeIsolation( + name=f"{header_tes}_ChargedIso_DR2_{str_angle2}", + reference_particles=track_data, + related_particles=charged_tracks, + cut=cone_cut) + neutral_iso = VertexAndConeIsolation( + name=f"{header_tes}_NeutralIso_DR2_{str_angle2}", + reference_particles=track_data, + related_particles=neutrals, + cut=cone_cut) + cone_iso_variables = FC.ConeIsolation( + charged_cone_isolation_alg=charged_iso, + neutral_cone_isolation_alg=neutral_iso, + array_indx_name=f"{header_tes}_cone_indx_DR2_{str_angle2}") + variables_all += cone_iso_variables + + for max_delta_vertex_cut in max_delta_vertex_chi2_cuts : + vertex_cut = F.ALL #(F.ABS @ (F.CHI2() @ F.FORWARDARG1() - F.CHI2() @ F.FORWARDARG0()) < float(max_delta_vertex_cut) ) + str_cut = f"DChi2Vtx_{max_delta_vertex_cut}".replace(".","p") + + OneTrack , TwoTrack = make_OneTrack_TwoTrack_ForIsolation( candidate = track_data, + extra_particles=charged_tracks, + use_fiducial_cut= False, + can_reco_vertex = False, + tes_name= header_tes , + bhead_label_decay= bhead_label_decay + ) + + # Add vertex isolation variables with one and two tracks, applying a cut + if max_delta_vertex_cut != "NO": + vtx_cut = (F.CHI2() @ F.FORWARDARG1() < float(max_delta_vertex_cut)) + else: + vtx_cut = F.ALL + + vtxiso_onetrack = VertexAndConeIsolation( + name=f"{header_tes}_OneTrack_{str_cut}", + reference_particles=track_data, + related_particles=OneTrack, + cut= vtx_cut, + ) + vtxiso_twotracks = VertexAndConeIsolation( + name=f"{header_tes}_TwoTracks_{str_cut}", + reference_particles=track_data, + related_particles=TwoTrack, + cut= vtx_cut, + ) + + vtxiso_onetrack_variables = FC.VertexIsolation(isolation_alg=vtxiso_onetrack) + vtxiso_twotracks_variables = FC.VertexIsolation(isolation_alg=vtxiso_twotracks) + variables_all += vtxiso_onetrack_variables + variables_all += vtxiso_twotracks_variables + return variables_all diff --git a/rd_ap_2024/tupling/variables/rd_stream_isolation_persist_reco.py b/rd_ap_2024/tupling/variables/rd_stream_isolation_persist_reco.py new file mode 100644 index 0000000000000000000000000000000000000000..b4eac420781fa5506f8e1cda000ce4a2c78af786 --- /dev/null +++ b/rd_ap_2024/tupling/variables/rd_stream_isolation_persist_reco.py @@ -0,0 +1,196 @@ + +############################################################################### +# (c) Copyright 2022-2023 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +""" +Option file with functions to implement cone isolation and vertex isolation variables in AP +""" + +from typing import Tuple +from PyConf.Algorithms import ThOrParticleSelection +from PyConf.dataflow import DataHandle # type: ignore[import] +import Functors as F +import Functors.math as fmath +from IsolationTools import VertexAndConeIsolation +#https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Phys/RelatedInfoTools/python/IsolationTools/IsolationTools.py?ref_type=heads +from Hlt2Conf.algorithms_thor import ParticleCombiner, ParticleContainersMerger +from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple +import FunTuple.functorcollections as FC +from DaVinci.algorithms import create_lines_filter +from DaVinci import Options, make_config +from Hlt2Conf.standard_particles import make_long_pions, make_up_pions, make_down_pions, make_ttrack_pions, make_photons, make_merged_pi0s +import math +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) + +def get_process_dependent_flags(options: Options) -> Tuple[str, str] : + print(options) + try: + if options.input_process == 'Spruce': + return 'Spruce', 'Spruce' + elif options.input_process == 'Hlt2': + return 'Hlt2', 'HLT2' + elif options.input_process == 'TurboPass' : + return 'Hlt2', 'HLT2' + else: + raise RuntimeError("`input_process` does not correspond to `Spruce` or `Hlt2`") + except: + raise RuntimeError("`input_process` not found in option dictionary") + + +LOG10_E = math.log10(math.e) +def make_OneTrack_TwoTrack_ForIsolation(candidate : DataHandle, + extra_particles : DataHandle, + bhead_label_decay : str = None + ) -> Tuple[ParticleContainersMerger, ParticleContainersMerger]: + assert( bhead_label_decay != None ) + candidate_charged = ("+" in bhead_label_decay) or ("-" in bhead_label_decay) + """ + Make two body combination of B0 and extra particles (long tracks without pion id). + + Args: + candidate: Containers of reference particles + use_fiducial_cut(bool): Use preselection requirement for the combination (default value False) + can_reco_vertex(bool): Choose algorithm for the combination. + ParticleVertexFitter if True, + ParticleAdder otherwise (default value True) + Returns: TES location of two body combination of candidate and extra_particles + """ + if candidate_charged: + DecayDescriptorOneTrack = f"[B*0 -> {bhead_label_decay} pi-]cc" + DecayDescriptorOneTrack_pi_Plus = f"[B*0 -> {bhead_label_decay} pi+]cc" #not used + DecayDescriptorTwoTrack = f"[B*+ -> {bhead_label_decay} rho(770)0]cc" + else : + #NB : should we make for this case with neutral [{bhead_label_decay}]CC ? + DecayDescriptorOneTrack = f"[B*+ -> {bhead_label_decay} pi+]cc" + DecayDescriptorOneTrack_pi_Minus = f"[B*+ -> {bhead_label_decay} pi+]cc" #not used + DecayDescriptorTwoTrack = f"[B*0 -> {bhead_label_decay} rho(770)0]cc" + dihadron = ParticleCombiner( + Inputs = [ extra_particles, extra_particles], + DecayDescriptor = "rho(770)0 -> pi+ pi-", + CombinationCut = F.ALL, + CompositeCut = F.ALL + ) + + comb_OneTrack = ParticleCombiner( + Inputs=[candidate, extra_particles], + name='rd_vtxiso_combiner_onetrack_1_{hash}', + # ParticleCombiner=('ParticleVertexFitter' if can_reco_vertex else 'ParticleAdder'), + # # TODO : check what to do here / what's more proper? + DecayDescriptor=DecayDescriptorOneTrack, + CombinationCut=F.ALL, + CompositeCut=F.ALL) + #second combiner: X pi- + comb_TwoTrack = ParticleCombiner( + Inputs=[candidate, dihadron], + name='rd_vtxiso_combiner_twotrack_2_{hash}', + # ParticleCombiner=('ParticleVertexFitter' if can_reco_vertex else 'ParticleAdder'), + # # TODO : check what to do here / what's more proper? + DecayDescriptor=DecayDescriptorTwoTrack, + CombinationCut=F.ALL, + CompositeCut=F.ALL) + #merge two combiners + combOneTrack = ParticleContainersMerger([comb_OneTrack],name=bhead_label_decay + '_OneTrack_{hash}') + combTwoTrack = ParticleContainersMerger([comb_TwoTrack],name=bhead_label_decay + '_TwoTrack_{hash}') + + return combOneTrack, combTwoTrack + +def make_Isolation_variables(options : Options, + data : DataHandle , + dr2_angle_list : list = None , + max_delta_vertex_chi2_cuts : list = None , + bhead_label_decay : str = "B0" + ): + print("#### make_Isolation_variables ####") + """ + This function Is an Helper for the tupling of Isolation Variables. + Adds ConeIsolation, VertexIsolation functor collections for branches. + Parameters: + - options : generic davinci Options setup + - data : the data (i.e get_particles from a line output) + - bhead_label_decay : string to map whatever the line had stored for input + When you see this piece of code in the line from RD it means that we store extra particles having a DR2 < 0.25 + iso_parts = rd_isolation.select_parts_for_isolation( + names=["B"], + candidates=[B], + cut=F.require_all(F.DR2 < 0.25, ~F.FIND_IN_TREE())) + iso_parts += rd_isolation.select_parts_for_isolation( + names=['pi+', 'e+', 'e-'], + candidates=[pi_p_child, e_p_child, e_m_child], + cut=F.require_all(F.DR2 < 0.25, ~F.FIND_IN_TREE())) + - angle_list : a list of cone angles to check for tupling , DR2 < Values applied before cone isolation stored. + - max_delta_vertex_cut : later on for vertex isolation + max_delta_vertex_cut=(F.ABS @ (F.CHI2() @ F.FORWARDARG1() - F.CHI2() @ F.FORWARDARG0()) < max_vertex_cut) + Used in https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Phys/RelatedInfoTools/python/IsolationTools/IsolationTools.py?ref_type=heads + - filter_tree_name : string for the isolation particle to store + """ + assert( bhead_label_decay != None and bhead_label_decay != "") + #inspired to https://lhcb-davinci.docs.cern.ch/examples/tupling/option_davinci_tupling_relation_isovariables.html + variables_all = FunctorCollection({}) + #All RD lines are filtering out the signal from the cone online so we can avoid this additional check + #stable_particles = ['L1','L2','mu','K','Pi',"H","Hp",'Hm'] # Do we need to add other stable particles? + + if len(dr2_angle_list) == 0 : + raise RuntimeError("dr2_angle_list must be defined with some angle content value , for example ['1.0' ,...]") + for angle2 in dr2_angle_list: + cone_cut= (F.DR2 < float(angle2)) & ~F.FIND_IN_TREE() + str_angle2 = angle2.replace(".","p") + charged_iso = VertexAndConeIsolation( + name=f"{bhead_label_decay}_ChargedIso_DR2_{str_angle2}_B2MuMu", + reference_particles=data, + related_particles=make_long_pions(), + cut=cone_cut) + neutral_iso = VertexAndConeIsolation( + name=f"{bhead_label_decay}_NeutralIso_DR2_{str_angle2}_B2MuMu", + reference_particles=data, + related_particles=make_photons(), + cut=cone_cut) + cone_iso_variables = FC.ConeIsolation( + charged_cone_isolation_alg=charged_iso, + neutral_cone_isolation_alg=neutral_iso, + array_indx_name=f"{bhead_label_decay}_cone_indx_DR2_{str_angle2}_B2MuMu") + variables_all += cone_iso_variables + + for max_delta_vertex_cut in max_delta_vertex_chi2_cuts : + vertex_cut = F.ALL #(F.ABS @ (F.CHI2() @ F.FORWARDARG1() - F.CHI2() @ F.FORWARDARG0()) < float(max_delta_vertex_cut) ) + str_cut = f"DChi2Vtx_{max_delta_vertex_cut}".replace(".","p") + + OneTrack , TwoTrack = make_OneTrack_TwoTrack_ForIsolation( candidate = data, + extra_particles=make_long_pions(), + bhead_label_decay= bhead_label_decay) + # Add vertex isolation variables with one and two tracks, applying a cut + if max_delta_vertex_cut != "NO": + vtx_cut = (F.CHI2() @ F.FORWARDARG1() < float(max_delta_vertex_cut)) + else: + vtx_cut = F.ALL + + vtxiso_onetrack = VertexAndConeIsolation( + name=f"{bhead_label_decay}_OneTrack_{str_cut}_B2MuMu", + reference_particles=data, + related_particles=OneTrack, + cut= vtx_cut, + ) + vtxiso_twotracks = VertexAndConeIsolation( + name=f"{bhead_label_decay}_TwoTracks_{str_cut}_B2MuMu", + reference_particles=data, + related_particles=TwoTrack, + cut= vtx_cut, + ) + + vtxiso_onetrack_variables = FC.VertexIsolation(isolation_alg=vtxiso_onetrack) + vtxiso_twotracks_variables = FC.VertexIsolation(isolation_alg=vtxiso_twotracks) + variables_all += vtxiso_onetrack_variables + variables_all += vtxiso_twotracks_variables + return variables_all \ No newline at end of file diff --git a/rd_ap_2024/tupling/variables/rd_stream_tupling_functions.py b/rd_ap_2024/tupling/variables/rd_stream_tupling_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..43abfcf7680e11b4ed8899ae0ed042cbc4890444 --- /dev/null +++ b/rd_ap_2024/tupling/variables/rd_stream_tupling_functions.py @@ -0,0 +1,1103 @@ +############################################################################### +# (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +"""Common configuration functions +""" +from rd_ap_2024.utils.log_store import LogStore +from PyConf.components import force_location +from Gaudi.Configuration import INFO +import Functors as F +from Functors.math import log +from PyConf.dataflow import DataHandle # type: ignore[import] +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary +) +from PyConf.Algorithms import DeterministicPrescaler +from DecayTreeFitter import DecayTreeFitter +from FunTuple import FunctorCollection +import Functors.math as fmath +from GaudiKernel.SystemOfUnits import GeV +from DaVinci import Options +# check here, for the DV version in use what can be imported / modified +# https://gitlab.cern.ch/lhcb/DaVinci/-/blob/v64r4/Phys/FunTuple/python/FunTuple/functorcollections.py?ref_type=tags#L1281 + +from FunTuple.functorcollections import ( + Kinematics, + SelectionInfo, + MCVertexInfo, + MCKinematics, + MCPromptDecay, + MCHierarchy, + MCPromptDecay, + MCReconstructed, + MCReconstructible, + MCPrimaries, + MCPrimaryVertexInfo, + EventInfo, + ParticleID, + ChargedCaloInfo, + NeutralCaloInfo, + VertexIsolation, + ConeIsolation, + ParticleIsolation, + DecayTreeFitterResults, + ParticlePVInfo, + HltTisTos, + LHCInfo +) +from FunTuple import FunTuple_Particles as Funtuple +from PyConf.application import metainfo_repos + +from DaVinci.algorithms import create_lines_filter +from PyConf.reading import ( + get_pvs, + get_rec_summary, + ) +from PyConf.Algorithms import ( + WeightedRelTableAlg, + Hlt1TisTosAlg, + Hlt2TisTosAlg, + ThOrParticleSelection + ) +import FunTuple.functorcollections as FC +from GaudiConf.LbExec import HltSourceID +from PyConf.reading import get_decreports, get_hlt1_selreports, get_particles +from PyConf.dataflow import DataHandle + +#swaps +from DaVinciTools import SubstitutePID +from PyConf.Algorithms import ParticleContainerMerger +import numpy as np + +import Functors.math as fmath +from GaudiKernel.SystemOfUnits import GeV + + +#### +from DaVinciMCTools import MCTruthAndBkgCat + + +logger=LogStore.add_logger('rd_ap_2024:rd_stream_tupling_functions') + +def make_truth_variables(options : Options, + data: DataHandle + ) -> FunctorCollection: + mctruth = MCTruthAndBkgCat(data) #, name='MCT') + trueid_bkgcat_info = { + "TRUEKEY": F.VALUE_OR(-1) @ mctruth(F.OBJECT_KEY), + "BKGCAT" : mctruth.BkgCat, + "TRUEID" : F.VALUE_OR(0) @ mctruth(F.PARTICLE_ID), + #"MC_VTX_TYPE": mctruth(F.MC_VTX_Type), + #"MC_VTX_TYPE": F.CAST_TO_INT @ mctruth(F._MC_VTX_TYPE), + #"MC_VTX_TYPE": mctruth(F.MC_VTX_TYPE() @ F.MC_ORIGINVERTEX()), #suggested by Abhijit + #"MC_VTX_TYPE_1": F.VALUE_OR(-1) @ mctruth(F.MC_VTX_TYPE @ F.MC_ORIGINVERTEX), #suggested by + #"MC_VTX_TYPE_2": F.VALUE_OR(-1) @ mctruth(F.MC_VTX_TYPE @ F.ENDVERTEX), #suggested by + } + variables = FunctorCollection(trueid_bkgcat_info) + variables += MCHierarchy(mctruth_alg=mctruth) + variables += MCVertexInfo(mctruth_alg=mctruth) + variables += MCKinematics(mctruth_alg=mctruth) + variables += MCPromptDecay(mctruth_alg=mctruth) + return variables + + +Hlt1_lines = [ + # from Moore: https://gitlab.cern.ch/lhcb/Moore/-/tree/master/Hlt/Hlt1Conf/python/Hlt1Conf/lines?ref_type=heads + # "Hlt1GECPassThrough", # also in Allen + # "Hlt1SingleHighPtMuon", # also in Allen + "Hlt1LowPtMuon", + "Hlt1MicroBiasLowMultVelo", + "Hlt1NoBias", + # "Hlt1TrackMuonMVA", # also in Allen + "Hlt1DiMuonLowMass", + # from Allen: https://gitlab.cern.ch/lhcb/Allen/-/blob/master/configuration/python/AllenConf/HLT1.py + # default physics lines + "Hlt1TrackMVA", + "Hlt1TwoTrackMVA", + "Hlt1D2KK", + "Hlt1D2KPi", + "Hlt1D2PiPi", + # ...with v0s + "Hlt1KsToPiPi", + "Hlt1KsToPiPiDoubleMuonMisID", + "Hlt1TwoTrackKs", + "Hlt1LambdaLLDetachedTrack", + "Hlt1XiOmegaLLL", + # ...with muon + "Hlt1SingleHighPtMuon", + "Hlt1SingleHighPtMuonNoMuID", + "Hlt1DiMuonHighMass", + "Hlt1DiMuonDisplaced", + "Hlt1DiMuonSoft", + "Hlt1TrackMuonMVA", + "Hlt1DiMuonNoIP", + "Hlt1DiMuonNoIP_SS", + "Hlt1DiMuonDrellYan_VLowMass", + "Hlt1DiMuonDrellYan_VLowMass_SS", + "Hlt1DiMuonDrellYan", + "Hlt1DiMuonDrellYan_SS", + "Hlt1DisplacedDiMuon", + "Hlt1OneMuonTrackLine", + "Hlt1LowPtDiMuon", + "Hlt1DetJpsiToMuMuPosTagLine", + "Hlt1DetJpsiToMuMuNegTagLine", + # ...with calo + "Hlt1TrackElectronMVA", + "Hlt1SingleHighPtElectron", + "Hlt1DiElectronDisplaced", + "Hlt1DiPhotonHighMass", + "Hlt1Pi02GammaGamma", + "Hlt1DiElectronHighMass_SS", + "Hlt1DiElectronHighMass", + "Hlt1DiElectronLowMass_massSlice1_prompt", + "Hlt1DiElectronLowMass_massSlice2_prompt", + "Hlt1DiElectronLowMass_massSlice3_prompt", + "Hlt1DiElectronLowMass_massSlice4_prompt", + "Hlt1DiElectronLowMass_massSlice1_displaced", + "Hlt1DiElectronLowMass_massSlice2_displaced", + "Hlt1DiElectronLowMass_massSlice3_displaced", + "Hlt1DiElectronLowMass_massSlice4_displaced", + "Hlt1DiElectronLowMass_SS_massSlice1_prompt", + "Hlt1DiElectronLowMass_SS_massSlice2_prompt", + "Hlt1DiElectronLowMass_SS_massSlice3_prompt", + "Hlt1DiElectronLowMass_SS_massSlice4_prompt", + "Hlt1DiElectronLowMass_SS_massSlice1_displaced", + "Hlt1DiElectronLowMass_SS_massSlice2_displaced", + "Hlt1DiElectronLowMass_SS_massSlice3_displaced", + "Hlt1DiElectronLowMass_SS_massSlice4_displaced", + # odin monitoring lines + "Hlt1ODINLumi", + "Hlt1ODIN1kHzLumi", + "Hlt1ODINCalib", + # Alignment monitoring lines + "Hlt1RICH1Alignment", + "Hlt1RICH2Alignment", + "Hlt1D2KPiAlignment", + "Hlt1Dst2D0PiAlignment", + "Hlt1MaterialVertexSeedsDownstreamz", + "Hlt1MaterialVertexSeeds_DWFS", + # ...with muons + "Hlt1DiMuonJpsiMassAlignment", + # added in setup_hlt1_node function + "Hlt1TAEPassthrough", + "Hlt1ErrorBank", + # currently not included: + # "Hlt1TwoTrackMVACharmXSec", + # "Hlt1DisplacedLeptons", + # "Hlt1SingleHighEt", #-> currently commented out in HLT1.py + # 'Hlt1LowPtDiMuon', +] + +Hlt1_decisions = [line + "Decision" for line in Hlt1_lines] + + +Spruce_decisions = [ + #spruce + f"SpruceRD_BuToHpMuMuDecision", + f"SpruceRD_B0ToHpHmMuMuDecision", + #f"SpruceRD_BuToHpEEDecision", + #f"SpruceRD_B0ToHpHmEEDecision", + #exlc + f"SpruceRD_B0ToKpPimMuMu_2023Decision", + f"SpruceRD_BuToKpMuMu_2023Decision", + f"SpruceRD_B0ToKpPimMuMuDecision", + f"SpruceRD_B0ToKpKmMuMuDecision", + f"SpruceRD_BuToKpMuMuDecision", + f"SpruceRD_BuToKpMuMu_SameSignDecision", + #electrons + #f"SpruceRD_B0ToKpPimEEDecision", + #f"SpruceRD_BuToKpEEDecision", + #f"SpruceRD_B0ToKpKmEEDecision", + #f"SpruceRD_BuToKpEE_SameSignDecision", +] + +Hlt2_topo_decisions = [ + #Topo lines + "Hlt2Topo2BodyDecision", "Hlt2Topo3BodyDecision", + "Hlt2TopoMu2BodyDecision", "Hlt2TopoMu3BodyDecision", +] +Hlt2_topoiddl_decisions = Hlt2_topo_decisions + [ + #Muons cutbased + "Hlt2CutBasedInclDimuonFakeMuMuPlusTwoTrackDecision", + "Hlt2CutBasedInclDimuonPlusTrackDecision", + "Hlt2CutBasedInclDimuonFakeMuPlusTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuMuDecision", + "Hlt2CutBasedInclDimuonPlusTwoTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuMuPlusTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuPlusTrackDecision", + "Hlt2CutBasedInclDimuonSSDecision", + "Hlt2CutBasedInclDimuonPlusTwoTrackDecision", + "Hlt2CutBasedInclDimuonFakeMuPlusTwoTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuMuPlusTrackDecision", + "Hlt2CutBasedInclDimuonDecision", + "Hlt2CutBasedInclDimuonFakeMuSSDecision", + #Muons detached + "Hlt2_InclDetDiMuonDecision", + "Hlt2_InclDetDiMuon_3BodyDecision", + "Hlt2_InclDetDiMuon_4BodyDecision", + # "Hlt2RD_B0ToKpPimMuMu_2023Decision", # not existing + # "Hlt2RD_BuToKpMuMu_2023Decision", # not existing + # "Hlt2RD_B0ToKpPimMuMuDecision" +] +Hlt2_decisions = [ + #RD + # hlt2 + # "Hlt2RD_B0ToKpPimMuMu_2023Decision", # not existing + # "Hlt2RD_BuToKpMuMu_2023Decision", # not existing + "Hlt2RD_B0ToKpPimMuMuDecision", + "Hlt2RD_B0ToKpKmMuMuDecision", + "Hlt2RD_B0ToPipPimMuMuDecision", + "Hlt2RD_BdToKSMuMu_LLDecision", + "Hlt2RD_LambdabToPKMuMuDecision", + "Hlt2RD_BuToHpMuMu_InclDecision", + "Hlt2RD_BuToHpMuMu_Incl_SameSignDecision", + # "Hlt2RD_BuToKpMuMuDecision", # not existing + # "Hlt2RD_BuToKpMuMu_SameSignDecision", # not existing + #electrons + "Hlt2RD_B0ToKpPimEEDecision", + "Hlt2RD_BuToKpEEDecision", + "Hlt2RD_B0ToKpKmEEDecision", + "Hlt2RD_BdToKSEE_LLDecision", + "Hlt2RD_LambdabToPKEEDecision", + "Hlt2RD_BuToKpEE_SameSignDecision", + # hemu_control_modes + # ...muons + 'Hlt2RD_BuToKpJpsi_JpsiToMuMuDecision', + 'Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToMuMuDecision', + # ...electrons + 'Hlt2RD_BuToKpJpsi_JpsiToEEDecision', + 'Hlt2RD_BdToKstJpsi_KstToKpPim_JpsiToEEDecision', + 'Hlt2RD_JpsiToEEDecision', + #generic + "Hlt2_JpsiToMuMuDecision", + "Hlt2_Psi2SToMuMuDecision", + "Hlt2_DiMuonJPsiTightFullDecision", + "Hlt2_DiMuonPsi2STightFullDecision", + # 'Hlt2_JpsiToMuMuDetachedDecision', # not existing + # 'Hlt2_Psi2SToMuMuDetachedDecision', # not existing + # 'Hlt2_DiMuonJPsiTightDecision', # not existing + # B2CC + "Hlt2B2CC_BuToJpsiKplus_JpsiToMuMu_DetachedDecision", + 'Hlt2B2CC_BuToJpsiKplus_JpsiToMuMu_PromptDecision', + 'Hlt2B2CC_BuToJpsiKplus_JpsiToMuMu_DetachedDecision', + 'Hlt2B2CC_BdToJpsiKstar_JpsiToMuMu_DetachedDecision', + 'Hlt2B2CC_BdToJpsiKstar_JpsiToMuMu_PromptDecision', + #'Hlt2B2CC_BdToJpsiKstar_JpsiToEE_DetachedDecision', + #'Hlt2B2CC_BdToJpsiKstar_JpsiToEEDecision', + #'Hlt2B2CC_BuToJpsiKplus_JpsiToEE_DetachedDecision', + #PID lines + #electrons + #'Hlt2PID_BToJpsiK_JpsiToEmEpTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmbremEpTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmEpbremTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpEmTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpEmbremTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpbremEmTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTagged_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmEpTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmbremEpTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmEpbremTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmbremEpbremTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpEmTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpEmbremTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpbremEmTaggedDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpbremEmbremTaggedDecision', + #'Hlt2PID_BToJpsiJpsi_JpsiToEmEp_Tagged_DielectronBrem_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpEm_Tagged_DielectronBrem_noPIDeDecision', + #'Hlt2PID_BToJpsiK_JpsiToEmEp_Tagged_DielectronBremDecision', + #'Hlt2PID_BToJpsiK_JpsiToEpEm_Tagged_DielectronBremDecision', + #muons + 'Hlt2PID_BToJpsiK_JpsiToMuMupTagged_DetachedDecision', + 'Hlt2PID_BToJpsiK_JpsiToMuMumTagged_DetachedDecision', + 'Hlt2PID_JpsiToMuMumTagged_DetachedDecision', + 'Hlt2PID_JpsiToMuMupTagged_DetachedDecision', + #BandQ + 'Hlt2BandQ_DiMuonJPsiHighPTDecision', + 'Hlt2BandQ_BpToJpsiKp_JpsiToMuMuDecision', + #QEE + 'Hlt2QEE_JpsiToMuMu_DetachedDecision', + 'Hlt2QEE_JpsiToMuMu_PromptDecision', + #Topo lines + "Hlt2Topo2BodyDecision", "Hlt2Topo3BodyDecision", + "Hlt2TopoMu2BodyDecision", "Hlt2TopoMu3BodyDecision", + #Muons fake cutbased + "Hlt2CutBasedInclDimuonFakeMuMuPlusTwoTrackDecision", + "Hlt2CutBasedInclDimuonFakeMuPlusTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuMuDecision", + "Hlt2CutBasedInclDimuonFakeMuMuPlusTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuPlusTrackDecision", + "Hlt2CutBasedInclDimuonFakeMuPlusTwoTrackSSDecision", + "Hlt2CutBasedInclDimuonFakeMuMuPlusTrackDecision", + "Hlt2CutBasedInclDimuonFakeMuSSDecision", + #Muons + "Hlt2_InclDetDiMuonDecision", + "Hlt2_InclDetDiMuon_3BodyDecision", + "Hlt2CutBasedInclDimuonDecision", + "Hlt2CutBasedInclDimuonPlusTrackDecision", + "Hlt2_InclDetDiMuon_4BodyDecision", + "Hlt2_InclDetDiMuon_neutralDecision", + "Hlt2CutBasedInclDimuonPlusTwoTrackDecision", + #Muons SS + "Hlt2_InclDetDiMuon_SSDecision", + "Hlt2_InclDetDiMuon_3Body_SSDecision", + "Hlt2CutBasedInclDimuonSSDecision", + "Hlt2CutBasedInclDimuonPlusTrackSSDecision", + "Hlt2_InclDetDiMuon_4Body_SSDecision", + "Hlt2_InclDetDiMuon_neutral_SSDecision", + "Hlt2CutBasedInclDimuonPlusTwoTrackSSDecision", + #Electrons + "Hlt2_InclDetDiElectronDecision", + "Hlt2_InclDetDiElectron_3BodyDecision", + "Hlt2CutBasedInclDielectronDecision", + "Hlt2CutBasedInclDielectronPlusTrackDecision", + "Hlt2_InclDetDiElectron_4BodyDecision", + "Hlt2_InclDetDiElectron_neutralDecision", + "Hlt2CutBasedInclDielectronPlusTwoTrackDecision", + #Electrons SS + "Hlt2_InclDetDiElectron_SSDecision", + "Hlt2_InclDetDiElectron_3Body_SSDecision", + "Hlt2CutBasedInclDielectronSSDecision", + "Hlt2CutBasedInclDielectronPlusTrackSSDecision", + "Hlt2_InclDetDiElectron_4Body_SSDecision", + "Hlt2_InclDetDiElectron_neutral_SSDecision", + "Hlt2CutBasedInclDielectronPlusTwoTrackSSDecision", + #MuE + "Hlt2_InclDetDiMuEDecision", + "Hlt2_InclDetDiMuE_3BodyDecision", + "Hlt2CutBasedInclElectronMuonDecision", + "Hlt2CutBasedInclElectronMuonPlusTrackDecision", + "Hlt2_InclDetDiMuE_4BodyDecision", + "Hlt2_InclDetDiMuE_neutralDecision", + "Hlt2CutBasedInclElectronMuonPlusTwoTrackDecision", + #MuE SS + "Hlt2_InclDetDiMuE_SSDecision", + "Hlt2_InclDetDiMuE_3Body_SSDecision", + "Hlt2CutBasedInclElectronMuonSSDecision", + "Hlt2CutBasedInclElectronMuonPlusTrackSSDecision", + "Hlt2_InclDetDiMuE_4Body_SSDecision", + "Hlt2_InclDetDiMuE_neutral_SSDecision", + "Hlt2CutBasedInclElectronMuonPlusTwoTrackSSDecision", +] + +def sum_hh(functor): + return F.CHILD(1, F.SUM(functor)) + F.CHILD(2, functor) +def sum_hhh(functor): + return F.CHILD(1, F.CHILD(1, F.SUM(functor))) + F.CHILD(1, F.CHILD(2, functor)) + F.CHILD(2, functor) + +def make_composite_variables(options : Options, data: DataHandle, v2_pvs: DataHandle, simulation : bool =False , MCTRUTH: MCTruthAndBkgCat=None, EndVertex: bool = True) -> FunctorCollection: + logger.debug("---------- make_composite_variables -------------") + ### some composite are done with VertexFitter, so a vertex exist , others with just ParticleAdder, no vertex made [e.g. Sigma -> p pi0] + variables = ( + FunctorCollection( + { + #kinematic vars + "MAX_PT" : F.MAX(F.PT), + "MIN_PT" : F.MIN(F.PT), + "SUM_PT" : F.SUM(F.PT), + "MAX_P" : F.MAX(F.P), + "MIN_P" : F.MIN(F.P), + "ETA" : F.ETA, + "PHI" : F.PHI, + "CHI2" : F.CHI2, + "CHI2DOF" : F.CHI2DOF, + #property vars + "ID" : F.PARTICLE_ID, + "KEY" : F.OBJECT_KEY, + "BPVX" : F.BPVX( v2_pvs), + "BPVY" : F.BPVY( v2_pvs), + "BPVZ" : F.BPVZ( v2_pvs), + "BPVIP" : F.BPVIP( v2_pvs), + "BPVIPCHI2" : F.BPVIPCHI2( v2_pvs), + "MAX_BPVIPCHI2": F.MAX(F.BPVIPCHI2( v2_pvs)), + "MIN_BPVIPCHI2": F.MIN(F.BPVIPCHI2( v2_pvs)), + # "OWNPVIPCHI2" : F.OWNPVIPCHI2, + # "OWNPVX" : F.OWNPVX, + # "OWNPVY" : F.OWNPVY, + # "OWNPVZ" : F.OWNPVZ, + # "OWNPV_COV" : F.COV + # "ALLPV_X[nPV]" : F.ALLPVX(v2_pvs), + # "ALLPV_Y[nPV]" : F.ALLPVY(v2_pvs), + # "ALLPV_Z[nPV]" : F.ALLPVZ(v2_pvs), + # "ALLPV_NDOF[nPV]" : F.MAP(F.NDOF) @ F.TES(v2_pvs), + # "ALLPV_CHI2[nPV]" : F.MAP(F.CHI2) @ F.TES(v2_pvs), + # "ALLPV_CHI2NDOF[nPV]": F.MAP(F.CHI2DOF) @ F.TES(v2_pvs), + # "ALLPV_FD[nPV]" : F.ALLPV_FD(v2_pvs), + # "ALLPV_IP[nPV]" : F.ALLPV_IP(v2_pvs), + } + ) + Kinematics() + ) + if EndVertex == True : + variables+= FunctorCollection({ + "BPVCORRM" : F.BPVCORRM( v2_pvs), + "BPVCORRMERR" : F.BPVCORRMERR( v2_pvs), + "BPVDIRA" : F.BPVDIRA( v2_pvs), + "BPVDLS" : F.BPVDLS( v2_pvs), + "BPVETA" : F.BPVETA( v2_pvs), + "BPVFD" : F.BPVFD( v2_pvs), + "BPVFDCHI2" : F.BPVFDCHI2( v2_pvs), + "BPVFDIR" : F.BPVFDIR( v2_pvs), + "BPVFDVEC" : F.BPVFDVEC( v2_pvs), + "BPVLTIME" : F.BPVLTIME( v2_pvs), + "ENDVERTEX_CHI2DOF": F.CHI2DOF @ F.ENDVERTEX, #to be careful, not all composites have ENDVTX_CHIDOF + "END_VX" : F.END_VX, + "END_VY" : F.END_VY, + "END_VZ" : F.END_VZ, + "BPVVDRHO" : F.BPVVDRHO( v2_pvs), + #geometry vars + "ALV" : F.ALV(1,2), + "MAXDOCACHI2" : F.MAXDOCACHI2, + "MAXDOCA" : F.MAXDOCA, + "MAXSDOCACHI2": F.MAXSDOCACHI2, + "MAXSDOCA" : F.MAXSDOCA, + # "R_BPVCORRM" : F.CHILD(1, F.BPVCORRM(v2_pvs)), + # "R_ALV" : F.CHILD(1, F.ALV(1,2)), #? + # "DOCA" : F.CHILD(1, F.SDOCA(1,2)), + } + ) + + variables += HltTisTos(selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=data) + # ONLY FOR make_composite calls (i.e the B and J/Psi )and for data and full- MC to recheck what to do + # TODO : what to do on MC? + if options.input_process == "Spruce" and options.simulation == False and options.input_stream == "rd": + # ONLY FOR FULL Sprucing with RD lines... should prevent the Spruce for Turcal to add this. + logger.debug("Adding HltTisTos HLT2 variables") + variables += HltTisTos(selection_type="Hlt2", trigger_lines=Hlt2_topoiddl_decisions, data=data) + if simulation and MCTRUTH: + variables += make_truth_matching_variables(options= options, data=data, MCTRUTH=MCTRUTH) + # if 'turcal' not in options.input_stream : + else: + #different because most likely the right information was not saved during HLT2? Using the line for simulation breaks with error: + #ERROR Hlt2TisTosAlg::operator() : Couldnt locate the trigger candidates for line Hlt2_InclDetDiMuonDecision. Please check! + #variables += HltTisTos(selection_type="Hlt2", trigger_lines=Hlt2_topo_decisions, data=data) + pass + return variables + +def make_intermediate_resonances_variables(options : Options, data : DataHandle, v2_pvs: DataHandle , ndau : int = 2 , EndVertex : bool = True ) -> FunctorCollection: + logger.debug("---------- make_intermediate_resonances_variables -------------") + + variables = FunctorCollection( { + "BPVX": F.BPVX(v2_pvs), + "BPVY": F.BPVY(v2_pvs), + "BPVZ": F.BPVZ(v2_pvs), + "BPVIP": F.BPVIP(v2_pvs), + "MAX_BPVIP": F.MAX(F.BPVIP(v2_pvs)), + "MIN_BPVIP": F.MIN(F.BPVIP(v2_pvs)), + "MAX_BPVIPCHI2": F.MAX(F.BPVIPCHI2(v2_pvs)), + "MIN_BPVIPCHI2": F.MIN(F.BPVIPCHI2(v2_pvs)), + "MINIPCHI2" : F.MINIPCHI2(v2_pvs) + }) + if EndVertex: + variables+= FunctorCollection({ + "BPVCHI2DOF" : F.CHI2DOF @ F.BPV(v2_pvs), + "BPVFDCHI2" : F.BPVFDCHI2(v2_pvs), + "BPVFD" : F.BPVFD(v2_pvs), + "BPVLTIME" : F.BPVLTIME(v2_pvs), + "BPVDIRA" : F.BPVDIRA(v2_pvs), + "END_VX": F.END_VX, + "END_VY": F.END_VY, + "END_VZ": F.END_VZ, + "END_VCHI2DOF" : F.CHI2DOF @ F.ENDVERTEX, + "END_VCOV" : F.POS_COV_MATRIX @ F.ENDVERTEX, + "END_NDOF" : F.NDOF @ F.ENDVERTEX, + "CHI2DOF" : F.CHI2DOF, + "CHI2" : F.CHI2, + "BPVVDRHO" : F.BPVVDRHO(v2_pvs), + "BPVVDZ" : F.BPVVDZ(v2_pvs), + }) + + if EndVertex : + variables+= FunctorCollection({ + "MAX_BPVIPCHI2": F.MAX(F.BPVIPCHI2(v2_pvs)), + "MIN_BPVIPCHI2": F.MIN(F.BPVIPCHI2(v2_pvs)), + "BPVFDCHI2": F.BPVFDCHI2(v2_pvs), + "BPVFD": F.BPVFD(v2_pvs), + "BPVLTIME": F.BPVLTIME(v2_pvs), + "BPVDIRA": F.BPVDIRA(v2_pvs), + "BPVVDRHO": F.BPVVDRHO(v2_pvs), + "BPVVDZ": F.BPVVDZ(v2_pvs), + "MAXDOCACHI2": F.MAXDOCACHI2, + "MAXDOCA": F.MAXDOCA, + "MAXSDOCACHI2": F.MAXSDOCACHI2, + "MAXSDOCA": F.MAXSDOCA, + }) + variables+= FunctorCollection( { + "MAX_PT": F.MAX(F.PT), + "MIN_PT": F.MIN(F.PT), + "SUM_PT": F.SUM(F.PT), + "MAX_P" : F.MAX(F.P), + "MIN_P" : F.MIN(F.P), + #"KEY" : F.OBJECT_KEY, + }) + + if ndau >= 2 and EndVertex: + variables+= FunctorCollection({ + "ALV12" : F.ALV(1,2) , + "DOCA12" : F.DOCA(1,2) , + "DOCACHI2_12" : F.DOCACHI2(1,2) , + "SDOCA12" : F.SDOCA(1,2), + }) + if ndau >= 3 and EndVertex: + variables+= FunctorCollection({ + "ALV13" : F.ALV(1,3), + "DOCA13" : F.DOCA(1,3), + "SDOCA13" : F.SDOCA(1,3), + "DOCACHI2_13" : F.DOCACHI2(1,3) , + "ALV23" : F.ALV(2,3), + "DOCA23" : F.DOCA(2,3), + "SDOCA23" : F.SDOCA(2,3), + "DOCACHI2_23" : F.DOCACHI2(2,3) + }) + if ndau >= 4 and EndVertex: + variables+= FunctorCollection({ + "ALV14" : F.ALV(1,4), + "DOCA14" : F.DOCA(1,4), + "SDOCA14" : F.SDOCA(1,4), + "DOCACHI2_14" : F.DOCACHI2(1,4), + "ALV24" : F.ALV(2,4), + "DOCA24" : F.DOCA(2,4), + "SDOCA24" : F.SDOCA(2,4), + "DOCACHI2_24" : F.DOCACHI2(2,4), + "ALV34" : F.ALV(3,4), + "DOCA34" : F.DOCA(3,4), + "SDOCA34" : F.SDOCA(3,4), + "DOCACHI2_34" : F.DOCACHI2(3,4) + }) + return variables + + +################################################################################# +# Create some variable using the substitute dictionary and the subpid functionality +# TODO : document functionality and use - case +################################################################################# +def make_variables_with_swapped_mass_hypothesis(options : Options, substitution_dict :dict , v2_pvs : DataHandle) -> FunctorCollection: + logger.debug("---------- make_variables_with_swapped_mass_hypothesis -------------") + variables_all = FunctorCollection({}) + for iname, sub_dict in substitution_dict.items(): + substitutions = sub_dict["substitutions"] + subpid = sub_dict['swapped_container'] + variables_all += FunctorCollection( + { + # f"{iname}_M" : subpid(F.MASS), + # f"{iname}_P" : subpid(F.P), + # f"{iname}_PT" : subpid(F.PT), + f"{iname}_PX" : subpid(F.PX), + f"{iname}_PY" : subpid(F.PY), + f"{iname}_PZ" : subpid(F.PZ), + f"{iname}_ENERGY": subpid(F.ENERGY)} + ) + return variables_all + +################################################################################# +# Add the truth matching information to tuples +################################################################################# +def make_truth_matching_variables( + options : Options , + data : DataHandle, + MCTRUTH : MCTruthAndBkgCat, + hierarchy : bool =True, + kinematics : bool =True, + vertex_info : bool =True, + bkgcat : bool =True, + prompt_info : bool =True, + ) -> FunctorCollection: + """Add MC truth matching functors to an existing FunctorCollection. + Args: + options (DaVinci.Options): DaVinci options object. + variables (FunctorCollection): FunctorCollection to modify + data: data handle + hierarchy (bool): Add MCHierarchy info (default True) + kinematics (bool): Add MCKinematics info (default True) + vertex_info (bool): Add MCVertexInfo (default True) + bkgcat (bool): Add TRUEKEY and BKGCAT functors - intended for composite particles (default False) + prompt_info (bool): Add MCPromptDecay info (default True) + Returns: + FunctorCollection: modified FunctorCollection with truth matched variables. + """ + + assert ( + options.simulation + ), "options.simulation is set to False - it doesn't make sense to add truth matching." + + variables = FunctorCollection({}) + if bkgcat: + variables += FunctorCollection( + { + # "TRUEKEY": F.VALUE_OR(-1) @ MCTRUTH(F.OBJECT_KEY), + "TRUEID": F.VALUE_OR(0) @ MCTRUTH(F.PARTICLE_ID), + # "TRUEKEY": F.VALUE_OR(-1) @ MCTRUTH(F.OBJECT_KEY), + "BKGCAT": MCTRUTH.BkgCat, + } + ) + if hierarchy: variables += MCHierarchy( mctruth_alg=MCTRUTH) # likely to change again!! + if vertex_info: variables += MCVertexInfo( mctruth_alg=MCTRUTH) # likely to change again!! + if kinematics: variables += MCKinematics( mctruth_alg=MCTRUTH) # likely to change again!! + if prompt_info: variables += MCPromptDecay(mctruth_alg=MCTRUTH) # likely to change again!! + + return variables + + +################################################################################# +# Basic variables maker +# ID +# ETA +# PHI +# BPVIPCHI2 +# MINIPCHI2 +# ALLPV_IP +# BPVX +# BPVY +# BPVZ +# Kinematic Functor collections (depends on DV version, but for example +# https://gitlab.cern.ch/lhcb/DaVinci/-/blob/v64r8/Phys/FunTuple/python/FunTuple/functorcollections.py?ref_type=tags#L304 +# If simulation and truth info, it adds the truth_matching_variables +# It also add the TISTOS of the HLT1 lines (not HLT2) +################################################################################# +def make_basic_variables(options : Options, data : DataHandle, v2_pvs : DataHandle, simulation : bool =False, MCTRUTH: MCTruthAndBkgCat=None) -> FunctorCollection: + logger.debug("---------- make_basic_variables -------------") + variables = ( + FunctorCollection({ + "ID": F.PARTICLE_ID, + "CHARGE": F.CHARGE, + "ETA": F.ETA, + "PHI": F.PHI, + "BPVIP" : F.BPVIP(v2_pvs), + "BPVIPCHI2": F.BPVIPCHI2(v2_pvs), + "MINIPCHI2": F.MINIPCHI2(v2_pvs), + "BPVX": F.BPVX(v2_pvs), + "BPVY": F.BPVY(v2_pvs), + "BPVZ": F.BPVZ(v2_pvs), + "ALLPV_IP" : F.ALLPV_IP( v2_pvs), + # TO ADD ? + # "ALLPV_X[nPV]" : F.ALLPVX(v2_pvs), + # "ALLPV_Y[nPV]" : F.ALLPVY(v2_pvs), + # "ALLPV_Z[nPV]" : F.ALLPVZ(v2_pvs), + # "ALLPV_NDOF[nPV]" : F.MAP(F.NDOF) @ F.TES(v2_pvs), + # "ALLPV_CHI2[nPV]" : F.MAP(F.CHI2) @ F.TES(v2_pvs), + # "ALLPV_CHI2NDOF[nPV]": F.MAP(F.CHI2DOF) @ F.TES(v2_pvs), + # "ALLPV_FD[nPV]" : F.ALLPV_FD(v2_pvs), + # "ALLPV_IP[nPV]" : F.ALLPV_IP(v2_pvs), + })) + Kinematics() + + variables += HltTisTos(selection_type="Hlt1", trigger_lines=Hlt1_decisions, data=data) + # logger.info(options) + if simulation and MCTRUTH: + variables+= make_truth_matching_variables( options= options, data=data, MCTRUTH=MCTRUTH) + return variables + + +################################################################################# +# Track Variable(s), final states particles +# TODO : document functionality and use - case +################################################################################# +def make_track_variables(options : Options, data : DataHandle, extrapolate: bool =True, bremvars : bool = True ) -> FunctorCollection: + _ParticleID = (FunctorCollection({ + "ID" : F.PARTICLE_ID, #Will be duplicate to PARTICLE_ID in make_basic_variable, one of the 2 used + # "PROBNN_D": F.PROBNN_D, #not tuned, always empty + "PROBNN_E": F.PROBNN_E, + "PROBNN_GHOST": F.PROBNN_GHOST, + "PROBNN_K": F.PROBNN_K, + "PROBNN_MU": F.PROBNN_MU, + "PROBNN_P": F.PROBNN_P, + "PROBNN_PI": F.PROBNN_PI, + "PID_E": F.PID_E, + "PID_K": F.PID_K, + "PID_MU": F.PID_MU, + "PID_P": F.PID_P, + # "PID_PI": F.PID_PI #no sense, DLL(pi) =0 always. + })) + + _RichPIDInfo = (FunctorCollection({ + "PPHASRICH" : F.PPHASRICH @ F.PROTOPARTICLE, + "RICH1_GAS_USED" : F.RICH1_GAS_USED, + "RICH2_GAS_USED" : F.RICH2_GAS_USED, + "RICH_DLL_BT" : F.RICH_DLL_BT, + "RICH_DLL_E" : F.RICH_DLL_E, + "RICH_DLL_K" : F.RICH_DLL_K, + "RICH_DLL_MU" : F.RICH_DLL_MU, + "RICH_DLL_P" : F.RICH_DLL_P, + # "RICH_DLL_D" : F.RICH_DLL_D, not tuned + # "RICH_DLL_PI" : F.RICH_DLL_PI, no sense, always zero + "RICH_SCALED_DLL_E" : F.RICH_SCALED_DLL_E, + "RICH_SCALED_DLL_MU" : F.RICH_SCALED_DLL_MU, + "RICH_THRESHOLD_DE" : F.RICH_THRESHOLD_DE, + "RICH_THRESHOLD_EL" : F.RICH_THRESHOLD_EL, + "RICH_THRESHOLD_KA" : F.RICH_THRESHOLD_KA, + "RICH_THRESHOLD_MU" : F.RICH_THRESHOLD_MU, + "RICH_THRESHOLD_PI" : F.RICH_THRESHOLD_PI, + "RICH_THRESHOLD_PR" : F.RICH_THRESHOLD_PR + })) + + _MuonIDInfo = (FunctorCollection({ + "PPHASMUONINFO": F.PPHASMUONINFO @ F.PROTOPARTICLE, + "INMUON" : F.INMUON, + "ISMUON" : F.ISMUON, + "ISMUONTIGHT" : F.ISMUONTIGHT, + "MUONCATBOOST" : F.MUONCATBOOST, + "MUONCHI2CORR" : F.MUONCHI2CORR, + "MUONLLBG" : F.MUONLLBG, + "MUONLLMU" : F.MUONLLMU + })) + _NeutralCaloInfo = NeutralCaloInfo(extra_info = True) + # _chargedCaloInfo = ChargedCaloInfo(extra_info = True) # not needed, transcripted below + + if bremvars : + _ChargedCaloInfo = (FunctorCollection({ + "IS_NOT_H" : F.IS_NOT_H, + "IS_PHOTON" : F.IS_PHOTON, + "INECAL" : F.INECAL, + "INHCAL" : F.INHCAL, + "INBREM" : F.INBREM, + "HASBREM" : F.HASBREM, + "HASBREMADDED" : F.HASBREMADDED, + "BREMENERGY" : F.BREMENERGY, + "BREMPIDE" : F.BREMPIDE, + "ECALPIDE" : F.ECALPIDE, + "ECALPIDMU" : F.ECALPIDMU, + "HCALPIDE" : F.HCALPIDE, + "HCALPIDMU" : F.HCALPIDMU, + "CLUSTERAREA" : F.CALOCELLID_AREA @ F._CLUSTERID, + "ELECTRONAREA" : F.CALOCELLID_AREA @ F._ELECTRONID, + "BREMHYPOAREA" : F.CALOCELLID_AREA @ F._BREMHYPOID, + "CLUSTERID" : F.CLUSTERID, + "CLUSTERROW" : F.CALOCELLID_ROW @ F._CLUSTERID, + "CLUSTERCOL" : F.CALOCELLID_COLUMN @ F._CLUSTERID, + "CLUSTERMATCH_CHI2" : F.CLUSTERMATCH_CHI2, + "ELECTRONSHOWEREOP" : F.ELECTRONSHOWEREOP, + "ELECTRONSHOWERDLL" : F.ELECTRONSHOWERDLL, + "ELECTRONMATCH_CHI2" : F.ELECTRONMATCH_CHI2, + "ELECTRONENERGY" : F.ELECTRONENERGY, + "ELECTRONROW" : F.CALOCELLID_ROW @ F._ELECTRONID, + "ELECTRONCOL" : F.CALOCELLID_COLUMN @ F._ELECTRONID, + "ELECTRONID" : F.ELECTRONID, + "BREMBENDCORR" : F.BREMBENDCORR, + "BREMHYPOID" : F.BREMHYPOID, + "BREMHYPOROW" : F.CALOCELLID_ROW @ F._BREMHYPOID, + "BREMHYPOCOL" : F.CALOCELLID_COLUMN @ F._BREMHYPOID, + "BREMHYPOMATCH_CHI2" : F.BREMHYPOMATCH_CHI2, + "BREMHYPOENERGY" : F.BREMHYPOENERGY, + "BREMHYPODELTAX" : F.BREMHYPODELTAX, + "BREMTRACKBASEDENERGY" : F.BREMTRACKBASEDENERGY, + "HCALEOP" : F.HCALEOP + })) + else: + _ChargedCaloInfo = (FunctorCollection({ + "INECAL" : F.INECAL, + "INHCAL" : F.INHCAL, + "INBREM" : F.INBREM, + })) + + #https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Phys/FunctorCore/python/Functors/__init__.py + _TrackingInfo = (FunctorCollection( { + "NVPHITSA" : F.VALUE_OR(-1) @ F.NVPHITSA @ F.TRACK , # Return number of hits in VELO A-side + "NVPHITSC" : F.VALUE_OR(-1) @ F.NVPHITSC @ F.TRACK , # Return number of hits in VELO C-side + "NVPOVERLAP" : F.VALUE_OR(-1) @ F.NVPHITSC @ F.TRACK , # Return number of overlap hits in VELO + "NHITS" : F.VALUE_OR(-1) @ F.NHITS @ F.TRACK, + "NVPHITS" : F.VALUE_OR(-1) @ F.NVPHITS @ F.TRACK, # VeloPixel hits + "NUTHITS" : F.VALUE_OR(-1) @ F.NUTHITS @ F.TRACK, # UpstreamTracker hits + "NFTHITS" : F.VALUE_OR(-1) @ F.NFTHITS @ F.TRACK, # ForwardTracker hits + "TRCHI2DOF" : F.VALUE_OR(-1) @ F.CHI2DOF @ F.TRACK, + "CHI2DOF" : F.CHI2DOF, + "TRGHOSTPROB" : F.GHOSTPROB, + "QOVERP" : F.QOVERP @ F.TRACK, + "TRACKTYPE" : F.VALUE_OR(-1) @ F.TRACKTYPE @ F.TRACK, + #"TRACKHAST" : F.VALUE_OR(-1) @ F.TRACKHAST @ F.TRACK, + #"TRACKHASUT" : F.VALUE_OR(-1) @ F.TRACKHASUT @ F.TRACK, + #"TRACKHASVELO": F.VALUE_OR(-1) @ F.TRACKHASVELO @ F.TRACK, + #"TRACKHISTORY": F.VALUE_OR(-1) @ F.TRACKHISTORY @ F.TRACK, + "TRACKISCLONE": F.VALUE_OR(-1) @ F.TRACKISCLONE @ F.TRACK, + #"TRACKISDOWNSTREAM": F.VALUE_OR(-1) @ F.TRACKISDOWNSTREAM @ F.TRACK, + "TRACKISINVALID": F.VALUE_OR(-1) @ F.TRACKISINVALID @ F.TRACK, + #"TRACKISLONG": F.VALUE_OR(-1) @ F.TRACKISLONG @ F.TRACK, + "TRACKISSELECTED": F.VALUE_OR(-1) @ F.TRACKISSELECTED @ F.TRACK, + #"TRACKISTTRACK": F.VALUE_OR(-1) @ F.TRACKISTTRACK @ F.TRACK, + #"TRACKISUPSTREAM": F.VALUE_OR(-1) @ F.TRACKISUPSTREAM @ F.TRACK, + #"TRACKISVELO": F.VALUE_OR(-1) @ F.TRACKISVELO @ F.TRACK, + #"TRACKISVELOBACKWARD": F.VALUE_OR(-1) @ F.TRACKISVELOBACKWARD @ F.TRACK, + "TRACK_PX": F.VALUE_OR(-1) @ F.PX @ F.TRACK, + "TRACK_PY": F.VALUE_OR(-1) @ F.PY @ F.TRACK, + "TRACK_PZ": F.VALUE_OR(-1) @ F.PZ @ F.TRACK, + "TRACK_P": F.VALUE_OR(-1) @ F.P @ F.TRACK, + # "TRACK_PT": F.VALUE_OR(-1) @ F.PT @ F.TRACK, can always be computed offline + # "TX": F.TX, just ratio of px/pz if needed with track or no track... + #"TY": F.TY, just ratio of py/pz if needed + # "KEY": F.OBJECT_KEY, useless + })) + _TrackingInfo+= (FunctorCollection( { + "THREE_MOM_COV" : F.THREE_MOM_COV_MATRIX, + "THREE_MOM_COV_WITHBREM" : F.THREE_MOM_COV_MATRIX @ F.WITH_BREM, + "THREE_MOM_POS_COV" : F.THREE_MOM_POS_COV_MATRIX, + "THREE_MOM_POS_COV_WITHBREM" : F.THREE_MOM_POS_COV_MATRIX @ F.WITH_BREM, + "MOM_POS_COV_MATRIX" : F.MOM_POS_COV_MATRIX, + "MOM_POS_COV_MATRIX_WITHBREM" : F.MOM_POS_COV_MATRIX @ F.WITH_BREM, + "POS_COV_MATRIX" : F.POS_COV_MATRIX, + "POS_COV_MATRIX_WITHBREM" : F.POS_COV_MATRIX @ F.WITH_BREM, + "STATEAT_FirstMeasurement" : F.STATE_AT( "FirstMeasurement") @ F.TRACK, + "STATEAT_LastMeasurement" : F.STATE_AT( "LastMeasurement") @ F.TRACK + })) + if extrapolate: + _TrackingInfo+=(FunctorCollection({ + # https://mattermost.web.cern.ch/lhcb/pl/zpg7hc3uetr7jqo34rxmpa8bwr + # On Long tracks + # Needs new release of DV later than v64r7 + # See Gerhard messages https://mattermost.web.cern.ch/lhcb/pl/h63i7hkrbjra5gigxutd8p395e + # Fixed in DaVinci v64r10 onwards + # https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/TrackEvent/include/Event/StateParameters.h + # namespace LHCb { + # /// Pre-defined z-positions of states for certain State locations + # /// (see Location enum in State.h) + # [[nodiscard]] constexpr std::optional<double> Z( State::Location location ) { + # switch ( location ) { + # case State::Location::EndVelo: + # return 770. * Gaudi::Units::mm; + # case State::Location::BegRich1: + # return 990. * Gaudi::Units::mm; + # case State::Location::EndRich1: + # return 2165. * Gaudi::Units::mm; + # case State::Location::EndUT: + # return 2700. * Gaudi::Units::mm; + # case State::Location::BegT: + # return 7500. * Gaudi::Units::mm; + # case State::Location::EndT: + # return 9410. * Gaudi::Units::mm; + # case State::Location::BegRich2: + # return 9450. * Gaudi::Units::mm; + # case State::Location::EndRich2: + # return 11900. * Gaudi::Units::mm; + # default: + # return std::nullopt; + # } + # }; + # } // namespace LHCb + # namespace /*[[deprecated]]*/ StateParameters { + # constexpr double ZEndVelo = LHCb::Z( LHCb::State::Location::EndVelo ).value(); + # constexpr double ZBegRich1 = LHCb::Z( LHCb::State::Location::BegRich1 ).value(); + # constexpr double ZEndRich1 = LHCb::Z( LHCb::State::Location::EndRich1 ).value(); + # constexpr double ZMidUT = 2485. * Gaudi::Units::mm; // no matching State::Location... + # constexpr double ZEndUT = LHCb::Z( LHCb::State::Location::EndUT ).value(); + # constexpr double ZBegT = LHCb::Z( LHCb::State::Location::BegT ).value(); + # constexpr double ZMidT = 8520. * Gaudi::Units::mm; // no matching State::Location... + # constexpr double ZEndT = LHCb::Z( LHCb::State::Location::EndT ).value(); + # constexpr double ZBegRich2 = LHCb::Z( LHCb::State::Location::BegRich2 ).value(); + # constexpr double ZEndRich2 = LHCb::Z( LHCb::State::Location::EndRich2 ).value(); + # } // namespace StateParameters + # For ECAL , see https://gitlab.cern.ch/lhcb/Detector/-/blob/master/compact/components/ECAL/2024-v00.00/parameters.xml#L189 + # Note those parameters for detector locations are expectations at a given z but the actual real intersection positions s + # hould be derived by geometry conditions or you need to extrapolate offline the states to have a more accurate x,y,tx,ty predictions + #"STATEAT_FirstMeasurement" : F.STATE_AT( "FirstMeasurement") @ F.TRACK, + #"STATEAT_LastMeasurement" : F.STATE_AT( "LastMeasurement") @ F.TRACK, + "STATEAT_EndVelo" : F.EXTRAPOLATE_TRACK(770.0) @ F.TRACK , + "STATEAT_BegRich1" : F.EXTRAPOLATE_TRACK(990.0) @ F.TRACK , + "STATEAT_EndRich1" : F.EXTRAPOLATE_TRACK(2165.0) @ F.TRACK , + "STATEAT_EndUT" : F.EXTRAPOLATE_TRACK(2700.0) @ F.TRACK , + "STATEAT_BegT" : F.EXTRAPOLATE_TRACK(7500.0) @ F.TRACK , + "STATEAT_EndT" : F.EXTRAPOLATE_TRACK(9410.0) @ F.TRACK , + "STATEAT_EndRich2" : F.EXTRAPOLATE_TRACK(11900.0) @ F.TRACK , + "STATEAT_Ecal" : F.EXTRAPOLATE_TRACK(12520.0) @ F.TRACK , + "STATEAT_Muon_M2" : F.EXTRAPOLATE_TRACK(15100.0) @ F.TRACK + # Other states always saved for down/long tracks? + })) + # covariances for tracks objects + # similar to what used to be stored in + # https://gitlab.cern.ch/LHCb-RD/ewp-rkstz/-/blob/master/tuples/davinci/dvDictionaries.py#L728 + + variables = _ParticleID + variables+= _RichPIDInfo + variables+= _MuonIDInfo + variables+= _NeutralCaloInfo + variables+= _ChargedCaloInfo + variables+= _TrackingInfo + return variables + +################################################################################# +# Event And HLT variables +# TODO : document functionality and use - case +################################################################################# +def make_hlt_event_variables(options : Options, line_name : str , v2_pvs = None ) -> FunctorCollection: + logger.debug("----- make_hlt_event_variables -----") + #get ODIN and DecReports location + odin = get_odin() + rec_summary = get_rec_summary() + hlt2_dec = get_decreports("Hlt2") + #event level variables + # + #check Here for RECSUMMARY_INFO https://gitlab.cern.ch/lhcb/LHCb/-/blob/v55r7/Event/RecEvent/include/Event/RecSummary.h?ref_type=tags + #here the ones actually filled https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Rec/RecAlgs/src/RecSummaryMaker.cpp?ref_type=heads + evt_variables = FunctorCollection({ + "EVENTTYPE" : F.EVENTTYPE(odin), + # "Hlt2_TCK" : F.TCK(hlt2_dec), --> SelectionInfo makes it + "nPVs" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nPVs"), + "nFTClusters" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nFTClusters"), + "nVPClusters" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nVPClusters"), + "nEcalClusters" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nEcalClusters"), + "eCalTot" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "eCalTot"), + "hCalTot" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "hCalTot"), + "nLongTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nLongTracks"), + "nDownstreamTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nDownstreamTracks"), + "nUpstreamTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nUpstreamTracks"), + "nTTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nTTracks"), + "nVeloTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nVeloTracks"), + "nBackTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nBackTracks"), + # + "nRich1Hits" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nRich1Hits"), + "nRich2Hits" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nRich2Hits"), + # "nTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nTracks"), + # "nGhosts" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nGhosts"), + # "nMuonCoordsS0" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nMuonCoordsS0"), + "nMuonCoordsS1" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nMuonCoordsS1"), + "nMuonCoordsS2" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nMuonCoordsS2"), + "nMuonCoordsS3" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nMuonCoordsS3"), + "nMuonCoordsS4" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nMuonCoordsS4"), + # "nMuonTracks" : F.VALUE_OR(-1) @ F.RECSUMMARY_INFO( rec_summary, "nMuonTracks") + #"Hlt2_DECISIONS" : F.DECREPORTS_FILTER(DecReports=hlt2_dec, Lines=hlt2_lines), + #TODO : understand what to do with it + }) + if v2_pvs is not None : + evt_variables += FunctorCollection( { + "PV_SIZE" : F.SIZE( v2_pvs) + }) + evt_variables += EventInfo() + if not(options.simulation) : + evt_variables += LHCInfo(extra_info=True) + # evt_variables += SelectionInfo(selection_type="Hlt2", trigger_lines=Hlt2_decisions) + evt_variables += SelectionInfo(selection_type="Hlt1", trigger_lines=Hlt1_decisions) + #evt_variables += SelectionInfo(selection_type="Spruce", trigger_lines=Spruce_decisions) + + return evt_variables + + +################################################################################# +# Create FunTuple With a HLT filter on lines +# TODO : document functionality and use - case +################################################################################# + +def Filter_Of_FunTuple( options : Options, line_name: str ): + hlt_filter = create_lines_filter( + name=f"HDRFilter_{line_name}", + lines=[line_name] + ) + return hlt_filter + +def FunTuple_no_Filter( + options : Options, + fields, + variables, + inputs, + name ="Tuple", + tuple_name="DecayTree", + event_variables=None, + store_multiple_cand_info = True): + + return Funtuple( name=name, + tuple_name=tuple_name, + fields=fields, + variables=variables, + inputs=inputs, + event_variables=event_variables, + store_multiple_cand_info=store_multiple_cand_info ) + +def Funtuple_with_filter( + options : Options, + line_name, + fields, + variables, + inputs, + name = "Tuple", + tuple_name = "DecayTree", + event_variables = None, + store_multiple_cand_info = True) -> list: + + ftp = Funtuple( + name=name, + tuple_name=tuple_name, + fields=fields, + variables=variables, + inputs=inputs, + event_variables=event_variables, + store_multiple_cand_info=store_multiple_cand_info) + + if line_name is None: + return [ftp] + + hlt_filter = create_lines_filter(name=f"HDRFilter_{line_name}", lines=[line_name]) + + return [hlt_filter, ftp] + +def Funtuple_with_filter_scaling( + options : Options, + line_name, + fields, + variables, + inputs, + name ="Tuple", + tuple_name="DecayTree", + event_variables=None, + store_multiple_cand_info = True, + prescale:float = None, +): + if prescale is None : + return Funtuple_with_filter( + options=options, + line_name=line_name, + fields=fields, + variables=variables, + inputs=inputs, + name= name , + tuple_name=tuple_name , + event_variables=make_hlt_event_variables(options, line_name), + ) + #TODO , figure out if it works for Upsilon Lines + odin = get_odin() + prescaler = DeterministicPrescaler( + name = f"{line_name}_Prescaler"+"_{hash}", + AcceptFraction = prescale, + SeedName = f"Seed_{line_name}"+"_{hash}", + ODINLocation = odin + ) + hlt_filter = create_lines_filter( + name=f"HDRFilter_{line_name}", + lines=[line_name] + ) + + return [prescaler, + hlt_filter, + Funtuple( + name=name, + tuple_name=tuple_name, + fields=fields, + variables=variables, + inputs=inputs, + event_variables=event_variables, + store_multiple_cand_info=store_multiple_cand_info + #store the totCandidates, nCandidates branches etc.. + )] + + +################################################################################# +# Make Hypotesis Substitution +# TODO : document functionality and use - case +################################################################################# +def make_hypothesis_substitution(options : Options, data: DataHandle, substitutions) -> DataHandle: + swapped_data = SubstitutePID( + "Subs_SwapKpi", # name of the algorithm + data, # input particle container + substitutions=substitutions, + output_level=INFO, + ).Particles + # Merge the swapped decays and the original decays + MergedContainer = ParticleContainerMerger( + name="HypothesisMerger", + InputContainers=[data, swapped_data], + OutputLevel=INFO, + ).OutputContainer diff --git a/rd_ap_2024/tupling/variables/tupling_dtf.py b/rd_ap_2024/tupling/variables/tupling_dtf.py new file mode 100644 index 0000000000000000000000000000000000000000..5619a3c7d441a41132e02508ff98e4ea3d1798b3 --- /dev/null +++ b/rd_ap_2024/tupling/variables/tupling_dtf.py @@ -0,0 +1,124 @@ +"""Common configuration functions +""" + +# Flag to fast debug memory consumption +DTF_ENABLED = True +from rd_ap_2024.utils.log_store import LogStore +from DaVinci import Options, make_config +from PyConf.components import force_location +from Gaudi.Configuration import INFO +import Functors as F +from Functors.math import log +from PyConf.dataflow import DataHandle # type: ignore[import] +from PyConf.reading import ( + get_particles, + get_pvs, + get_mc_particles, + get_odin, + get_rec_summary, +) +from typing import List, Dict + +# Information on DTF: https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Phys/DecayTreeFitter/python/DecayTreeFitter/DecayTreeFitter.py +from DecayTreeFitter import DecayTreeFitter +from FunTuple import FunctorCollection + +# check here, for the DV version in use what can be imported / modified +# https://gitlab.cern.ch/lhcb/DaVinci/-/blob/v64r4/Phys/FunTuple/python/FunTuple/functorcollections.py?ref_type=tags#L1281 +# +from FunTuple.functorcollections import ( + Kinematics, + SelectionInfo, + MCVertexInfo, + MCKinematics, + MCPromptDecay, + MCHierarchy, + MCPromptDecay, + MCReconstructed, + MCReconstructible, + MCPrimaries, + MCPrimaryVertexInfo, + EventInfo, + ParticleID, + ChargedCaloInfo, + NeutralCaloInfo, + VertexIsolation, + ConeIsolation, + ParticleIsolation, + DecayTreeFitterResults, + ParticlePVInfo, + HltTisTos, + LHCInfo, +) +from FunTuple import FunTuple_Particles as Funtuple +from PyConf.application import metainfo_repos + +from DaVinci.algorithms import create_lines_filter +from PyConf.reading import ( + get_pvs, + get_rec_summary, +) +from PyConf.Algorithms import ( + WeightedRelTableAlg, + Hlt1TisTosAlg, + Hlt2TisTosAlg, + ThOrParticleSelection, +) +import FunTuple.functorcollections as FC +from GaudiConf.LbExec import HltSourceID +from PyConf.reading import get_decreports, get_hlt1_selreports, get_particles +from PyConf.dataflow import DataHandle + +# swaps +from DaVinciTools import SubstitutePID +from PyConf.Algorithms import ParticleContainerMerger +import numpy as np + + +logger=LogStore.add_logger('rd_ap_2024:tupling_dtf') + +def make_dtf_variables_v2(options: Options, + data: DataHandle, + v2_pvs: DataHandle=None , + Constraints_Config: dict={}) -> dict : + if DTF_ENABLED == False: + logger.debug("--- no DTF vars made, debugging memory consumption ----") + return FunctorCollection() + + variables = { + "mother" : FunctorCollection({}), + "intermediate": FunctorCollection({}), + "finalstates" : FunctorCollection({}), + } + + for prefix in Constraints_Config.keys(): + assert( type(Constraints_Config[prefix]["substitutions"]) == list ) + substitutions = Constraints_Config[prefix]["substitutions"] if Constraints_Config[prefix]["substitutions"] else None + # logger.info( f"{prefix} : Substitutions = {substitutions}") + massconstraints = Constraints_Config[prefix]["mass_constraints"] + if "withPV" in Constraints_Config[prefix].keys() : + cstr_own_pv = Constraints_Config[prefix]["withPV"] + else : + cstr_own_pv = False + if cstr_own_pv : + DTF = DecayTreeFitter(name=prefix + "_{hash}" , + input_particles=data, + mass_constraints=massconstraints, + substitutions=substitutions, + input_pvs=v2_pvs, + constrain_to_ownpv= cstr_own_pv , + fit_all_pvs=False + ) + else: + DTF = DecayTreeFitter(name=prefix + "_{hash}" , + input_particles=data, + mass_constraints=massconstraints, + substitutions=substitutions, + input_pvs=None , + constrain_to_ownpv= cstr_own_pv , + fit_all_pvs=False + ) + variables["mother"] += FC.DecayTreeFitterResults(DTF=DTF, decay_origin=True, with_lifetime=True, with_kinematics=True , prefix=prefix) + variables["intermediate"] += FC.DecayTreeFitterResults(DTF=DTF, decay_origin=False, with_lifetime=False, with_kinematics=True , prefix=prefix) + variables["finalstates"] += FC.DecayTreeFitterResults(DTF=DTF, decay_origin=False, with_lifetime=False, with_kinematics=True , prefix=prefix) + return variables diff --git a/rd_ap_2024/utils/__init__.py b/rd_ap_2024/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rd_ap_2024/utils/log_store.py b/rd_ap_2024/utils/log_store.py new file mode 100644 index 0000000000000000000000000000000000000000..b0c4596d594e7d7bb1039d032dcff1fcaca43d17 --- /dev/null +++ b/rd_ap_2024/utils/log_store.py @@ -0,0 +1,140 @@ +''' +Module holding LogStore +''' + +import os +import logging + +#------------------------------------------------------------ +class StoreFormater(logging.Formatter): + ''' + Custom formatter + ''' + LOG_COLORS = { + logging.DEBUG : '\033[94m', # Gray + logging.INFO : '\033[37m', # White + logging.WARNING : '\033[93m', # Yellow + logging.ERROR : '\033[91m', # Red + logging.CRITICAL: '\033[1;91m' # Bold Red + } + + RESET_COLOR = '\033[0m' # Reset color to default + + def format(self, record): + log_color = self.LOG_COLORS.get(record.levelno, self.RESET_COLOR) + message = super().format(record) + + return f'{log_color}{message}{self.RESET_COLOR}' +#------------------------------------------------------------ +class LogStore: + ''' + Class used to make loggers, set log levels, print loggers, e.g. interface to logging/logzero, etc. + ''' + #pylint: disable = invalid-name + d_logger = {} + d_levels = {} + log_level = logging.INFO + is_configured = False + backend = 'logging' + #-------------------------- + @staticmethod + def _check_backend() -> None: + if 'LOGSTORE_BACKEND' not in os.environ: + return + + LogStore.backend = os.environ['LOGSTORE_BACKEND'] + #-------------------------- + @staticmethod + def add_logger(name=None): + ''' + Will use underlying logging library logzero/logging, etc to make logger + + name (str): Name of logger + ''' + + if name is None: + raise ValueError('Logger name missing') + + if name in LogStore.d_logger: + raise ValueError(f'Logger name {name} already found') + + level = LogStore.log_level if name not in LogStore.d_levels else LogStore.d_levels[name] + + LogStore._check_backend() + + if LogStore.backend == 'logging': + logger = LogStore._get_logging_logger(name, level) + elif LogStore.backend == 'logzero': + logger = LogStore._get_logzero_logger(name, level) + else: + raise ValueError(f'Invalid backend: {LogStore.backend}') + + LogStore.d_logger[name] = logger + + return logger + #-------------------------- + @staticmethod + def _get_logzero_logger(name : str, level : int): + import logzero + + log = logzero.setup_logger(name=name) + log.setLevel(level) + + return log + #-------------------------- + @staticmethod + def _get_logging_logger(name : str, level : int): + logger = logging.getLogger(name=name) + + logger.setLevel(level) + + hnd= logging.StreamHandler() + hnd.setLevel(level) + + fmt= StoreFormater('%(asctime)s - %(filename)s:%(lineno)d - %(message)s', datefmt='%H:%M:%S') + hnd.setFormatter(fmt) + + if logger.hasHandlers(): + logger.handlers.clear() + + logger.addHandler(hnd) + + return logger + #-------------------------- + @staticmethod + def set_level(name, value): + ''' + Will set the level of a logger, it not present yet, it will store the level and set it when created. + Parameters: + ----------------- + name (str): Name of logger + value (int): 10 debug, 20 info, 30 warning + ''' + + if name in LogStore.d_logger: + lgr=LogStore.d_logger[name] + lgr.handlers[0].setLevel(value) + lgr.setLevel(value) + else: + LogStore.d_levels[name] = value + #-------------------------- + @staticmethod + def show_loggers(): + ''' + Will print loggers and log levels in two columns + ''' + print(80 * '-') + print(f'{"Name":<60}{"Level":<20}') + print(80 * '-') + for name, logger in LogStore.d_logger.items(): + print(f'{name:<60}{logger.level:<20}') + #-------------------------- + @staticmethod + def set_all_levels(level): + ''' + Will set all loggers to this level (int) + ''' + for name, logger in LogStore.d_logger.items(): + logger.setLevel(level) + print(f'{name:<60}{"->":20}{logger.level:<20}') +#------------------------------------------------------------