###############################################################################
# (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 PyConf.tonic import configurable
from PyConf.components import Algorithm
from .event_filters import require_gec
from .legacy_rec_hlt1_tracking import (
make_pvs, make_all_pvs, make_legacy_rec_hlt1_tracks,
make_SPmixed_raw_banks, make_RetinaCluster_raw_bank,
make_VeloClusterTrackingSIMD, make_VeloClusterTrackingSIMD_hits,
make_VeloKalman_fitted_tracks, make_legacy_rec_hlt1_fitted_tracks,
make_velo_full_clusters, make_tracks_with_muon_id)
from RecoConf.decoders import default_VeloCluster_source
from RecoConf.legacy_rec_hlt1_muonmatch import make_tracks_with_muonmatch_ipcut
from RecoConf.legacy_rec_hlt1_tracking import all_velo_track_types
from RecoConf.muonid import make_muon_id, make_muon_hits
from RecoConf.muon_reconstruction import make_all_muon_pids, make_merged_muon_pids, make_conv_muon_pids
from RecoConf.hlt2_tracking import (
all_hlt2_forward_track_types, get_PrForwardTracksFromVeloUTV1_converter,
make_PrStoreSciFiHits_hits, make_PrStoreUTHit_hits, make_hlt2_tracks,
make_hlt2_tracks_without_UT, get_default_hlt2_tracks,
make_TrackBestTrackCreator_tracks, get_default_tracks_for_calo,
get_default_out_track_types_for_light_reco, make_PrForwardTracking_tracks,
make_PrHybridSeeding_tracks, convert_tracks_to_v3_from_v1)
from RecoConf.calorimeter_reconstruction import (
make_calo, make_calo_resolution_gamma, make_calo_resolution_pi0,
make_digits, make_convert_calo_chargedpids, make_calo_cluster_shapes)
from RecoConf.calorimeter_mc_checking import (
check_calo_cluster_resolution, check_calo_photon_resolution,
check_calo_pi0_resolution, check_calo_efficiency_all,
check_calo_efficiency_fromB, check_calo_charged_pids)
from RecoConf.rich_reconstruction import make_rich_pixels, default_rich_reco_options
from PyConf.application import default_raw_event, make_odin
from PyConf.packing import persistable_location
from PyConf.Algorithms import (
CaloFutureDigit2MCLinks2Table, CaloClusterMCTruth, TracksToSelection,
TrackSelectionMerger, RawBankSizeMonitor, VPRetinaFullClustering,
TracksEmptyProducer, PVsEmptyProducer, PrKalmanFilter,
PrKalmanFilter_Downstream, PrKalmanFilter_noUT, PrKalmanFilter_Velo,
PrKalmanFilter_Seed, MonitorDetectorCorrelations,
MonitorDetectorCorrelationsVeloSciFi,
MonitorECALEnergyTrackerHitsCorrelations,
MonitorECALEnergyRichHitsCorrelations,
MonitorECALEnergyRawEventSizeCorrelations)
from .mc_checking import (
get_track_checkers, get_fitted_tracks_checkers, get_pv_checkers,
get_best_tracks_checkers, get_track_checkers_multiplicity,
hits_resolution_checkers, make_links_lhcbids_mcparticles_VP_FT)
from .reconstruction_objects import reconstruction
from .protoparticles import (make_charged_protoparticles,
make_neutral_protoparticles)
from .calo_data_monitoring import monitor_calo
from .track_data_monitoring import monitor_tracking, get_monitoring_track_types_for_light_reco
from .muonPID_data_monitoring import monitor_muon_PID
from .mass_monitors import make_mass_monitors
from GaudiKernel.SystemOfUnits import MeV, mm
from Moore.config import Reconstruction
from .data_from_file import boole_links_digits_mcparticles, mc_unpacker
from .rich_add_reconstruction_monitoring_checking import add_hlt2_rich
from PyConf.Algorithms import (
LHCb__Phoenix__DumpPlanarCaloCellsToJson, LHCb__Phoenix__DumpVPHitEvent,
LHCb__Phoenix__DumpFTHitEvent, LHCb__Phoenix__DumpUTHitEvent,
LHCb__Phoenix__DumpProtoParticlesEvent, LHCb__Phoenix__DumpMuonHitEvent,
LHCb__Phoenix__DumpRichEvent)
from PyConf.Algorithms import PrintProtoParticles
from PyConf.control_flow import (CompositeNode, NodeLogic)
[docs]@configurable
def reco_prefilters(gec: bool = True,
skipUT: bool = False,
gec_cut: int = None) -> list[Algorithm]:
"""Typical filters applied before the reconstruction starts.
Args:
gec (bool, optional): Global event cut. Defaults to True.
skipUT (bool, optional): Consideration of UT raw banks. Defaults to False.
gec_cut (int, optional): Value applied by global event cut. Defaults to None,
in which case the default defined by `require_gec` is applied.
Returns:
list[Algorithm]: A list of the filtering algorithms.
"""
opts = dict(skipUT=skipUT)
if gec:
if gec_cut is not None: opts.update(dict(cut=gec_cut))
return [require_gec(**opts)]
else:
return []
[docs]@configurable
def standalone_hlt1_reco(do_mc_checking=False):
""" Run the Hlt1 reconstruction, i.e. tracking and muon id, MC checking optional
Args:
do_mc_checking (bool): Enable MC checking.
Returns:
Reconstruction: Data and control flow of Hlt1 reconstruction.
"""
hlt1_tracks = make_legacy_rec_hlt1_tracks()
pvs = make_pvs()
fitted_tracks = make_VeloKalman_fitted_tracks(hlt1_tracks)
muon_ids = make_muon_id(hlt1_tracks["Forward"])
tracks_with_muon_id = make_tracks_with_muon_id(fitted_tracks, muon_ids)
data = [pvs, fitted_tracks["Pr"], tracks_with_muon_id]
if do_mc_checking:
types_and_locations_for_checkers = {
"Velo": hlt1_tracks["Velo"],
"Upstream": hlt1_tracks["Upstream"],
"Forward": hlt1_tracks["Forward"],
}
data += get_track_checkers(types_and_locations_for_checkers)
data += get_pv_checkers(pvs, hlt1_tracks["Velo"])
return Reconstruction('hlt1_reco', data, reco_prefilters())
[docs]@configurable
def phoenix_data_dump_hlt2():
""" Run the Hlt2 reconstruction up to ProtoParticle and dump the hist and tracks to Phoenix JSON
"""
hlt2_tracks = make_hlt2_tracks_without_UT(light_reco=True)
pvs = make_all_pvs()
# Add Rich
rich_reco = add_hlt2_rich(
light_reco=False,
best_tracks=hlt2_tracks["BestLong"],
do_mc_checking=False,
do_data_monitoring=False)
# Add Calo
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
hlt2_tracks["BestLong"]["v1"],
track_types=["Long", "Downstream", "Ttrack"],
shared_container=False)
# Add Calo
calo = make_calo(tracks_v3, pvs["v3"], trackrels=trackrels)
# Add Muons
muonRecConfs = make_all_muon_pids(tracks=tracks_v3)
muon_conv, muon_tracks = make_conv_muon_pids(muonRecConfs, trackrels)
muon_pids = make_merged_muon_pids(muon_conv)
# Adding hits needed for the JSON dump
VP_hits = make_VeloClusterTrackingSIMD_hits()
FT_hits = make_PrStoreSciFiHits_hits()
UT_hits = make_PrStoreUTHit_hits()
Muon_hits = make_muon_hits()
odin = make_odin()
calo_dig = make_digits()
calo_Edig = calo_dig["digitsEcal"]
calo_Hdig = calo_dig["digitsHcal"]
rich_data = make_rich_pixels(default_rich_reco_options())
# Add proto particles
charged_protos = make_charged_protoparticles(
name="ChargedProtoParticleMaker_{hash}",
tracks=[hlt2_tracks["BestLong"], hlt2_tracks["BestSeed"]],
rich_pids=rich_reco["rich_pids"],
track_types=["Long", "Ttrack"],
calo_pids=calo,
muon_pids=muon_pids)
neutral_protos = make_neutral_protoparticles(
calo_pids=calo)['ProtoParticleLocation']
# Actual Phoenix data dump
### Algorithms in Rec/RecAlgs Project to dump the data into Phoenix .json format
planar_dumper = LHCb__Phoenix__DumpPlanarCaloCellsToJson(
CaloEDigits=calo_Edig, CaloHDigits=calo_Hdig, ODIN=odin)
vp_dumper = LHCb__Phoenix__DumpVPHitEvent(
VPHitsLocation=VP_hits, ODIN=odin)
rich_dumper = LHCb__Phoenix__DumpRichEvent(
DecodedDataLocation=rich_data['RichDecodedData'], ODIN=odin)
ft_dumper = LHCb__Phoenix__DumpFTHitEvent(
FTHitsLocation=FT_hits, ODIN=odin)
ut_dumper = LHCb__Phoenix__DumpUTHitEvent(
UTHitsLocation=UT_hits, ODIN=odin)
muon_dumper = LHCb__Phoenix__DumpMuonHitEvent(
HitContainer=Muon_hits, ODIN=odin)
particles_dumper = LHCb__Phoenix__DumpProtoParticlesEvent(
ChargedProtoParticles=charged_protos,
NeutralProtoParticles=neutral_protos,
ODIN=odin,
VeloTracks=hlt2_tracks["Velo"]["v1"],
BackwardTracks=hlt2_tracks["Velo"]["Pr::backward"],
PrimaryVertices=pvs["v1"])
data = [
planar_dumper, vp_dumper, ft_dumper, ut_dumper, rich_dumper,
muon_dumper, particles_dumper
]
return Reconstruction('phoenix_data_dump_hlt2', data, reco_prefilters())
[docs]def phoenix_data_dump_hlt2_protoparticles():
''' Dump the protoparticle information ONLY '''
reco = reconstruction()
odin = make_odin()
from PyConf.Algorithms import ProtoContainersSharedMerger
charged_protos = ProtoContainersSharedMerger(
InputLocations=[reco["LongProtos"], reco["DownstreamProtos"]])
neutral_protos = reco["NeutralProtos"]
print_charged = PrintProtoParticles(
name="PrintChargedProtos",
Input=charged_protos,
)
print_neutral = PrintProtoParticles(
name="PrintNeutralProtos",
Input=neutral_protos,
)
particles_dumper = LHCb__Phoenix__DumpProtoParticlesEvent(
ChargedProtoParticles=charged_protos,
NeutralProtoParticles=neutral_protos,
ODIN=odin)
data = [print_charged, print_neutral, particles_dumper]
prefilters = [require_gec()]
return Reconstruction('hlt2_protoparticles', data, prefilters)
[docs]@configurable
def standalone_hlt1_reco_retinacluster(do_mc_checking=False):
""" Run the Hlt1 reconstruction, i.e. tracking and muon id, using Retina Cluster, MC checking optional
Args:
do_mc_checking (bool): Enable MC checking.
Returns:
Reconstruction: Data and control flow of Hlt1 reconstruction.
"""
with default_VeloCluster_source.bind(bank_type="VPRetinaCluster"),\
make_RetinaCluster_raw_bank.bind(make_raw=make_SPmixed_raw_banks),\
make_velo_full_clusters.bind( make_raw=make_SPmixed_raw_banks,make_full_cluster=VPRetinaFullClustering),\
make_VeloClusterTrackingSIMD.bind(make_raw=make_RetinaCluster_raw_bank):
return standalone_hlt1_reco(do_mc_checking=do_mc_checking)
[docs]def standalone_hlt1_reco_velo_only():
""" Run the default Hlt1 Velo reconstruction
Returns:
Reconstruction: Data and control flow of Hlt1 reconstruction.
"""
return Reconstruction('hlt1_velo_reco',
[make_legacy_rec_hlt1_tracks()["Velo"]["Pr"]],
reco_prefilters())
@configurable
def standalone_hlt1_muonmatching_reco(do_mc_checking=False,
velo_track_min_ip=0.4 * mm,
tracking_min_pt=80. * MeV):
all_tracks = make_tracks_with_muonmatch_ipcut(
velo_track_min_ip=velo_track_min_ip, tracking_min_pt=tracking_min_pt)
fitted_tracks = make_legacy_rec_hlt1_fitted_tracks(all_tracks)
muon_ids = make_muon_id(all_tracks["Forward"])
tracks_with_muon_id = make_tracks_with_muon_id(fitted_tracks, muon_ids)
data = [fitted_tracks["Pr"], tracks_with_muon_id]
if do_mc_checking:
types_and_locations_for_checkers = {
"Velo": all_tracks["Velo"],
"Upstream": all_tracks["Upstream"],
"Forward": all_tracks["Forward"],
}
data += get_track_checkers(types_and_locations_for_checkers)
return Reconstruction('hlt1_muonmatching_reco', data, reco_prefilters())
[docs]@configurable
def standalone_hlt2_full_track_reco(light_reco=False,
fast_reco=False,
do_mc_checking=False):
""" Run the Hlt2 track reconstruction, i.e. pattern recognition and track fit, MC checking optional
Args:
do_mc_checking (bool): Enable MC checking.
Returns:
Reconstruction: Data and control flow of Hlt2 track reconstruction.
"""
hlt2_tracks = make_hlt2_tracks(light_reco=light_reco, fast_reco=fast_reco)
track_version = "v1"
best_tracks = {}
if light_reco:
best_tracks["BestLong"] = hlt2_tracks["BestLong"]
best_tracks["BestDownstream"] = hlt2_tracks["BestDownstream"]
else:
best_tracks["Best"] = hlt2_tracks["Best"]
pvs = make_pvs()
data = [best_tracks[key][track_version] for key in best_tracks.keys()]
data += [pvs]
if (do_mc_checking):
types_and_locations_for_checkers = {
"Velo": hlt2_tracks["Velo"],
"VeloFull": hlt2_tracks["Velo"],
"Upstream": hlt2_tracks["Upstream"],
"Forward": hlt2_tracks["Forward"],
"ForwardHlt1": hlt2_tracks["ForwardFastFitted"],
"Seed": hlt2_tracks["Seed"],
"Match": hlt2_tracks["Match"],
"Downstream": hlt2_tracks["Downstream"]
}
data += get_track_checkers(types_and_locations_for_checkers)
if light_reco:
data += get_fitted_tracks_checkers(best_tracks)
else:
data += get_best_tracks_checkers(best_tracks["Best"])
return Reconstruction('hlt2_track_reco', data, reco_prefilters())
[docs]@configurable
def standalone_hlt2_full_track_reco_retinacluster(light_reco=False,
fast_reco=False,
do_mc_checking=False):
""" Run the Hlt2 track reconstruction, i.e. pattern recognition and track fit, using Retina Cluster, MC checking optional
Args:
do_mc_checking (bool): Enable MC checking.
Returns:
Reconstruction: Data and control flow of Hlt2 track reconstruction.
"""
with default_VeloCluster_source.bind(bank_type="VPRetinaCluster"),\
make_RetinaCluster_raw_bank.bind(make_raw=make_SPmixed_raw_banks),\
make_velo_full_clusters.bind(make_full_cluster=VPRetinaFullClustering,make_raw=make_SPmixed_raw_banks),\
make_VeloClusterTrackingSIMD.bind(make_raw=make_RetinaCluster_raw_bank):
return standalone_hlt2_full_track_reco(
light_reco=light_reco,
fast_reco=fast_reco,
do_mc_checking=do_mc_checking)
@configurable
def monitor_detector_correlations(calo_objects):
velohits = make_VeloClusterTrackingSIMD_hits()
scifihits = make_PrStoreSciFiHits_hits()
muonhits = make_muon_hits()
rich_pixels = make_rich_pixels(default_rich_reco_options())
data = []
data += [
MonitorECALEnergyTrackerHitsCorrelations(
name="MonitorECALEnergyTrackerHitsCorrelations",
VeloHits=velohits,
SciFiHits=scifihits,
ECALDigits=calo_objects["digitsEcal"])
]
data += [
MonitorECALEnergyRichHitsCorrelations(
name="MonitorECALEnergyRichHitsCorrelations",
ECALDigits=calo_objects["digitsEcal"],
RichHits=rich_pixels["RichDecodedData"])
]
data += [
MonitorDetectorCorrelations(
name="MonitorDetectorCorrelations",
VeloHits=velohits,
SciFiHits=scifihits,
MuonHits=muonhits,
ECALClusters=calo_objects["ecalClusters"],
ECALDigits=calo_objects["digitsEcal"],
HCALDigits=calo_objects["digitsHcal"],
RichPixels=rich_pixels['RichDecodedData'],
CollisionType="pp") # set pp for pp, PbPb for PbPb
]
data += [
MonitorECALEnergyRawEventSizeCorrelations(
name="MonitorECALEnergyRawEventSizeCorrelations",
ECALDigits=calo_objects["digitsEcal"],
RawEvent=default_raw_event("ALL"))
]
return data
[docs]@configurable
def standalone_hlt2_reco(do_mc_checking=False, do_data_monitoring=False):
""" Run the Hlt2 reconstruction up to ProtoParticle making, MC checking optional and data monitoring optional
Args:
do_mc_checking (bool): Enable MC checking.
do_data_monitoring (bool): Enable data monitoring.
Returns:
Reconstruction: Data and control flow of Hlt2 reconstruction.
"""
hlt2_tracks = make_hlt2_tracks(light_reco=False)
best_tracks = hlt2_tracks["Best"]
pvs = make_all_pvs()
data = [best_tracks["v1"], pvs["v3"]]
if (do_mc_checking):
types_and_locations_for_checkers = {
"Velo": hlt2_tracks["Velo"],
"VeloFull": hlt2_tracks["Velo"],
"Upstream": hlt2_tracks["Upstream"],
"Forward": hlt2_tracks["Forward"],
"ForwardHlt1": hlt2_tracks["ForwardFastFitted"],
"Seed": hlt2_tracks["Seed"],
"Match": hlt2_tracks["Match"],
"Downstream": hlt2_tracks["Downstream"]
}
data += get_track_checkers(types_and_locations_for_checkers)
data += get_track_checkers_multiplicity(
types_and_locations_for_checkers)
data += get_best_tracks_checkers(best_tracks)
#PrHits monitoring
data += hits_resolution_checkers()
# Add RICH
rich_reco = add_hlt2_rich(
light_reco=False,
best_tracks=best_tracks,
do_mc_checking=do_mc_checking,
do_data_monitoring=do_data_monitoring)
data += [rich_reco["rich_pids"]]
if rich_reco["monitoring"] is not None:
data += rich_reco["monitoring"]
if rich_reco["mcchecking"] is not None:
data += rich_reco["mcchecking"]
# v3 tracks needed for calo and muon
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
best_tracks["v1"],
track_types=["Long", "Downstream", "Ttrack"],
shared_container=False)
# Add Calo
calo = make_calo(tracks_v3, pvs["v3"], trackrels=trackrels)
data += [calo["ecalSplitClusters"]]
data += [
calo["v1_chargedpids"][tt] for tt in calo["v1_chargedpids"].keys()
]
data += [calo["v1_breminfos"][tt] for tt in calo["v1_breminfos"].keys()]
# Add Muons
muonRecConfs = make_all_muon_pids(tracks=tracks_v3)
muon_conv, muon_tracks = make_conv_muon_pids(muonRecConfs, trackrels)
muon_pids = make_merged_muon_pids(muon_conv)
data += [muon_pids]
# Add monitoring
monitors_outside_gec = []
if do_data_monitoring:
data += monitor_calo(calo, tracks_v3)
data += [
monitor_tracking(
tracks=best_tracks["v1"],
velo_tracks=all_velo_track_types()["v1"],
tracks_for_pvs=hlt2_tracks["Velo"]["v1"],
pvs=pvs["v1"])
]
data += [
# TODO below we rely on the fact that the RawEvent containing
# "VP" also has the other banks. The proper fix would be to
# have the RawBankSizeMonitor accept multiple RawEvents (or
# even RawBank::View's)
RawBankSizeMonitor(RawEventLocation=default_raw_event("VP"))
]
data += [monitor_muon_PID(muon_pids)]
monitors_outside_gec += monitor_detector_correlations(calo)
data += make_mass_monitors()
# Add mc checking
if do_mc_checking:
data += check_calo_efficiency_all(calo)
# TODO: ADD RESOLUTION
# Add proto particles
charged_protos = make_charged_protoparticles(
name="ChargedProtoParticleMaker_{hash}",
tracks=best_tracks['v1'],
rich_pids=rich_reco["rich_pids"],
calo_pids=calo,
muon_pids=muon_pids,
location=None)
data += [charged_protos]
neutral_protos = make_neutral_protoparticles(
calo_pids=calo)['ProtoParticleLocation']
data += [neutral_protos]
data_producers_node = CompositeNode(
"data_with_gec",
data,
combine_logic=NodeLogic.NONLAZY_OR,
force_order=True)
with_gec_node = CompositeNode(
"with_gec",
reco_prefilters() + [data_producers_node],
combine_logic=NodeLogic.LAZY_AND,
force_order=True)
return Reconstruction('hlt2_reco', monitors_outside_gec + [with_gec_node])
[docs]@configurable
def standalone_hlt2_light_reco(fast_reco=False,
do_mc_checking=False,
do_data_monitoring=False,
use_pr_kf=False):
""" Run the Hlt2 light track reconstruction
Args:
do_mc_checking (bool): Enable MC checking.
do_data_monitoring (bool): Enable monitoring.
Returns:
Reconstruction: Data and control flow of Hlt2 track reconstruction.
"""
# tracking
if use_pr_kf and do_data_monitoring:
with PrKalmanFilter.bind(
FillFitResult=True), PrKalmanFilter_Downstream.bind(
FillFitResult=True):
hlt2_tracks = make_hlt2_tracks(
light_reco=True, fast_reco=fast_reco, use_pr_kf=use_pr_kf)
else:
hlt2_tracks = make_hlt2_tracks(
light_reco=True, fast_reco=fast_reco, use_pr_kf=use_pr_kf)
out_track_types = get_default_out_track_types_for_light_reco()
best_tracks = {
track_type: hlt2_tracks[track_type]
for track_type in out_track_types["Best"]
}
data = [tracks["v1"] for tracks in best_tracks.values()]
data += [
hlt2_tracks[track_type]["v1"]
for track_type in out_track_types["Unfitted4Calo"]
]
pvs = make_all_pvs()
data += [pvs["v3"]]
if (do_mc_checking):
types_and_locations_for_checkers = {
"Velo": hlt2_tracks["Velo"],
"VeloFull": hlt2_tracks["Velo"],
"Upstream": hlt2_tracks["Upstream"],
"Forward": hlt2_tracks["Forward"],
"ForwardHlt1": hlt2_tracks["ForwardFastFitted"],
"Seed": hlt2_tracks["Seed"],
"Match": hlt2_tracks["Match"],
"Downstream": hlt2_tracks["Downstream"],
}
data += get_track_checkers(types_and_locations_for_checkers)
data += get_fitted_tracks_checkers(
hlt2_tracks,
fitted_track_types=[
"BestLong",
"BestDownstream",
"BestVelo",
"BestVeloBackward",
"BestUpstream",
"BestSeed",
])
data += hits_resolution_checkers()
# Add RICH
tracks4rich = {
"Long": best_tracks["BestLong"],
"Downstream": best_tracks["BestDownstream"]
}
rich_reco = add_hlt2_rich(
best_tracks=tracks4rich,
light_reco=True,
do_mc_checking=do_mc_checking,
do_data_monitoring=do_data_monitoring,
track_types=list(tracks4rich.keys()))
data += [
rich_reco["rich_pids"][key] for key in rich_reco["rich_pids"].keys()
]
if rich_reco["monitoring"] is not None:
data += rich_reco["monitoring"]
if rich_reco["mcchecking"] is not None:
data += rich_reco["mcchecking"]
trackSelections = {}
for track_type in out_track_types["Best"] + out_track_types[
"Unfitted4Calo"]:
trackSelections[track_type] = TracksToSelection(
InputLocation=hlt2_tracks[track_type]["v1"]).OutputLocation
all_best_tracks = {}
all_best_tracks["v1"] = TrackSelectionMerger(InputLocations=[
trackSelections[track_type] for track_type in out_track_types["Best"]
]).OutputLocation
tracks4calo = [all_best_tracks["v1"]] + [
trackSelections[key] for key in out_track_types["Unfitted4Calo"]
]
alltracks4calo = TrackSelectionMerger(
InputLocations=tracks4calo).OutputLocation
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
alltracks4calo,
track_types=["Long", "Downstream", "Ttrack"],
shared_container=True)
# Add Calo
with make_convert_calo_chargedpids.bind(shared_container=True):
calo = make_calo(tracks_v3, pvs["v3"], trackrels=trackrels)
data += [calo["ecalSplitClusters"]]
data += [
calo["v1_chargedpids"][tt] for tt in calo["v1_chargedpids"].keys()
]
data += [calo["v1_breminfos"][tt] for tt in calo["v1_breminfos"].keys()]
muonRecConfs = make_all_muon_pids(
tracks=tracks_v3, track_types=list(tracks4rich.keys()))
muon_conv, muon_tracks = make_conv_muon_pids(
muonRecConfs, trackrels, shared_container=True)
muon_pids = make_merged_muon_pids(muon_conv)
data += [muon_pids]
monitors_outside_gec = []
if do_data_monitoring:
data += monitor_calo(calo, tracks_v3)
data += [
monitor_tracking(
tracks=all_best_tracks['v1'],
velo_tracks=all_velo_track_types()["v1"],
tracks_for_pvs=hlt2_tracks["Velo"]["v1"],
pvs=pvs["v1"],
use_pr_kf=use_pr_kf)
]
monitors_outside_gec += monitor_detector_correlations(calo)
data += [monitor_muon_PID(muon_pids)]
data += make_mass_monitors()
# Add mc checking
if do_mc_checking:
data += check_calo_efficiency_all(calo, highET=False)
# TODO: ADD RESOLUTION
# proto particles
charged_protos = {}
for key in sorted(tracks4rich):
charged_protos[key] = make_charged_protoparticles(
name=f"ChargedProtoParticleMaker{key}" + "_{hash}",
tracks=tracks4rich[key]['v1'],
rich_pids=rich_reco["rich_pids"][key],
calo_pids=calo,
muon_pids=muon_pids,
track_types=[key],
location=persistable_location(f'{key}Protos'))
data += [charged_protos[key]]
neutral_protos = make_neutral_protoparticles(
calo_pids=calo)['ProtoParticleLocation']
data += [neutral_protos]
data_producers_node = CompositeNode(
"data_with_gec",
data,
combine_logic=NodeLogic.NONLAZY_OR,
force_order=True)
with_gec_node = CompositeNode(
"with_gec",
reco_prefilters() + [data_producers_node],
combine_logic=NodeLogic.LAZY_AND,
force_order=True)
return Reconstruction('hlt2_reco', monitors_outside_gec + [with_gec_node])
[docs]@configurable
def standalone_hlt2_light_reco_without_UT(fast_reco=False,
use_pr_kf=True,
do_mc_checking=False,
do_data_monitoring=False,
monitor_all_tracks=False,
skip_RICH=False,
skip_Calo=False,
skip_Muon=False):
""" Run the Hlt2 track reconstruction optimized for not having the UT detector
Args:
do_mc_checking (bool): Enable MC checking.
do_data_monitoring (bool): Enable monitoring.
Returns:
Reconstruction: Data and control flow of Hlt2 track reconstruction.
"""
if do_data_monitoring and use_pr_kf:
with PrKalmanFilter_noUT.bind(
FillFitResult=True), PrKalmanFilter_Seed.bind(
FillFitResult=True), PrKalmanFilter_Velo.bind(
FillFitResult=True):
hlt2_tracks = make_hlt2_tracks_without_UT(
light_reco=True, fast_reco=fast_reco, use_pr_kf=use_pr_kf)
else:
hlt2_tracks = make_hlt2_tracks_without_UT(
light_reco=True, fast_reco=fast_reco, use_pr_kf=use_pr_kf)
out_track_types = get_default_out_track_types_for_light_reco(skip_UT=True)
if monitor_all_tracks:
monitor_track_types = get_monitoring_track_types_for_light_reco(
skip_UT=True)
else:
monitor_track_types = out_track_types
best_tracks = {
track_type: hlt2_tracks[track_type]
for track_type in out_track_types["Best"]
}
data = [tracks["v1"] for tracks in best_tracks.values()]
data += [
hlt2_tracks[track_type]["v1"]
for track_type in out_track_types["Unfitted4Calo"]
]
pvs = make_all_pvs()
data += [pvs["v3"]]
if (do_mc_checking):
types_and_locations_for_checkers = {
"Velo": hlt2_tracks["Velo"],
"VeloFull": hlt2_tracks["Velo"],
"Forward": hlt2_tracks["Forward"],
"Seed": hlt2_tracks["Seed"],
"Match": hlt2_tracks["Match"],
}
data += get_track_checkers(
types_and_locations_for_checkers,
uthit_efficiency_types=[],
make_links_lhcbids_mcparticles=make_links_lhcbids_mcparticles_VP_FT
)
data += get_fitted_tracks_checkers(
best_tracks,
fitted_track_types=["BestLong"],
make_links_lhcbids_mcparticles=make_links_lhcbids_mcparticles_VP_FT,
with_UT=False)
data += hits_resolution_checkers(with_UT=False)
tracks4rich = {
"Long": best_tracks["BestLong"],
}
# Add RICH
if not skip_RICH:
rich_reco = add_hlt2_rich(
best_tracks=tracks4rich,
light_reco=True,
do_mc_checking=do_mc_checking,
do_data_monitoring=do_data_monitoring,
track_types=list(tracks4rich.keys()),
with_UT=False)
data += [
rich_reco["rich_pids"][key]
for key in rich_reco["rich_pids"].keys()
]
if rich_reco["monitoring"] is not None:
data += rich_reco["monitoring"]
if rich_reco["mcchecking"] is not None:
data += rich_reco["mcchecking"]
# tracks for physics analysis
trackSelections = {}
for track_type in out_track_types["Best"] + out_track_types[
"Unfitted4Calo"]:
trackSelections[track_type] = TracksToSelection(
InputLocation=hlt2_tracks[track_type]["v1"]).OutputLocation
all_best_tracks = {}
all_best_tracks["v1"] = TrackSelectionMerger(InputLocations=[
trackSelections[track_type] for track_type in out_track_types["Best"]
]).OutputLocation
# tracks for monitoring
trackMonitorSelections = {}
for track_type in monitor_track_types["Best"]:
trackMonitorSelections[track_type] = TracksToSelection(
InputLocation=hlt2_tracks[track_type]["v1"]).OutputLocation
monitor_tracks = {}
monitor_tracks["v1"] = TrackSelectionMerger(InputLocations=[
trackMonitorSelections[track_type]
for track_type in monitor_track_types["Best"]
]).OutputLocation
# tracks for Calo
tracks4calo = [all_best_tracks["v1"]] + [
trackSelections[key] for key in out_track_types["Unfitted4Calo"]
]
alltracks4calo = TrackSelectionMerger(
InputLocations=tracks4calo).OutputLocation
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
alltracks4calo, track_types=["Long", "Ttrack"], shared_container=True)
# Add Calo
if not skip_Calo:
with make_convert_calo_chargedpids.bind(shared_container=True):
calo = make_calo(tracks_v3, pvs["v3"], trackrels=trackrels)
data += [calo["ecalSplitClusters"]]
data += [
calo["v1_chargedpids"][tt]
for tt in calo["v1_chargedpids"].keys()
]
data += [
calo["v1_breminfos"][tt] for tt in calo["v1_breminfos"].keys()
]
# Add Muon
if not skip_Muon:
tracktypes_formuon = list(tracks4rich.keys())
muonRecConfs = make_all_muon_pids(
tracks=tracks_v3, track_types=tracktypes_formuon)
muon_conv, muon_tracks = make_conv_muon_pids(
muonRecConfs, trackrels, shared_container=True)
muon_pids = make_merged_muon_pids(muon_conv)
data += [muon_pids]
monitors_outside_gec = []
if do_data_monitoring:
if not skip_Calo:
data += monitor_calo(calo, tracks_v3)
data += [
monitor_tracking(
tracks=monitor_tracks['v1'],
velo_tracks=all_velo_track_types()["v1"],
tracks_for_pvs=hlt2_tracks["Velo"]["v1"],
pvs=pvs["v1"],
use_pr_kf=use_pr_kf)
]
if not skip_Muon:
data += [monitor_muon_PID(muon_pids)]
if not (skip_Muon or skip_Calo or skip_RICH):
monitors_outside_gec += monitor_detector_correlations(calo)
else:
hit_correlations = MonitorDetectorCorrelationsVeloSciFi(
name="MonitorDetectorCorrelations",
VeloHits=make_VeloClusterTrackingSIMD_hits(),
SciFiHits=make_PrStoreSciFiHits_hits(),
CollisionType="pp"
) # set CollisionType pp for pp, PbPb for PbPb
monitors_outside_gec += [hit_correlations]
data += make_mass_monitors()
if do_mc_checking:
if not skip_Calo:
data += check_calo_efficiency_all(calo)
if not (skip_RICH or skip_Calo or skip_Muon):
charged_protos = {}
for key in sorted(tracks4rich):
charged_protos[key] = make_charged_protoparticles(
name=f"ChargedProtoParticleMaker{key}" + "_{hash}",
tracks=tracks4rich[key]['v1'],
rich_pids=rich_reco["rich_pids"][key],
calo_pids=calo,
muon_pids=muon_pids,
track_types=[key],
location=persistable_location(f'{key}Protos'))
data += [charged_protos[key]]
neutral_protos = make_neutral_protoparticles(
calo_pids=calo)['ProtoParticleLocation']
data += [neutral_protos]
data_producers_node = CompositeNode(
"data_with_gec",
data,
combine_logic=NodeLogic.NONLAZY_OR,
force_order=True)
with_gec_node = CompositeNode(
"with_gec",
reco_prefilters(skipUT=True) + [data_producers_node],
combine_logic=NodeLogic.LAZY_AND,
force_order=True)
return Reconstruction('hlt2_reco', monitors_outside_gec + [with_gec_node])
[docs]@configurable
def standalone_hlt2_seeding(do_mc_checking=False, do_data_monitoring=False):
""" Run the Hlt2 track reconstruction optimized for not having the UT detector
Args:
do_mc_checking (bool): Enable MC checking.
do_data_monitoring (bool): Enable monitoring.
Returns:
Reconstruction: Data and control flow of Hlt2 track reconstruction.
"""
seed_tracks = make_PrHybridSeeding_tracks()
data = [seed_tracks["v1"]]
if (do_mc_checking):
types_and_locations_for_checkers = {
"Seed": seed_tracks,
}
data += get_track_checkers(
types_and_locations_for_checkers,
uthit_efficiency_types=[],
make_links_lhcbids_mcparticles=make_links_lhcbids_mcparticles_VP_FT
)
data += hits_resolution_checkers(with_UT=False)
return Reconstruction('hlt2_reco', data, reco_prefilters())
@configurable
def standalone_hlt2_calo_resolution_gamma(light_reco=False):
# if running on XDIGI files
hlt2_tracks = make_hlt2_tracks(light_reco=light_reco)
pvs = make_pvs()
tracks_for_calo = get_default_tracks_for_calo(
hlt2_tracks, light_reco=light_reco)
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
tracks_for_calo,
track_types=["Long", "Downstream", "Ttrack"],
shared_container=light_reco)
calo = make_calo_resolution_gamma(tracks_v3, pvs)
tableMCCaloDigits = CaloFutureDigit2MCLinks2Table(
CaloDigits=calo['digitsEcal'],
MCParticles=mc_unpacker("MCParticles"),
Link=boole_links_digits_mcparticles("EcalDigitsV1"),
).Output
# produce one table with relations (CellID,MCparticle) which can be used for all clusters
# NB use clusters BEFORE overlap as now these are "future" clusters
# eventually could switch to using clusters after shower overlap at this stage
tableMCCaloClusters = CaloClusterMCTruth(
InputRelations=tableMCCaloDigits,
Input=boole_links_digits_mcparticles("EcalDigits"),
MCParticleLocation=mc_unpacker("MCParticles"),
Clusters=calo["clusters"]["ecalClustersNoOverlap"]).Output
data = []
# clusters resolution
data += check_calo_cluster_resolution(
'OverlapDefGC', calo["clusters"]["ecalClustersGCWithCovar"],
tableMCCaloClusters)
data += check_calo_cluster_resolution(
'OverlapDefCA', calo["clusters"]["ecalClustersOverlapWithCovar"],
tableMCCaloClusters)
data += check_calo_photon_resolution('OverlapDefCA', calo["photons"],
tableMCCaloClusters)
data += check_calo_photon_resolution('OverlapDefGC', calo["photonsGC"],
tableMCCaloClusters)
return Reconstruction('hlt2_calo_resolution', data, reco_prefilters())
def standalone_hlt2_calo_cluster_shapes(light_reco=False):
hlt2_tracks = make_hlt2_tracks(light_reco=light_reco)
pvs = make_pvs()
tracks_for_calo = get_default_tracks_for_calo(
hlt2_tracks, light_reco=light_reco)
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
tracks_for_calo,
track_types=["Long", "Downstream", "Ttrack"],
shared_container=light_reco)
calo = make_calo_cluster_shapes(tracks_v3, pvs)
# produce Digit-MCParticle relations that can be used for all clusters
tableMCCaloDigits = CaloFutureDigit2MCLinks2Table(
CaloDigits=calo['digitsEcal'],
MCParticles=mc_unpacker("MCParticles"),
Link=boole_links_digits_mcparticles("EcalDigitsV1"),
).Output
data = []
# produce Cluster-MCParticle relations and check resolution
# for each cluster shape
tableMCCaloClusters = {}
for shape, clusters in calo["clusters"].items():
tableMCCaloClusters[shape] = CaloClusterMCTruth(
InputRelations=tableMCCaloDigits,
Input=boole_links_digits_mcparticles("EcalDigits"),
MCParticleLocation=mc_unpacker("MCParticles"),
Clusters=clusters["ecalClustersOverlapWithCovar"]).Output
# clusters resolution
data += check_calo_cluster_resolution(
shape, clusters["ecalClustersOverlapWithCovar"],
tableMCCaloClusters[shape])
data += check_calo_photon_resolution(
shape, calo["photons_and_electrons"][shape]["photons"],
tableMCCaloClusters[shape])
return Reconstruction('hlt2_calo_resolution', data, reco_prefilters())
def standalone_hlt2_calo_resolution_pi0():
with reconstruction.bind(from_file=False):
reco = reconstruction()
pvs = reco["ExtendedPVs"]
calo = make_calo_resolution_pi0(pvs)
tableMCCaloDigits = CaloFutureDigit2MCLinks2Table(
CaloDigits=calo['digitsEcal'],
MCParticles=mc_unpacker("MCParticles"),
Link=boole_links_digits_mcparticles("EcalDigitsV1"),
).Output
# produce one table with relations (CellID,MCparticle) which can be used for all clusters
# NB use clusters BEFORE overlap as now these are "future" clusters
# eventually could switch to using clusters after shower overlap at this stage
tableMCCaloClusters = CaloClusterMCTruth(
InputRelations=tableMCCaloDigits,
Input=boole_links_digits_mcparticles("EcalDigits"),
MCParticleLocation=mc_unpacker("MCParticles"),
Clusters=calo["clusters"]["ecalClustersNoOverlap"]).Output
data = []
data += check_calo_pi0_resolution(
'-clusDefGC-pi0Def', calo["clusDefGC-pi0Def"], tableMCCaloClusters)
data += check_calo_pi0_resolution(
'-clusDef-pi0Def', calo["clusDef-pi0Def"], tableMCCaloClusters)
return Reconstruction('hlt2_calo_resolution_pi0', data, reco_prefilters())
@configurable
def standalone_hlt2_calo_efficiency(light_reco=False):
# get tracks and pvs, needed for calo reco
hlt2_tracks = make_hlt2_tracks(light_reco=light_reco)
pvs = make_pvs()
# get tracks for calo
if light_reco:
out_track_types = get_default_out_track_types_for_light_reco()
trackSelections = {}
for track_type in out_track_types["Best"] + out_track_types[
"Unfitted4Calo"]:
trackSelections[track_type] = TracksToSelection(
InputLocation=hlt2_tracks[track_type]["v1"]).OutputLocation
all_best_tracks = {}
all_best_tracks["v1"] = TrackSelectionMerger(InputLocations=[
trackSelections[track_type]
for track_type in out_track_types["Best"]
]).OutputLocation
tracks4calo = [all_best_tracks["v1"]] + [
trackSelections[key] for key in out_track_types["Unfitted4Calo"]
]
alltracks4calo = TrackSelectionMerger(
InputLocations=tracks4calo).OutputLocation
for key in hlt2_tracks.keys():
print(key)
print("")
for key in hlt2_tracks.keys():
print(key, hlt2_tracks[key])
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
alltracks4calo,
track_types=["Long", "Downstream", "Ttrack"],
shared_container=True)
else:
best_tracks = hlt2_tracks["Best"]
alltracks4calo = best_tracks["v1"]
tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
alltracks4calo, track_types=["Long", "Downstream", "Ttrack"])
# get calo reco
with make_convert_calo_chargedpids.bind(shared_container=light_reco):
calo = make_calo(tracks_v3, pvs, trackrels=trackrels)
data = check_calo_efficiency_fromB(calo)
return Reconstruction('hlt2_calo_efficiency', data)
@configurable
def standalone_hlt2_calo_tracks_v3(chargedpid_types={
"calo": ["Long", "Downstream"],
"brem": ["Long", "Downstream", "Upstream"]
}):
# get v1 tracks and pvs, needed for calo reco
hlt2_tracks = get_default_hlt2_tracks()
track_containers = make_TrackBestTrackCreator_tracks(
tracks=hlt2_tracks, track_version="v1")
for trktype in track_containers.keys():
hlt2_tracks[trktype] = {"v1": track_containers[trktype]}
# get PVs
pvs = make_pvs()
# get v3 tracks from v1 tracks
best_tracks_v1 = hlt2_tracks["Best"]["v1"]
best_tracks_v3, trackrels = convert_tracks_to_v3_from_v1(
best_tracks_v1,
track_types=list(
dict.fromkeys(chargedpid_types["calo"] +
chargedpid_types["brem"])))
# get calo reco
calo = make_calo(
best_tracks_v3,
pvs,
chargedpid_types=chargedpid_types,
trackrels=trackrels)
# checker
data = [
check_calo_charged_pids(
best_tracks_v1,
calo["v1_chargedpids"]["Long"],
calo["v1_breminfos"]["Long"],
checktracktype=True,
tracktype="Long")
]
# relevant data
for tt in chargedpid_types["calo"]:
data.append(calo["v1_chargedpids"][tt])
for tt in chargedpid_types["brem"]:
data.append(calo["v1_breminfos"][tt])
return Reconstruction('hlt2_calo_tracks_v3', data)
[docs]@configurable
def standalone_hlt2_forward_track_reco(do_mc_checking=False,
use_upstream_tracks=False):
""" Runs only components needed to produce HLT2 long tracks using the PrForwardTracking.
Args:
do_mc_checking (bool) : Enable MC checking.
velo_ut_filter (bool) : Use upstream tracks as input to PrForwardTracking.
Returns:
Reconstruction: Data and control flow of HLT2 forward track reconstruction.
Note:
If MC checking is enabled only the Checker for Forward Tracks will run.
The main purpose is to test different PrForwardTracking configurations such as
using PrVeloUT tracking as filtering input.
"""
hlt1_tracks = make_legacy_rec_hlt1_tracks()
if use_upstream_tracks:
forward_tracks = all_hlt2_forward_track_types(
hlt1_tracks["Upstream"],
make_forward_tracks=make_PrForwardTracking_tracks,
converter=get_PrForwardTracksFromVeloUTV1_converter)
else:
forward_tracks = all_hlt2_forward_track_types(hlt1_tracks["Velo"])
data = [forward_tracks["Pr"]]
if (do_mc_checking):
data += get_track_checkers({"Forward": forward_tracks})
return Reconstruction('hlt2_forward_track_reco', data, reco_prefilters())
[docs]@configurable
def standalone_hlt2_calo_only_reco(do_mc_checking=False,
do_data_monitoring=False):
""" Run only the Hlt2 calorimeter reconstruction up to neutral ProtoParticle making, MC checking optional and data monitoring optional
Args:
do_mc_checking (bool): Enable MC checking.
do_data_monitoring (bool): Enable data monitoring.
Returns:
Reconstruction: Data and control flow of Hlt2 reconstruction.
"""
# make fake container of tracks and PVs
tracks = TracksEmptyProducer()
pvs = PVsEmptyProducer()
# Add Calo
tracks_for_calo, trackrels = convert_tracks_to_v3_from_v1(
tracks, track_types=['Long'])
calo = make_calo(tracks_for_calo, pvs, trackrels=trackrels)
data = [
calo["ecalSplitClusters"],
]
# Add monitoring
if do_data_monitoring:
data += monitor_calo(calo)
# Add mc checking
if do_mc_checking:
data += check_calo_efficiency_fromB(
calo, hypos=False) # no calo hypo efficiency
# TODO: ADD CLUSTER RESOLUTION
# make neutral protoparticles
neutral_protos = make_neutral_protoparticles(
calo_pids=calo)['ProtoParticleLocation']
data += [neutral_protos]
return Reconstruction('hlt2_calo_only_reco', data,
reco_prefilters(gec=False))