Source code for RecoConf.standalone

###############################################################################
# (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))