diff --git a/ew_projects_run3/ftuple.py b/ew_projects_run3/ftuple.py new file mode 100644 index 0000000000000000000000000000000000000000..57e2daa2a4275482bbb94a9f33478d9a2e4a77c2 --- /dev/null +++ b/ew_projects_run3/ftuple.py @@ -0,0 +1,129 @@ +from PyConf.reading import (get_particles, get_pvs, get_rec_summary, + get_mc_particles) +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 .ftuple_helpers import ( + decaytree_variables, mcdecaytree_selection_to_variables, extra_event_info, + selection_to_decay_descriptor, mcdtt_selections_to_decay_descriptor, Spec, + rec_summary_variables, selection_dependent_filtering, trkeff_probes, + decaytreefitter_variables) + +hlt1_tistos_lines = ["Hlt1SingleHighPtMuon", "Hlt1SingleHighPtMuonNoMuID"] +hlt2_tistos_lines = [ + "Hlt2QEE_SingleHighPtMuonFull", "Hlt2QEE_SingleHighPtMuonNoMuIDFull", + "Hlt2QEE_ZToMuMuFull", "Hlt2QEE_ZToMuMu_SingleNoMuIDFull" +] + + +def hlt2_decision_lines(trkeff_methods): + return hlt2_tistos_lines + [ + f"Hlt2TrackEff_ZToMuMu_{trkeff_method}_{probe}_{decision_type}" + for trkeff_method in trkeff_methods for probe in trkeff_probes + for decision_type in ["Tag", "Match"] + ] + + +def make_DTT(selection, line, pvs, spec): + dec_desc = selection_to_decay_descriptor( + trkeff_methods=spec.trkeff_methods)[selection] + data = selection_dependent_filtering( + data=get_particles(f"/Event/{spec.dataLocProcess}/{line}/Particles"), + selection=selection) + + variables = decaytree_variables( + selection=selection, pvs=pvs, data=data, spec=spec) + evtinfo = FC.EventInfo() + evtinfo += extra_event_info(spec=spec) + evtinfo += FC.SelectionInfo( + selection_type="Hlt1", trigger_lines=hlt1_tistos_lines) + + evtinfo += rec_summary_variables(rec_summary=get_rec_summary()) + evtinfo += FC.SelectionInfo( + selection_type="Hlt2", + trigger_lines=hlt2_decision_lines(spec.trkeff_methods)) + + variables["ALL"] += FC.HltTisTos( + selection_type="Hlt1", + trigger_lines=[f"{line}Decision" for line in hlt1_tistos_lines], + data=data) + + if spec.isFull: + variables["ALL"] += FC.HltTisTos( + selection_type="Hlt2", + trigger_lines=[f"{line}Decision" for line in hlt2_tistos_lines], + data=data) + + if spec.isTurCal: + dtf_variables = decaytreefitter_variables( + selection=selection, pvs=pvs, data=data) + for k in dtf_variables.keys(): + variables[k] = variables.get(k, FunctorCollection( + {})) + dtf_variables[k] + + funtuple = Funtuple( + name=selection, + tuple_name="DecayTree", + fields=dec_desc, + variables=variables, + inputs=data, + store_multiple_cand_info=True, + event_variables=evtinfo) + + return funtuple + + +def make_MCDTT(selection, spec): + dec_desc = mcdtt_selections_to_decay_descriptor[selection] + container_loc_prefix = "/Event/Spruce/HLT2" if spec.isFull else "/Event/HLT2" + mc_particles = get_mc_particles(f"{container_loc_prefix}/MC/Particles") + + variables = mcdecaytree_selection_to_variables[selection] + variables["ALL"] = FunctorCollection({"ID": F.PARTICLE_ID}) + evtinfo = extra_event_info(spec=spec) + + return MCFuntuple( + name=f"{selection}_mcdtt", + tuple_name="DecayTree", + fields=dec_desc, + variables=variables, + event_variables=evtinfo, + inputs=mc_particles, + ) + + +def make_ET(spec): + return EventFuntuple( + name="EventTuple", + tuple_name="EventTuple", + variables=extra_event_info(spec=spec)) + + +def main(options: Options, stream: str, campaign: str, polarity: str, + sample: str): + spec = Spec(stream, campaign, polarity, sample) + + algs = {} + + for selection, line in spec.selection_line_map.items(): + line_prefilter = create_lines_filter( + name=f"PreFilter_{line}", lines=[line]) + pvs = get_pvs() + algs[selection] = [ + line_prefilter, + require_pvs(pvs), + make_DTT(selection=selection, line=line, pvs=pvs, spec=spec) + ] + if spec.isMC: algs["EventTuple"] = [make_ET(spec=spec)] + if spec.isMC and spec.isFull: + for mcdtt_selection in mcdtt_selections_to_decay_descriptor.keys(): + algs[f"{mcdtt_selection}_MCDecayTree"] = [ + make_MCDTT(selection=mcdtt_selection, spec=spec) + ] + return make_config(options, algs) diff --git a/ew_projects_run3/ftuple_helpers.py b/ew_projects_run3/ftuple_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..89685f8139f35cdc99923cc083ebb2c220e99801 --- /dev/null +++ b/ew_projects_run3/ftuple_helpers.py @@ -0,0 +1,410 @@ +from PyConf.reading import get_charged_protoparticles +from PyConf.Algorithms import WeightedRelTableAlg, ThOrParticleSelection +from DaVinciMCTools import MCTruthAndBkgCat +from DecayTreeFitter import DecayTreeFitter +from Hlt2Conf.lines.qee import single_high_pt_muon +from Hlt2Conf.standard_particles import make_ismuon_long_muon +from Hlt2Conf.standard_jets import make_onlytrack_particleflow, make_charged_particles +from Hlt2Conf.algorithms_thor import ParticleFilter +from GaudiKernel.SystemOfUnits import GeV +from FunTuple import FunctorCollection +import Functors as F +from enum import Enum + +_Z_decay_descriptor = { + "Z0": "^(Z0 -> mu- mu+)", + "mum": "Z0 -> ^mu- mu+", + "mup": "Z0 -> mu- ^mu+", +} +_Jpsi_decay_descriptor = { + "Jpsi": "^(J/psi(1S) -> mu- mu+)", + "mum": "J/psi(1S) -> ^mu- mu+", + "mup": "J/psi(1S) -> mu- ^mu+", +} +_Upsilon_decay_descriptor = { + "U1S": "^(Upsilon(1S) -> mu- mu+)", + "mum": "Upsilon(1S) -> ^mu- mu+", + "mup": "Upsilon(1S) -> mu- ^mu+", +} +_Wp_decay_descriptor = { + "mu": '^mu+', +} +_Wm_decay_descriptor = { + "mu": '^mu-', +} +trkeff_probes = ["mum", "mup"] + +FSR_electron_descriptor = ' {e+} {e-} {e+} {e-} ' +mcdtt_selections_to_decay_descriptor = { + "Z": { + "Z": f"^(Z0 => mu- mu+ {FSR_electron_descriptor})", + "mum": f"Z0 => ^mu- mu+ {FSR_electron_descriptor}", + "mup": f"Z0 => mu- ^mu+ {FSR_electron_descriptor}", + }, + "W": { + "W": f"^[W+ => mu+ nu_mu {FSR_electron_descriptor}]CC", + "mu": f"[W+ => ^mu+ nu_mu {FSR_electron_descriptor}]CC", + }, + "Ztau": { + "Z": + f"^(Z0 => (tau+ => mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) (tau- => mu- nu_mu~ nu_tau {FSR_electron_descriptor}))", + "taup": + f"Z0 => ^(tau+ => mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) (tau- => mu- nu_mu~ nu_tau {FSR_electron_descriptor})", + "mup": + f"Z0 => (tau+ => ^mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) (tau- => mu- nu_mu~ nu_tau {FSR_electron_descriptor})", + "taum": + f"Z0 => (tau+ => mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) ^(tau- => mu- nu_mu~ nu_tau {FSR_electron_descriptor})", + "mum": + f"Z0 => (tau+ => mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) (tau- => ^mu- nu_mu~ nu_tau {FSR_electron_descriptor})", + }, + "Wtau": { + "W": + f"^[W+ => (tau+ => mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) nu_tau]CC", + "tau": + f"[W+ => ^(tau+ => mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) nu_tau]CC", + "mu": + f"[W+ => (tau+ => ^mu+ nu_mu nu_tau~ {FSR_electron_descriptor}) nu_tau]CC", + } +} + +_rapidity_functor = 0.5 * F.math.log((F.ENERGY + F.PZ) / (F.ENERGY - F.PZ)) +_mcdecaytree_lepton_variables = FunctorCollection({ + "PT": F.PT, + "ETA": F.ETA, + "PHI": F.PHI +}) +_mcdecaytree_boson_variables = FunctorCollection({ + "M": F.MASS, + "PT": F.PT, + "Y": _rapidity_functor +}) +mcdecaytree_selection_to_variables = { + "W": { + "mu": _mcdecaytree_lepton_variables + }, + "Wtau": { + "mu": _mcdecaytree_lepton_variables, + "tau": _mcdecaytree_lepton_variables + }, + "Z": { + "mum": _mcdecaytree_lepton_variables, + "mup": _mcdecaytree_lepton_variables, + "Z": _mcdecaytree_boson_variables, + }, + "Ztau": { + "mum": _mcdecaytree_lepton_variables, + "mup": _mcdecaytree_lepton_variables, + "taum": _mcdecaytree_lepton_variables, + "taup": _mcdecaytree_lepton_variables, + "Z": _mcdecaytree_boson_variables, + }, +} + + +def selection_to_decay_descriptor(trkeff_methods): + return { + "Z": _Z_decay_descriptor, + "ZMuID": _Z_decay_descriptor, + "Jpsi_Detached": _Jpsi_decay_descriptor, + "Jpsi_Prompt": _Jpsi_decay_descriptor, + "U1S": _Upsilon_decay_descriptor, + "Wp": _Wp_decay_descriptor, + "Wm": _Wm_decay_descriptor, + "WpNoMuID": _Wp_decay_descriptor, + "WmNoMuID": _Wm_decay_descriptor, + "ZSS": { + "Z0": "[Z0 -> mu- mu-]CC", + "mum": "[Z0 -> ^mu- mu-]CC", + "mup": "[Z0 -> mu- ^mu-]CC", + } + } | { + f"ZTrkEff_{trkeff_method}_{probe}": _Z_decay_descriptor + for trkeff_method in trkeff_methods for probe in trkeff_probes + } + + +def rec_summary_variables(rec_summary): + # as per https://gitlab.cern.ch/lhcb/Rec/-/blob/master/Rec/RecAlgs/src/RecSummaryMaker.cpp?ref_type=heads#L71 + _rec_summary_vars = [ + "nPVs", "nLongTracks", "nFTClusters", "nVPClusters", "nEcalClusters", + "hCalTot" + ] + return FunctorCollection({ + var: F.VALUE_OR(-1) @ F.RECSUMMARY_INFO(rec_summary, var) + for var in _rec_summary_vars + }) + + +def decaytree_variables(selection, pvs, spec, data): + variables = {} + variables["ALL"] = FunctorCollection({"PID": F.PARTICLE_ID}) + + muon_FC = FunctorCollection({ + "BPVIP": F.BPVIP(pvs), + "BPVIPCHI2": F.BPVIPCHI2(pvs), + "TRCHI2NDOF": F.CHI2DOF, + "PV_X": F.BPVX(pvs), + "PV_Y": F.BPVY(pvs), + "PV_Z": F.BPVZ(pvs), + "Q": F.CHARGE, + "PX": F.PX, + "PY": F.PY, + "PZ": F.PZ, + "PERR2": F.PERR2(), + "ISMUON": F.ISMUON, + "INMUON": F.INMUON, + "PIDmu": F.PID_MU, + "HCALEOP": F.VALUE_OR(0) @ F.HCALEOP, + "ECALEOP": F.VALUE_OR(0) @ F.ELECTRONSHOWEREOP, + }) + for particle in selection_to_decay_descriptor( + trkeff_methods=spec.trkeff_methods)[selection].keys(): + if "mu" not in particle: # These don't work for muons (no endvertex) + variables[particle] = FunctorCollection({ + "ENDVCHI2": + F.CHI2 @ F.ENDVERTEX, + "ENDVCHI2DOF": + F.CHI2DOF @ F.ENDVERTEX, + }) + else: + variables[particle] = muon_FC + if spec.doIsolation: + variables[particle] += _iso_variables( + data=data, pref=particle, selection=selection) + if particle == "mu": # This needs to only be Single muons (not DiMuons) + variables[particle] += _zveto_variables(data=data) + + if spec.isMC: + # Necessary to prevent duplicated algorithms with different names + unique_selection_name = selection.replace('Wp', 'W').replace('Wm', 'W') + MCTRUTH = MCTruthAndBkgCat( + data, name=f"MCTruthAndBkgCat__{unique_selection_name}") + variables["ALL"] += FunctorCollection({ + "TRUEPX": + MCTRUTH(F.PX), + "TRUEPY": + MCTRUTH(F.PY), + "TRUEPZ": + MCTRUTH(F.PZ), + "TRUEID": + F.VALUE_OR(0) @ MCTRUTH(F.PARTICLE_ID), + }) + return variables + + +def extra_event_info(spec): + """ + Defines several event-level variables for later use. + """ + return FunctorCollection({ + 'year_int': F.ALL() * 2024, + 'isMC': F.ALL() * int(spec.isMC), + 'polarity_sign': F.ALL() * spec.magpolInt + }) + + +def decaytreefitter_variables(selection, pvs, data): + v = {} + dtf__name = "DTF_AllPV" + + dtf = DecayTreeFitter( + input_particles=data, + name="__".join([dtf__name, selection]), + input_pvs=pvs, + fit_all_pvs=True) + + _dtf_FC = lambda d: FunctorCollection({ + f"_{dtf__name}__{key}": dtf(functor) + for key, functor in d.items() + }) + for muon in trkeff_probes: + v[muon] = _dtf_FC({ + "P": F.P, + "PERR2": F.PERR2(), + }) + v["Z0"] = _dtf_FC({ + "MASS": F.MASS, + "CHI2DOF": F.VALUE_OR(-999) @ F.CHI2DOF, + }) + + return v + + +def selection_dependent_filtering(data, selection): + if selection in streams_to_map()[Stream.Turbo]: + # https://gitlab.cern.ch/lhcb/Moore/-/merge_requests/3418#note_7953141 + child_pidmu_cut = lambda i: F.CHILD(i, F.PID_MU) > -10 + return ParticleFilter( + data, + F.FILTER(F.require_all(child_pidmu_cut(1), child_pidmu_cut(2))), + name=f'{selection}__pidmu_filter') + return data + + +def _iso_variables(data, pref, selection): + """ + For each candidate muon: + generate the particles within a cone with following cuts: + - radius 0.5 in (DPHI, DETA) space around signal candidate + - ~SHARE_TRACKS i.e. don't count our signal candidate + Defines: + ISO_C{PT,PX,PY} via _safe_sumcone + """ + # extract muon particlecontainer from the main decay candidate. + mu_decdesc = {"mup": "mu+", "mum": "mu-", "mu": "mu"}[pref] + isDimuon = "W" not in selection + mu_particles = _extract_muons_from_composite_candidate( + data=data, decdesc=mu_decdesc) if isDimuon else data + + with make_charged_particles.bind( + make_protoparticles=get_charged_protoparticles): + input_cands = make_onlytrack_particleflow() + alg = WeightedRelTableAlg( + ReferenceParticles=mu_particles, + InputCandidates=input_cands, + Cut=F.require_all(F.DR2 < (0.5**2), ~F.SHARE_TRACKS())) + return FunctorCollection({ + "ISO050_CPT": _safe_sumcone(alg, F.PT), + "ISO050_CPX": _safe_sumcone(alg, F.PX), + "ISO050_CPY": _safe_sumcone(alg, F.PY), + }) + + +def _zveto_variables(data): + """ + Only makes sense for W-like candidates, i.e. not Z-like. + """ + min_muon_pt = 0.1 * GeV # Just a sanity cut + input_cands = ParticleFilter( + make_ismuon_long_muon(), + F.FILTER(F.require_all(F.PT > min_muon_pt)), + name='ZVeto_muon_filter') + + alg = WeightedRelTableAlg( + ReferenceParticles=data, + InputCandidates=input_cands, + Cut=F.require_all(~F.SHARE_TRACKS())) + + zveto_muon_variables = {"PX": F.PX, "PY": F.PY, "PZ": F.PZ, "Q": F.CHARGE} + + def _zveto_muon_functor_composition(functor, relations): + return F.VALUE_OR(0) @ functor @ F.TO @ F.ENTRY_WITH_MAX_REL_VALUE_OF( + F.PT @ F.TO @ F.FORWARDARG0).bind( + F.RELATIONS.bind(F.TES(relations), F.FORWARDARGS)) + + return FunctorCollection({ + f"OTHERMUON_{var}": _zveto_muon_functor_composition( + functor=functor, relations=alg.OutputRelations) + for var, functor in zveto_muon_variables.items() + }) + + +def _extract_muons_from_composite_candidate(data, decdesc): + """ + Navigates the descendants of a candidate particle + Returns the child muons for that candidate. + """ + return ThOrParticleSelection( + InputParticles=data, + Functor=F.FILTER(F.IS_ID(decdesc)) + @ F.GET_ALL_DESCENDANTS()).OutputSelection + + +def _safe_sumcone(reltable_alg, functor): + """ + Given a relation table and a functor: + Returns SUM(functor) over all particles within that relation table. + Safe refers to giving the physical invalid value of 0 if the relation is empty (i.e. instead of NaN) + """ + return F.VALUE_OR(0) @ F.SUMCONE( + Functor=functor, Relations=reltable_alg.OutputRelations) + + +class Sample(Enum): + MC = 0 + DATA = 1 + + +class Campaign(Enum): + s24c1 = 1 + s24c2 = 2 + s24c3 = 3 + + +class Stream(Enum): + Full = 1 + Turbo = 2 + TurCal = 3 + + +class MagPol(Enum): + MagUp = 1 + MagDown = -1 + + +def _data_loc_process(stream_enum): + return { + Stream.Full: 'Spruce', + Stream.Turbo: 'HLT2', + Stream.TurCal: 'Spruce' + }[stream_enum] + + +def _do_isolation(stream_enum): + return { + Stream.Full: True, + Stream.Turbo: False, + Stream.TurCal: True + }[stream_enum] + + +def _trkeff_methods(campaign_enum): + m_withoutUT = ["VeloMuon", "SeedMuon"] + m_withUT = m_withoutUT + ["MuonUT", "Downstream"] + return { + Campaign.s24c1: m_withoutUT, + Campaign.s24c2: m_withUT, + Campaign.s24c3: m_withUT + }[campaign_enum] + + +def streams_to_map(trkeff_methods=[""]): + return { # Stream : { selection : linename } + Stream.Turbo: { + "Jpsi_Detached": "Hlt2QEE_JpsiToMuMu_Detached", + "Jpsi_Prompt": "Hlt2QEE_JpsiToMuMu_Prompt", + "U1S": "Hlt2QEE_Upsilon1SToMuMu", + }, + Stream.Full: { + "Z": "SpruceQEE_ZToMuMu", + "ZMuID": "SpruceQEE_ZToMuMu_SingleNoMuID", + "Wp": "SpruceQEE_SingleHighPtMuon", + "Wm": "SpruceQEE_SingleHighPtMuon", + "WpNoMuID": "SpruceQEE_SingleHighPtMuonNoMuID", + "WmNoMuID": "SpruceQEE_SingleHighPtMuonNoMuID", + "ZSS": "SpruceQEE_DiMuonSameSign", + }, + Stream.TurCal: { + f"ZTrkEff_{trkeff_method}_{probe}": + f"SpruceTurCalTrackEff_ZToMuMu_{trkeff_method}_{probe}_Tag" + for trkeff_method in trkeff_methods for probe in trkeff_probes + } + } + + +class Spec(): + def __init__(self, stream, campaign, magpol, sample): + stream_enum = Stream[stream] + campaign_enum = Campaign[f's{campaign}'] + magpol_enum = MagPol[magpol] + sample_enum = Sample[sample] + + self.isFull = stream_enum == Stream.Full + self.isTurCal = stream_enum == Stream.TurCal + self.isMC = sample_enum == Sample.MC + self.magpolInt = magpol_enum.value + self.trkeff_methods = _trkeff_methods(campaign_enum) + self.selection_line_map = streams_to_map( + self.trkeff_methods)[stream_enum] + self.dataLocProcess = _data_loc_process(stream_enum) + self.doIsolation = _do_isolation(stream_enum) diff --git a/ew_projects_run3/info.yaml b/ew_projects_run3/info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0858620485fa14a7edd09eaed26f585318ae6e88 --- /dev/null +++ b/ew_projects_run3/info.yaml @@ -0,0 +1,58 @@ +defaults: + inform: + - luke.grazette@cern.ch + wg: QEE + +################ +##### DATA ##### +################ + + +# https://twiki.cern.ch/twiki/bin/viewauth/LHCbInternal/OperationSummary2024 +# sprucing_campaign, moore_v, tuple_v +# 24c1 : Moore/DV latest `2024-patches` release as of 22-Apr-24 +# 24c2 : started withUT ~JuneTS : https://gitlab.cern.ch/lhcb-core/lhcbstacks/-/blob/master/data/stacks/DPA/2024.06.18.yml +# 24c3 : Started post AugMD +{%- set processing_campaigns = [ + ('24c3', '/Real Data/Sprucing24c3', 'v55r12p3', 'v64r9') +]%} +{%- set polarities=['MagDown', 'MagUp'] %} + +{%- for campaign, campaign_bkkpath, moore_v, tuple_v in processing_campaigns %} + {%- for polarity in polarities %} + {%- set bkk_prefix = '/LHCb/Collision24/Beam6800GeV-VeloClosed-' + polarity + campaign_bkkpath %} + {%- set datasets = [ + ('TurCal', 'Spruce' , 'turcal_persistrecorawbanks', bkk_prefix + '/95100000/TURCAL_PERSISTRECORAWBANKS.DST'), + ] + %} + {%- for stream, input_process, input_stream, bk_query in datasets %} + +DATA{{campaign}}_{{polarity}}_{{stream}}: + application: DaVinci/{{tuple_v}} + input: + bk_query: {{bk_query}} + dq_flags: + - OK + - UNCHECKED + output: FTupleQEE.root + options: + entrypoint: ew_projects_run3.ftuple:main + extra_options: + input_raw_format: 0.5 + input_type: ROOT + simulation: False + data_type: "Upgrade" + geometry_version: run3/2024.Q1.2-v00.00 + conditions_version: master + input_process: {{input_process}} + input_stream: {{input_stream}} + extra_args: + - -- + - {{stream}} + - {{campaign}} + - {{polarity}} + - DATA + + {%- endfor %} + {%- endfor %} +{%- endfor %} diff --git a/ew_projects_run3/mc/24c1/hlt1.py b/ew_projects_run3/mc/24c1/hlt1.py new file mode 100644 index 0000000000000000000000000000000000000000..3e376e91fdb6821818bc7c777a9e04ecd48c38bc --- /dev/null +++ b/ew_projects_run3/mc/24c1/hlt1.py @@ -0,0 +1,14 @@ +""" +Stolen verbatim from Hlt/Hlt1Conf/options/hlt1_pp_expected_24_without_UT.py from v55r7 + - Added a `make_passthrough_line` bind +""" +from Moore import Options +from Moore.config import run_allen +from RecoConf.hlt1_allen import allen_gaudi_config as allen_sequence +from AllenConf.hlt1_calibration_lines import make_passthrough_line + + +def main(options: Options): + with allen_sequence.bind(sequence="hlt1_pp_matching_no_ut_1000KHz"),\ + make_passthrough_line.bind(pre_scaler=1): + return run_allen(options) diff --git a/ew_projects_run3/mc/24c1/hlt2.py b/ew_projects_run3/mc/24c1/hlt2.py new file mode 100644 index 0000000000000000000000000000000000000000..3c014a60f63dee0c4a89f5a98030c0bcc502ef06 --- /dev/null +++ b/ew_projects_run3/mc/24c1/hlt2.py @@ -0,0 +1,92 @@ +""" +Stolen and adapted from Hlt/Hlt2Conf/options/hlt2_pp_expected_24_without_UT.py from v55r7. +""" +from Moore import Options, run_moore +from RecoConf.reconstruction_objects import reconstruction +from RecoConf.hlt2_global_reco import reconstruction as hlt2_reconstruction, make_light_reco_pr_kf_without_UT +from RecoConf.decoders import default_VeloCluster_source +from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom +from RecoConf.hlt2_tracking import ( + make_TrackBestTrackCreator_tracks, + make_PrKalmanFilter_noUT_tracks, + make_PrKalmanFilter_Velo_tracks, + make_PrKalmanFilter_Seed_tracks, +) +from RecoConf.event_filters import require_gec +from RecoConf.protoparticles import make_charged_protoparticles +from Hlt2Conf.settings.defaults import get_default_hlt1_filter_code_for_hlt2 + +from Moore.streams import Stream, Streams, DETECTORS +import sys +from Moore.lines import Hlt2Line +from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines +from Hlt2Conf.lines.qee.single_high_pt_muon import all_lines as qee_single_muon_lines +from Hlt2Conf.lines.qee.single_high_pt_electron import all_lines as qee_single_electron_lines +from Hlt2Conf.lines.qee.quarkonia import all_lines as qee_quarkonia_lines +from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines + + +def pass_through_line(name="Hlt2Passthrough"): + """Return a HLT2 line that performs no selection but runs and persists the reconstruction + """ + return Hlt2Line(name=name, prescale=1, algs=[], persistreco=True) + + +def _pop_line(linename, line_dict): + print(f"Removing {linename}") + line_dict.pop(linename) + return 0 + + +def _make_lines(): + # Remove UT dependent lines + for linename in [ + name for name in z_trackeff_lines.keys() + if "Downstream" in name or "MuonUT" in name + ]: + _pop_line(linename, z_trackeff_lines) + + ret = [ + builder(prescale=1) for line_dict in [ + qee_single_muon_lines, qee_dimuon_lines, qee_quarkonia_lines, + qee_single_electron_lines, z_trackeff_lines + ] for builder in line_dict.values() + ] + ret += [pass_through_line()] + return ret + + +def make_streams(): + streams = [ + Stream(lines=_make_lines(), routing_bit=98, detectors=DETECTORS) + ] + return Streams(streams=streams) + + +def main(options: Options): + # NOTE: These are fr from options/hlt2_pp_2024 + from PyConf.Tools import TrackMasterExtrapolator, TrackMasterFitter + TrackMasterExtrapolator.global_bind( + ApplyMultScattCorr=False, + ApplyEnergyLossCorr=False, + ApplyElectronEnergyLossCorr=False) + TrackMasterFitter.global_bind(ApplyMaterialCorrections=False) + + public_tools = [ + trackMasterExtrapolator_with_simplified_geom(), + stateProvider_with_simplified_geom() + ] + + # NOTE: the TBTC does not apply a chi2 cut because it is applied by the PrKF + # NOTE: reconstruction and default VeloCluster are from options/hlt2_pp_2024 + with reconstruction.bind(from_file=False),\ + default_VeloCluster_source.bind(bank_type="VPRetinaCluster"),\ + hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf_without_UT),\ + require_gec.bind(skipUT=True),\ + make_charged_protoparticles.bind(fill_probnn_defaults=True),\ + make_TrackBestTrackCreator_tracks.bind(max_ghost_prob=0.7, max_chi2ndof=sys.float_info.max),\ + make_PrKalmanFilter_Velo_tracks.bind(max_chi2ndof=5.),\ + make_PrKalmanFilter_noUT_tracks.bind(max_chi2ndof=4.),\ + make_PrKalmanFilter_Seed_tracks.bind(max_chi2ndof=6.),\ + get_default_hlt1_filter_code_for_hlt2.bind(code=r"Hlt1(?!PassthroughLargeEvent).*Decision"): + return run_moore(options, make_streams, public_tools=public_tools) diff --git a/ew_projects_run3/mc/24c1/spruce.py b/ew_projects_run3/mc/24c1/spruce.py new file mode 100644 index 0000000000000000000000000000000000000000..336b224a4c5fc000cbb08d21f1b04c6b52c40be3 --- /dev/null +++ b/ew_projects_run3/mc/24c1/spruce.py @@ -0,0 +1,87 @@ +""" +The different streaming configurations stolen from the following on v55r7: + Turbo: Hlt/Hlt2Conf/options/sprucing/sprucepass_pp_expected_24.py + Full: Hlt/Hlt2Conf/options/sprucing/spruce_pp_expected_24.py + TurCal: Hlt/Hlt2Conf/python/Hlt2Conf/sprucing_settings/Sprucing_production_PP_24c1.py + Removed reco binds as per https://gitlab.cern.ch/lhcb-datapkg/AnalysisProductions/-/merge_requests/1119#note_7859546 +""" +from Moore import Options, run_moore +from Moore.streams import DETECTORS, Stream, Streams +from Moore.lines import PassLine, SpruceLine +from PyConf.reading import get_particles, upfront_reconstruction as upfront_spruce +from RecoConf.global_tools import stateProvider_with_simplified_geom + +from Hlt2Conf.lines.qee import sprucing_lines as qee_sprucing_lines + +from Moore.persistence.hlt2_tistos import list_of_full_stream_lines +from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines +from Hlt2Conf.lines.qee.single_high_pt_muon import all_lines as qee_single_muon_lines +from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines + + +def make_turbo_streams(): + streams = [Stream(lines=[PassLine(name="PassLine")], detectors=DETECTORS)] + return Streams(streams=streams) + + +def pass_through_line(name="SprucePassThrough"): + """Return a Spruce line that performs no selection but runs and persists the reconstruction + """ + return SpruceLine( + name=name, prescale=1, algs=upfront_spruce(), persistreco=True) + + +def make_full_streams(): + lines = [builder() for builder in qee_sprucing_lines.values()] + lines += [pass_through_line(name="SprucePassThrough__exclusive")] + streams = [Stream(lines=lines, detectors=[])] + return Streams(streams=streams) + + +def make_turcal_spruceline(hlt2_linename, persist_reco=False, prescale=1.): + filter = f"{hlt2_linename}Decision" + location = f"/Event/HLT2/{hlt2_linename}/Particles" + spruce_linename = hlt2_linename.replace("Hlt2", "SpruceTurCal") + print(f"{filter} {location} {spruce_linename}") + hlt2_particles = get_particles(location) + turcal_spruce_line = SpruceLine( + name=spruce_linename, + hlt2_filter_code=filter, + algs=upfront_spruce() + [hlt2_particles], + persistreco=persist_reco, + prescale=prescale) + return turcal_spruce_line + + +def make_turcal_streams(): + # Remove UT dependent lines + lines = [ + make_turcal_spruceline(linename, persist_reco=True) + for linename in z_trackeff_lines.keys() + if ("Downstream" not in linename and "MuonUT" not in linename) + ] + lines += [pass_through_line(name="SprucePassThrough__turcal")] + streams = [Stream(lines=lines, detectors=DETECTORS)] + return Streams(streams=streams) + + +def lines_for_tistos(): + return [ + linename for line_dict in [qee_single_muon_lines, qee_dimuon_lines] + for linename in line_dict.keys() + ] + + +def Turbo(options: Options): + return run_moore(options, make_turbo_streams, public_tools=[]) + + +def Full(options: Options): + public_tools = [stateProvider_with_simplified_geom()] + with list_of_full_stream_lines.bind(lines=lines_for_tistos()): + return run_moore(options, make_full_streams, public_tools=public_tools) + + +def TurCal(options: Options): + with list_of_full_stream_lines.bind(lines=[]): + return run_moore(options, make_turcal_streams, public_tools=[]) diff --git a/ew_projects_run3/mc/24c2/hlt1.py b/ew_projects_run3/mc/24c2/hlt1.py new file mode 100644 index 0000000000000000000000000000000000000000..07fc116dcf6b008eef7b16260f71359cd11745df --- /dev/null +++ b/ew_projects_run3/mc/24c2/hlt1.py @@ -0,0 +1,14 @@ +""" +Stolen verbatim from Hlt/Hlt1Conf/options/hlt1_pp_expected_24_without_UT.py from v55r10p1 + - Added a `make_passthrough_line` bind +""" +from Moore import Options +from Moore.config import run_allen +from RecoConf.hlt1_allen import allen_gaudi_config as allen_sequence +from AllenConf.hlt1_calibration_lines import make_passthrough_line + + +def main(options: Options): + with allen_sequence.bind(sequence="hlt1_pp_matching_no_ut_1000KHz"),\ + make_passthrough_line.bind(pre_scaler=1): + return run_allen(options) diff --git a/ew_projects_run3/mc/24c2/hlt2.py b/ew_projects_run3/mc/24c2/hlt2.py new file mode 100644 index 0000000000000000000000000000000000000000..fc22f15abfb0d497a3485d83375536d5e7117a66 --- /dev/null +++ b/ew_projects_run3/mc/24c2/hlt2.py @@ -0,0 +1,73 @@ +from Moore import Options, run_moore +from RecoConf.reconstruction_objects import reconstruction +from RecoConf.decoders import default_VeloCluster_source +from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom + +from RecoConf.hlt2_global_reco import ( + reconstruction as hlt2_reconstruction, + make_light_reco_pr_kf, +) +from RecoConf.hlt2_tracking import ( + make_TrackBestTrackCreator_tracks, + make_PrKalmanFilter_tracks, + make_PrKalmanFilter_Velo_tracks, + make_PrKalmanFilter_Seed_tracks, + make_PrHybridSeeding_tracks, +) +from RecoConf.event_filters import require_gec +from Hlt2Conf.settings.defaults import get_default_hlt1_filter_code_for_hlt2 + +import sys + +from Moore.lines import Hlt2Line +from Moore.streams import Stream, Streams, DETECTORS +from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines +from Hlt2Conf.lines.qee.single_high_pt_muon import all_lines as qee_single_muon_lines +from Hlt2Conf.lines.qee.single_high_pt_electron import all_lines as qee_single_electron_lines +from Hlt2Conf.lines.qee.quarkonia import all_lines as qee_quarkonia_lines +from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines + + +def pass_through_line(name="Hlt2Passthrough"): + """Return a HLT2 line that performs no selection but runs and persists the reconstruction + """ + return Hlt2Line(name=name, prescale=1, algs=[], persistreco=True) + + +def _make_lines(): + ret = [ + builder(prescale=1) for line_dict in [ + qee_single_muon_lines, qee_dimuon_lines, qee_quarkonia_lines, + qee_single_electron_lines, z_trackeff_lines + ] for builder in line_dict.values() + ] + ret += [pass_through_line()] + return ret + + +def make_streams(): + streams = [ + Stream(lines=_make_lines(), routing_bit=98, detectors=DETECTORS) + ] + return Streams(streams=streams) + + +def main(options: Options): + # https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r10p1/Hlt/Hlt2Conf/python/Hlt2Conf/settings/hlt2_pp_2024.py + # https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r10p1/Hlt/Hlt2Conf/options/hlt2_pp_2024.py + public_tools = [ + trackMasterExtrapolator_with_simplified_geom(), + stateProvider_with_simplified_geom() + ] + with reconstruction.bind(from_file=False),\ + default_VeloCluster_source.bind(bank_type="VPRetinaCluster"),\ + hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf),\ + require_gec.bind(skipUT=True),\ + make_TrackBestTrackCreator_tracks.bind(max_ghost_prob=0.5, max_chi2ndof=sys.float_info.max),\ + make_PrKalmanFilter_Velo_tracks.bind(max_chi2ndof=5.),\ + make_PrKalmanFilter_tracks.bind(max_chi2ndof=4.),\ + make_PrKalmanFilter_Seed_tracks.bind(max_chi2ndof=6.),\ + get_default_hlt1_filter_code_for_hlt2.bind(code=r"Hlt1(?!PassthroughLargeEvent).*Decision"),\ + make_PrHybridSeeding_tracks.bind(FasterCloneRemoval=True): + + return run_moore(options, make_streams, public_tools=public_tools) diff --git a/ew_projects_run3/mc/24c2/spruce.py b/ew_projects_run3/mc/24c2/spruce.py new file mode 100644 index 0000000000000000000000000000000000000000..6aab0f546528e532851965bb0765ea75771d85a7 --- /dev/null +++ b/ew_projects_run3/mc/24c2/spruce.py @@ -0,0 +1,87 @@ +from Moore import Options, run_moore +from Moore.streams import DETECTORS, Stream, Streams +from Moore.lines import PassLine, SpruceLine + +from PyConf.reading import get_particles, upfront_reconstruction as upfront_spruce +from Moore.persistence.hlt2_tistos import list_of_full_stream_lines + +from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom +from PyConf.Algorithms import VeloRetinaClusterTrackingSIMD +from RecoConf.legacy_rec_hlt1_tracking import make_VeloClusterTrackingSIMD +from RecoConf.decoders import default_VeloCluster_source + +from Hlt2Conf.lines.qee import sprucing_lines as qee_sprucing_lines +from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines +from Hlt2Conf.lines.qee.single_high_pt_muon import all_lines as qee_single_muon_lines +from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines + +# https://gitlab.cern.ch/lhcb-datapkg/SprucingConfig/-/blob/master/SprucingConfig/Spruce24/Sprucing_production_physics_pp_Collision24c2.py +# Removed reco binds as per https://gitlab.cern.ch/lhcb-datapkg/AnalysisProductions/-/merge_requests/1119#note_7859546 + + +def pass_through_line(name="SprucePassThrough"): + """Return a Spruce line that performs no selection but runs and persists the reconstruction + """ + return SpruceLine( + name=name, prescale=1, algs=upfront_spruce(), persistreco=True) + + +def Full(options: Options): + def _make_streams(): + lines = [builder() for builder in qee_sprucing_lines.values()] + lines += [pass_through_line(name="SprucePassThrough__exclusive")] + streams = [Stream(lines=lines, detectors=[])] + return Streams(streams=streams) + + default_VeloCluster_source.global_bind(bank_type="VPRetinaCluster") + make_VeloClusterTrackingSIMD.global_bind( + algorithm=VeloRetinaClusterTrackingSIMD) + + public_tools = [ + trackMasterExtrapolator_with_simplified_geom(), + stateProvider_with_simplified_geom() + ] + full_lines_for_TISTOS = [ + linename for line_dict in [qee_single_muon_lines, qee_dimuon_lines] + for linename in line_dict.keys() + ] + with list_of_full_stream_lines.bind(lines=full_lines_for_TISTOS): + return run_moore(options, _make_streams, public_tools=public_tools) + + +def Turbo(options: Options): + def _make_streams(): + streams = [ + Stream(lines=[PassLine(name="PassLine")], detectors=DETECTORS) + ] + return Streams(streams=streams) + + return run_moore(options, _make_streams, public_tools=[]) + + +def TurCal(options: Options): + def make_turcal_spruceline(hlt2_linename, persistreco=False, prescale=1.): + line_filter = f"{hlt2_linename}Decision" + location = f"/Event/HLT2/{hlt2_linename}/Particles" + spruce_linename = hlt2_linename.replace("Hlt2", "SpruceTurCal") + print(f"{line_filter} {location} {spruce_linename}") + hlt2_particles = get_particles(location) + turcal_spruce_line = SpruceLine( + name=spruce_linename, + hlt2_filter_code=line_filter, + algs=[hlt2_particles], + persistreco=persistreco, + prescale=prescale) + return turcal_spruce_line + + def _make_streams(): + lines = [ + make_turcal_spruceline(linename, persistreco=True) + for linename in z_trackeff_lines.keys() + ] + lines += [pass_through_line(name="SprucePassThrough__turcal")] + streams = [Stream(lines=lines, detectors=DETECTORS)] + return Streams(streams=streams) + + with list_of_full_stream_lines.bind(lines=[]): + return run_moore(options, _make_streams, public_tools=[]) diff --git a/ew_projects_run3/mc/24c3/hlt1.py b/ew_projects_run3/mc/24c3/hlt1.py new file mode 100644 index 0000000000000000000000000000000000000000..5cee9ba1671503ff65922091af1442bc25a9b81f --- /dev/null +++ b/ew_projects_run3/mc/24c3/hlt1.py @@ -0,0 +1,14 @@ +""" +Stolen verbatim from Hlt/Hlt1Conf/options/hlt1_pp_expected_24_without_UT.py from v55r10p1 + - Added a `make_passthrough_line` bind +""" +from Moore import Options +from Moore.config import run_allen +from RecoConf.hlt1_allen import allen_gaudi_config as allen_sequence +from AllenConf.hlt1_calibration_lines import make_passthrough_line + + +def main(options: Options): + with allen_sequence.bind(sequence="hlt1_pp_forward_then_matching_1000kHz"),\ + make_passthrough_line.bind(pre_scaler=1): + return run_allen(options) diff --git a/ew_projects_run3/mc/24c3/hlt2.py b/ew_projects_run3/mc/24c3/hlt2.py new file mode 100644 index 0000000000000000000000000000000000000000..fc22f15abfb0d497a3485d83375536d5e7117a66 --- /dev/null +++ b/ew_projects_run3/mc/24c3/hlt2.py @@ -0,0 +1,73 @@ +from Moore import Options, run_moore +from RecoConf.reconstruction_objects import reconstruction +from RecoConf.decoders import default_VeloCluster_source +from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom + +from RecoConf.hlt2_global_reco import ( + reconstruction as hlt2_reconstruction, + make_light_reco_pr_kf, +) +from RecoConf.hlt2_tracking import ( + make_TrackBestTrackCreator_tracks, + make_PrKalmanFilter_tracks, + make_PrKalmanFilter_Velo_tracks, + make_PrKalmanFilter_Seed_tracks, + make_PrHybridSeeding_tracks, +) +from RecoConf.event_filters import require_gec +from Hlt2Conf.settings.defaults import get_default_hlt1_filter_code_for_hlt2 + +import sys + +from Moore.lines import Hlt2Line +from Moore.streams import Stream, Streams, DETECTORS +from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines +from Hlt2Conf.lines.qee.single_high_pt_muon import all_lines as qee_single_muon_lines +from Hlt2Conf.lines.qee.single_high_pt_electron import all_lines as qee_single_electron_lines +from Hlt2Conf.lines.qee.quarkonia import all_lines as qee_quarkonia_lines +from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines + + +def pass_through_line(name="Hlt2Passthrough"): + """Return a HLT2 line that performs no selection but runs and persists the reconstruction + """ + return Hlt2Line(name=name, prescale=1, algs=[], persistreco=True) + + +def _make_lines(): + ret = [ + builder(prescale=1) for line_dict in [ + qee_single_muon_lines, qee_dimuon_lines, qee_quarkonia_lines, + qee_single_electron_lines, z_trackeff_lines + ] for builder in line_dict.values() + ] + ret += [pass_through_line()] + return ret + + +def make_streams(): + streams = [ + Stream(lines=_make_lines(), routing_bit=98, detectors=DETECTORS) + ] + return Streams(streams=streams) + + +def main(options: Options): + # https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r10p1/Hlt/Hlt2Conf/python/Hlt2Conf/settings/hlt2_pp_2024.py + # https://gitlab.cern.ch/lhcb/Moore/-/blob/v55r10p1/Hlt/Hlt2Conf/options/hlt2_pp_2024.py + public_tools = [ + trackMasterExtrapolator_with_simplified_geom(), + stateProvider_with_simplified_geom() + ] + with reconstruction.bind(from_file=False),\ + default_VeloCluster_source.bind(bank_type="VPRetinaCluster"),\ + hlt2_reconstruction.bind(make_reconstruction=make_light_reco_pr_kf),\ + require_gec.bind(skipUT=True),\ + make_TrackBestTrackCreator_tracks.bind(max_ghost_prob=0.5, max_chi2ndof=sys.float_info.max),\ + make_PrKalmanFilter_Velo_tracks.bind(max_chi2ndof=5.),\ + make_PrKalmanFilter_tracks.bind(max_chi2ndof=4.),\ + make_PrKalmanFilter_Seed_tracks.bind(max_chi2ndof=6.),\ + get_default_hlt1_filter_code_for_hlt2.bind(code=r"Hlt1(?!PassthroughLargeEvent).*Decision"),\ + make_PrHybridSeeding_tracks.bind(FasterCloneRemoval=True): + + return run_moore(options, make_streams, public_tools=public_tools) diff --git a/ew_projects_run3/mc/24c3/spruce.py b/ew_projects_run3/mc/24c3/spruce.py new file mode 100644 index 0000000000000000000000000000000000000000..6aab0f546528e532851965bb0765ea75771d85a7 --- /dev/null +++ b/ew_projects_run3/mc/24c3/spruce.py @@ -0,0 +1,87 @@ +from Moore import Options, run_moore +from Moore.streams import DETECTORS, Stream, Streams +from Moore.lines import PassLine, SpruceLine + +from PyConf.reading import get_particles, upfront_reconstruction as upfront_spruce +from Moore.persistence.hlt2_tistos import list_of_full_stream_lines + +from RecoConf.global_tools import stateProvider_with_simplified_geom, trackMasterExtrapolator_with_simplified_geom +from PyConf.Algorithms import VeloRetinaClusterTrackingSIMD +from RecoConf.legacy_rec_hlt1_tracking import make_VeloClusterTrackingSIMD +from RecoConf.decoders import default_VeloCluster_source + +from Hlt2Conf.lines.qee import sprucing_lines as qee_sprucing_lines +from Hlt2Conf.lines.qee.high_mass_dimuon import all_lines as qee_dimuon_lines +from Hlt2Conf.lines.qee.single_high_pt_muon import all_lines as qee_single_muon_lines +from Hlt2Conf.lines.trackeff.ZTrackEfficiency import all_lines as z_trackeff_lines + +# https://gitlab.cern.ch/lhcb-datapkg/SprucingConfig/-/blob/master/SprucingConfig/Spruce24/Sprucing_production_physics_pp_Collision24c2.py +# Removed reco binds as per https://gitlab.cern.ch/lhcb-datapkg/AnalysisProductions/-/merge_requests/1119#note_7859546 + + +def pass_through_line(name="SprucePassThrough"): + """Return a Spruce line that performs no selection but runs and persists the reconstruction + """ + return SpruceLine( + name=name, prescale=1, algs=upfront_spruce(), persistreco=True) + + +def Full(options: Options): + def _make_streams(): + lines = [builder() for builder in qee_sprucing_lines.values()] + lines += [pass_through_line(name="SprucePassThrough__exclusive")] + streams = [Stream(lines=lines, detectors=[])] + return Streams(streams=streams) + + default_VeloCluster_source.global_bind(bank_type="VPRetinaCluster") + make_VeloClusterTrackingSIMD.global_bind( + algorithm=VeloRetinaClusterTrackingSIMD) + + public_tools = [ + trackMasterExtrapolator_with_simplified_geom(), + stateProvider_with_simplified_geom() + ] + full_lines_for_TISTOS = [ + linename for line_dict in [qee_single_muon_lines, qee_dimuon_lines] + for linename in line_dict.keys() + ] + with list_of_full_stream_lines.bind(lines=full_lines_for_TISTOS): + return run_moore(options, _make_streams, public_tools=public_tools) + + +def Turbo(options: Options): + def _make_streams(): + streams = [ + Stream(lines=[PassLine(name="PassLine")], detectors=DETECTORS) + ] + return Streams(streams=streams) + + return run_moore(options, _make_streams, public_tools=[]) + + +def TurCal(options: Options): + def make_turcal_spruceline(hlt2_linename, persistreco=False, prescale=1.): + line_filter = f"{hlt2_linename}Decision" + location = f"/Event/HLT2/{hlt2_linename}/Particles" + spruce_linename = hlt2_linename.replace("Hlt2", "SpruceTurCal") + print(f"{line_filter} {location} {spruce_linename}") + hlt2_particles = get_particles(location) + turcal_spruce_line = SpruceLine( + name=spruce_linename, + hlt2_filter_code=line_filter, + algs=[hlt2_particles], + persistreco=persistreco, + prescale=prescale) + return turcal_spruce_line + + def _make_streams(): + lines = [ + make_turcal_spruceline(linename, persistreco=True) + for linename in z_trackeff_lines.keys() + ] + lines += [pass_through_line(name="SprucePassThrough__turcal")] + streams = [Stream(lines=lines, detectors=DETECTORS)] + return Streams(streams=streams) + + with list_of_full_stream_lines.bind(lines=[]): + return run_moore(options, _make_streams, public_tools=[])