From 36b3be875dad9a9199b08a8b52a1e9d872aad1b7 Mon Sep 17 00:00:00 2001 From: Fang Wenxing <wxfang@lxslc609.ihep.ac.cn> Date: Sat, 6 Jun 2020 13:21:25 +0800 Subject: [PATCH] update --- Examples/options/LCIO_read_pan.py | 115 + Examples/options/tut_detsim_pan_matrix.py | 217 ++ Reconstruction/Digi_Calo/CMakeLists.txt | 28 + Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp | 151 ++ .../Digi_Calo/src/CaloDigiAlg.cpp_id | 91 + .../Digi_Calo/src/CaloDigiAlg.cpp_v1 | 131 ++ Reconstruction/Digi_Calo/src/CaloDigiAlg.h | 88 + .../CED/.cepcenv/01-09-01/status/install.yml | 20 + Reconstruction/PFA/Pandora/CED/CED/ced.cc | 382 ++++ Reconstruction/PFA/Pandora/CED/CED/ced.h | 146 ++ Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc | 539 +++++ Reconstruction/PFA/Pandora/CED/CED/ced_cli.h | 432 ++++ .../PFA/Pandora/CED/CED/ced_config.h | 204 ++ .../PFA/Pandora/GaudiPandora/CMakeLists.txt | 51 + .../GaudiPandora/include/CaloHitCreator.h | 282 +++ .../GaudiPandora/include/GeometryCreator.h | 158 ++ .../GaudiPandora/include/MCParticleCreator.h | 100 + .../GaudiPandora/include/PandoraPFAlg.h | 320 +++ .../Pandora/GaudiPandora/include/PfoCreator.h | 221 ++ .../GaudiPandora/include/TrackCreator.h | 378 ++++ .../Pandora/GaudiPandora/include/Utility.h | 6 + .../GaudiPandora/include/cellIDDecoder.h | 127 ++ .../GaudiPandora/src/CaloHitCreator.cpp | 867 +++++++ .../GaudiPandora/src/GeometryCreator.cpp | 433 ++++ .../GaudiPandora/src/MCParticleCreator.cpp | 378 ++++ .../Pandora/GaudiPandora/src/PandoraPFAlg.cpp | 910 ++++++++ .../Pandora/GaudiPandora/src/PfoCreator.cpp | 429 ++++ .../Pandora/GaudiPandora/src/TrackCreator.cpp | 992 ++++++++ .../PFA/Pandora/GaudiPandora/src/Utility.cpp | 7 + .../MarlinUtil/01-08/source/ClusterShapes.cc | 2005 +++++++++++++++++ .../MarlinUtil/01-08/source/ClusterShapes.h | 356 +++ .../MarlinUtil/01-08/source/HelixClass.cc | 768 +++++++ .../MarlinUtil/01-08/source/HelixClass.h | 302 +++ .../MarlinUtil/01-08/source/LineClass.cc | 73 + .../MarlinUtil/01-08/source/LineClass.h | 32 + .../PFA/Pandora/MatrixPandora/CMakeLists.txt | 57 + .../MatrixPandora/include/CaloHitCreator.h | 298 +++ .../MatrixPandora/include/GeometryCreator.h | 166 ++ .../MatrixPandora/include/MCParticleCreator.h | 98 + .../MatrixPandora/include/PandoraMatrixAlg.h | 324 +++ .../MatrixPandora/include/PfoCreator.h | 219 ++ .../MatrixPandora/include/TrackCreator.h | 373 +++ .../Pandora/MatrixPandora/include/Utility.h | 6 + .../MatrixPandora/include/cellIDDecoder.h | 127 ++ .../MatrixPandora/src/CaloHitCreator.cpp | 959 ++++++++ .../MatrixPandora/src/GeometryCreator.cpp | 488 ++++ .../MatrixPandora/src/MCParticleCreator.cpp | 372 +++ .../MatrixPandora/src/PandoraMatrixAlg.cpp | 932 ++++++++ .../Pandora/MatrixPandora/src/PfoCreator.cpp | 429 ++++ .../MatrixPandora/src/TrackCreator.cpp | 987 ++++++++ .../PFA/Pandora/MatrixPandora/src/Utility.cpp | 7 + 51 files changed, 17581 insertions(+) create mode 100644 Examples/options/LCIO_read_pan.py create mode 100644 Examples/options/tut_detsim_pan_matrix.py create mode 100644 Reconstruction/Digi_Calo/CMakeLists.txt create mode 100644 Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp create mode 100644 Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_id create mode 100644 Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_v1 create mode 100644 Reconstruction/Digi_Calo/src/CaloDigiAlg.h create mode 100644 Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml create mode 100644 Reconstruction/PFA/Pandora/CED/CED/ced.cc create mode 100644 Reconstruction/PFA/Pandora/CED/CED/ced.h create mode 100644 Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc create mode 100644 Reconstruction/PFA/Pandora/CED/CED/ced_cli.h create mode 100644 Reconstruction/PFA/Pandora/CED/CED/ced_config.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp create mode 100644 Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc create mode 100644 Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h create mode 100644 Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc create mode 100644 Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h create mode 100644 Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc create mode 100644 Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp create mode 100644 Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp diff --git a/Examples/options/LCIO_read_pan.py b/Examples/options/LCIO_read_pan.py new file mode 100644 index 00000000..97b5f9e9 --- /dev/null +++ b/Examples/options/LCIO_read_pan.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from Gaudi.Configuration import * +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") + +# read LCIO files +from Configurables import LCIOInput +read = LCIOInput("read") +read.inputs = [ +#"/cefs/data/FullSim/CEPC240/CEPC_v4/higgs/smart_final_states/E240.Pffh_invi.e0.p0.whizard195//ffh_inv.e0.p0.00001_1000_sim.slcio" +#"/junofs/users/wxfang/CEPC/CEPCOFF/doReco/reco_output/nnh_aa.e0.p0.00010_000000_rec.slcio" +"/cefs/higgs/wxfang/cepc/Pandora/CaloDigi/gamma/Digi_sim_0.slcio" +] +read.collections = { + #"COILCollection" : "SimTrackerHit", + #"EcalBarrelSiliconCollection" : "SimCalorimeterHit", + "MCParticle" : "MCParticle", + "ECALBarrel" : "CalorimeterHit", + "ECALEndcap" : "CalorimeterHit", + "ECALOther" : "CalorimeterHit", + "HCALBarrel" : "CalorimeterHit", + "HCALEndcap" : "CalorimeterHit", + "HCALOther" : "CalorimeterHit", + "MUON" : "CalorimeterHit", + "LCAL" : "CalorimeterHit", + "LHCAL" : "CalorimeterHit", + "BCAL" : "CalorimeterHit", + #"MarlinTrkTracks" : "Track" + #"TPCCollection" : "SimTrackerHit", + #"VXDCollection" : "SimTrackerHit" +} +############################################################################## +from Configurables import GearSvc +gearSvc = GearSvc("GearSvc") +gearSvc.GearXMLFile = "/junofs/users/wxfang/CEPC/CEPCOFF/doSim/fullDet/GearOutput.xml" +############################################################################## +from Configurables import PandoraPFAlg + +pandoralg = PandoraPFAlg("PandoraPFAlg") +## KEEP same with lcioinput name for the ReadXXX ########### +pandoralg.ReadMCParticle = "MCParticle" +pandoralg.ReadECALBarrel = "ECALBarrel" +pandoralg.ReadECALEndcap = "ECALEndcap" +pandoralg.ReadECALOther = "ECALOther" +pandoralg.ReadHCALBarrel = "HCALBarrel" +pandoralg.ReadHCALEndcap = "HCALEndcap" +pandoralg.ReadHCALOther = "HCALOther" +pandoralg.ReadMUON = "MUON" +pandoralg.ReadLCAL = "LCAL" +pandoralg.ReadLHCAL = "LHCAL" +pandoralg.ReadBCAL = "BCAL" +pandoralg.ReadKinkVertices = "KinkVertices" +pandoralg.ReadProngVertices = "ProngVertices" +pandoralg.ReadSplitVertices = "SplitVertices" +pandoralg.ReadV0Vertices = "V0Vertices" +pandoralg.ReadTracks = "MarlinTrkTracks" +pandoralg.WriteClusterCollection = "PandoraClusters" +pandoralg.WriteReconstructedParticleCollection = "PandoraPFOs" +pandoralg.WriteVertexCollection = "PandoraPFANewStartVertices" +pandoralg.AnaOutput = "/cefs/higgs/wxfang/cepc/Pandora/Ana/gamma/Ana_gamma_test.root" + +pandoralg.PandoraSettingsDefault_xml = "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" +#### Do not chage the collection name, only add or delete ############### +pandoralg.TrackCollections = ["MarlinTrkTracks"] +pandoralg.ECalCaloHitCollections= ["ECALBarrel", "ECALEndcap", "ECALOther"] +pandoralg.HCalCaloHitCollections= ["HCALBarrel", "HCALEndcap", "HCALOther"] +pandoralg.LCalCaloHitCollections= ["LCAL"] +pandoralg.LHCalCaloHitCollections= ["LHCAL"] +pandoralg.MuonCaloHitCollections= ["MUON"] +pandoralg.MCParticleCollections = ["MCParticle"] +pandoralg.RelCaloHitCollections = ["RecoCaloAssociation_ECALBarrel", "RecoCaloAssociation_ECALEndcap", "RecoCaloAssociation_ECALOther", "RecoCaloAssociation_HCALBarrel", "RecoCaloAssociation_HCALEndcap", "RecoCaloAssociation_HCALOther", "RecoCaloAssociation_LCAL", "RecoCaloAssociation_LHCAL", "RecoCaloAssociation_MUON"] +pandoralg.RelTrackCollections = ["MarlinTrkTracksMCTruthLink"] +pandoralg.KinkVertexCollections = ["KinkVertices"] +pandoralg.ProngVertexCollections= ["ProngVertices"] +pandoralg.SplitVertexCollections= ["SplitVertices"] +pandoralg.V0VertexCollections = ["V0Vertices"] +pandoralg.ECalToMipCalibration = 160.0 +pandoralg.HCalToMipCalibration = 34.8 +pandoralg.ECalMipThreshold = 0.5 +pandoralg.HCalMipThreshold = 0.3 +pandoralg.ECalToEMGeVCalibration= 0.9 #for G2CD Digi, 1.007 for NewLDCaloDigi +pandoralg.HCalToEMGeVCalibration= 1.007 +pandoralg.ECalToHadGeVCalibrationBarrel= 1.12 #very small effect +pandoralg.ECalToHadGeVCalibrationEndCap= 1.12 +pandoralg.HCalToHadGeVCalibration= 1.07 +pandoralg.MuonToMipCalibration= 10.0 +pandoralg.DigitalMuonHits= 0 +pandoralg.MaxHCalHitHadronicEnergy = 1.0 +pandoralg.UseOldTrackStateCalculation= 0 +pandoralg.AbsorberRadLengthECal= 0.2854 +pandoralg.AbsorberIntLengthECal= 0.0101 +pandoralg.AbsorberRadLengthHCal= 0.0569 +pandoralg.AbsorberIntLengthHCal= 0.006 +pandoralg.AbsorberRadLengthOther= 0.0569 +pandoralg.AbsorberIntLengthOther= 0.006 + +############################################################################## + +# write PODIO file +from Configurables import PodioOutput +write = PodioOutput("write") +write.filename = "test.root" +write.outputCommands = ["keep *"] + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( + #TopAlg = [read, pandoralg, write], + TopAlg = [read, pandoralg], + EvtSel = 'NONE', + EvtMax = 10, + ExtSvc = [dsvc, gearSvc], + OutputLevel=INFO +) diff --git a/Examples/options/tut_detsim_pan_matrix.py b/Examples/options/tut_detsim_pan_matrix.py new file mode 100644 index 00000000..50fdf5ba --- /dev/null +++ b/Examples/options/tut_detsim_pan_matrix.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +import os +print(os.environ["DD4HEP_LIBRARY_PATH"]) +import sys +# sys.exit(0) + +from Gaudi.Configuration import * + +############################################################################## +# Random Number Svc +############################################################################## +from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_ + +# rndmengine = HepRndm__Engine_CLHEP__RanluxEngine_() # The default engine in Gaudi +rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_() # The default engine in Geant4 +rndmengine.SetSingleton = True +rndmengine.Seeds = [42] + +# rndmgensvc = RndmGenSvc("RndmGenSvc") +# rndmgensvc.Engine = rndmengine.name() + + +############################################################################## +# Event Data Svc +############################################################################## +#from Configurables import CEPCDataSvc +#dsvc = CEPCDataSvc("EventDataSvc") +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") + + +############################################################################## +# Geometry Svc +############################################################################## + +# geometry_option = "CepC_v4-onlyTracker.xml" +geometry_option = "CepC_v4-onlyVXD.xml" + +if not os.getenv("DETCEPCV4ROOT"): + print("Can't find the geometry. Please setup envvar DETCEPCV4ROOT." ) + sys.exit(-1) + +geometry_path = os.path.join(os.getenv("DETCEPCV4ROOT"), "compact", geometry_option) +if not os.path.exists(geometry_path): + print("Can't find the compact geometry file: %s"%geometry_path) + sys.exit(-1) + +from Configurables import GeoSvc +geosvc = GeoSvc("GeoSvc") +#geosvc.compact = geometry_path +geosvc.compact = "../Detector/DetEcalMatrix/compact/det.xml" + +############################################################################## +# Physics Generator +############################################################################## +from Configurables import GenAlgo +from Configurables import GtGunTool +from Configurables import StdHepRdr +from Configurables import SLCIORdr +from Configurables import HepMCRdr +from Configurables import GenPrinter + +gun = GtGunTool("GtGunTool") +gun.Particles = ["gamma"] +#gun.Energies = [0.5, 1] # GeV +#gun.EnergyMin = [0.1] # GeV +gun.EnergyMin = [1] # GeV +gun.EnergyMax = [1] # GeV +gun.ThetaMins = [90] # rad; 45deg +gun.ThetaMaxs = [90] # rad; 45deg +gun.PhiMins = [0] # rad; 0deg +gun.PhiMaxs = [0] # rad; 360deg + +stdheprdr = StdHepRdr("StdHepRdr") +#stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +#stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +stdheprdr.Input = "/cefs/data/stdhep/CEPC250/higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.stdhep" + +# lciordr = SLCIORdr("SLCIORdr") +# lciordr.Input = "/cefs/data/stdhep/lcio250/signal/Higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.slcio" + +# hepmcrdr = HepMCRdr("HepMCRdr") +# hepmcrdr.Input = "example_UsingIterators.txt" + +genprinter = GenPrinter("GenPrinter") + +genalg = GenAlgo("GenAlgo") +genalg.GenTools = ["GtGunTool"] +#genalg.GenTools = ["StdHepRdr"] +# genalg.GenTools = ["StdHepRdr", "GenPrinter"] +# genalg.GenTools = ["SLCIORdr", "GenPrinter"] +# genalg.GenTools = ["HepMCRdr", "GenPrinter"] + +############################################################################## +# Detector Simulation +############################################################################## +from Configurables import DetSimSvc + +detsimsvc = DetSimSvc("DetSimSvc") + +# from Configurables import ExampleAnaElemTool +# example_anatool = ExampleAnaElemTool("ExampleAnaElemTool") + +from Configurables import DetSimAlg + +detsimalg = DetSimAlg("DetSimAlg") + +# detsimalg.VisMacs = ["vis.mac"] + +detsimalg.RunCmds = [ +# "/tracking/verbose 1", +] +detsimalg.AnaElems = [ + # example_anatool.name() + # "ExampleAnaElemTool" + "Edm4hepWriterAnaElemTool" +] +detsimalg.RootDetElem = "WorldDetElemTool" + +from Configurables import AnExampleDetElemTool +example_dettool = AnExampleDetElemTool("AnExampleDetElemTool") + +############################################################################## +from Configurables import CaloDigiAlg +example_CaloDigiAlg = CaloDigiAlg("CaloDigiAlg") +example_CaloDigiAlg.Scale = 1 +example_CaloDigiAlg.SimCaloHitCollection = "SimCalorimeterCol" +example_CaloDigiAlg.CaloHitCollection = "ECALBarrel" +############################################################################## +from Configurables import GearSvc +gearSvc = GearSvc("GearSvc") +gearSvc.GearXMLFile = "/junofs/users/wxfang/CEPC/CEPCOFF/doSim/fullDet/GearOutput.xml" +############################################################################## +#from Configurables import PandoraPFAlg +from Configurables import PandoraMatrixAlg + +#pandoralg = PandoraPFAlg("PandoraPFAlg") +pandoralg = PandoraMatrixAlg("PandoraMatrixAlg") +## KEEP same with lcioinput name for the ReadXXX ########### +pandoralg.ReadMCParticle = "MCParticle" +pandoralg.ReadECALBarrel = "ECALBarrel" +pandoralg.ReadECALEndcap = "ECALEndcap" +pandoralg.ReadECALOther = "ECALOther" +pandoralg.ReadHCALBarrel = "HCALBarrel" +pandoralg.ReadHCALEndcap = "HCALEndcap" +pandoralg.ReadHCALOther = "HCALOther" +pandoralg.ReadMUON = "MUON" +pandoralg.ReadLCAL = "LCAL" +pandoralg.ReadLHCAL = "LHCAL" +pandoralg.ReadBCAL = "BCAL" +pandoralg.ReadKinkVertices = "KinkVertices" +pandoralg.ReadProngVertices = "ProngVertices" +pandoralg.ReadSplitVertices = "SplitVertices" +pandoralg.ReadV0Vertices = "V0Vertices" +pandoralg.ReadTracks = "MarlinTrkTracks" +pandoralg.WriteClusterCollection = "PandoraClusters" +pandoralg.WriteReconstructedParticleCollection = "PandoraPFOs" +pandoralg.WriteVertexCollection = "PandoraPFANewStartVertices" +pandoralg.AnaOutput = "/cefs/higgs/wxfang/cepc/Pandora/Ana/gamma/Ana_gamma_Matrix_NewTest.root" + +pandoralg.PandoraSettingsDefault_xml = "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" +#### Do not chage the collection name, only add or delete ############### +pandoralg.TrackCollections = ["MarlinTrkTracks"] +pandoralg.ECalCaloHitCollections= ["ECALBarrel", "ECALEndcap", "ECALOther"] +pandoralg.HCalCaloHitCollections= ["HCALBarrel", "HCALEndcap", "HCALOther"] +pandoralg.LCalCaloHitCollections= ["LCAL"] +pandoralg.LHCalCaloHitCollections= ["LHCAL"] +pandoralg.MuonCaloHitCollections= ["MUON"] +pandoralg.MCParticleCollections = ["MCParticle"] +pandoralg.RelCaloHitCollections = ["RecoCaloAssociation_ECALBarrel", "RecoCaloAssociation_ECALEndcap", "RecoCaloAssociation_ECALOther", "RecoCaloAssociation_HCALBarrel", "RecoCaloAssociation_HCALEndcap", "RecoCaloAssociation_HCALOther", "RecoCaloAssociation_LCAL", "RecoCaloAssociation_LHCAL", "RecoCaloAssociation_MUON"] +pandoralg.RelTrackCollections = ["MarlinTrkTracksMCTruthLink"] +pandoralg.KinkVertexCollections = ["KinkVertices"] +pandoralg.ProngVertexCollections= ["ProngVertices"] +pandoralg.SplitVertexCollections= ["SplitVertices"] +pandoralg.V0VertexCollections = ["V0Vertices"] +pandoralg.ECalToMipCalibration = 112 #1000MeV/8.918 #CEPC :160.0 +pandoralg.HCalToMipCalibration = 34.8 +pandoralg.ECalMipThreshold = 0.225# 8.918*0.225=2.00655 #CEPC 0.5 +pandoralg.HCalMipThreshold = 0.3 +pandoralg.ECalToEMGeVCalibration= 1.# BGO, to be tuned # CEPC: 0.9 for G2CD Digi, 1.007 for NewLDCaloDigi +pandoralg.HCalToEMGeVCalibration= 1.007 +pandoralg.ECalToHadGeVCalibrationBarrel= 1.12 #very small effect +pandoralg.ECalToHadGeVCalibrationEndCap= 1.12 +pandoralg.HCalToHadGeVCalibration= 1.07 +pandoralg.MuonToMipCalibration= 10.0 +pandoralg.DigitalMuonHits= 0 +pandoralg.MaxHCalHitHadronicEnergy = 1.0 +pandoralg.UseOldTrackStateCalculation= 0 +pandoralg.AbsorberRadLengthECal= 0.08945 #BG0: 1/11.18 mm , CEPC: 0.2854 = 1/3.504 mm +pandoralg.AbsorberIntLengthECal= 0.00448 #BG0: 1/223.2 mm , CEPC: 0.0101 = 1/99.46 mm +pandoralg.AbsorberRadLengthHCal= 0.0569 +pandoralg.AbsorberIntLengthHCal= 0.006 +pandoralg.AbsorberRadLengthOther= 0.0569 +pandoralg.AbsorberIntLengthOther= 0.006 + +############################################################################## + +# write PODIO file +from Configurables import PodioOutput +write = PodioOutput("write") +write.filename = "test.root" +write.outputCommands = ["keep *"] + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg = [genalg, detsimalg, example_CaloDigiAlg, pandoralg], + #TopAlg = [genalg, detsimalg], + #TopAlg = [genalg, detsimalg, write], + #TopAlg = [read, pandoralg], + EvtSel = 'NONE', + EvtMax = 100, + #ExtSvc = [rndmengine, dsvc, geosvc, gearSvc], + ExtSvc = [rndmengine, dsvc, geosvc, gearSvc,detsimsvc], + OutputLevel=INFO +) diff --git a/Reconstruction/Digi_Calo/CMakeLists.txt b/Reconstruction/Digi_Calo/CMakeLists.txt new file mode 100644 index 00000000..5bec00f6 --- /dev/null +++ b/Reconstruction/Digi_Calo/CMakeLists.txt @@ -0,0 +1,28 @@ +gaudi_subdir(Digi_Calo v0r0) + +find_package(DD4hep COMPONENTS DDG4 REQUIRED) +find_package(EDM4HEP REQUIRED ) +message("EDM4HEP_INCLUDE_DIRS: ${EDM4HEP_INCLUDE_DIR}") +message("EDM4HEP_LIB: ${EDM4HEP_LIBRARIES}") +include_directories(${EDM4HEP_INCLUDE_DIR}) +link_libraries("/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/externals/97.0.0/EDM4hep/lib64/libedm4hep.so") + +find_package(CLHEP REQUIRED) +find_package(podio REQUIRED ) + +set(srcs + src/*.cpp +) + +gaudi_depends_on_subdirs( + Detector/DetInterface +) +## Modules +gaudi_add_module(Digi_Calo ${srcs} + INCLUDE_DIRS FWCore GaudiKernel GaudiAlgLib CLHEP DD4hep + LINK_LIBRARIES FWCore GaudiKernel GaudiAlgLib CLHEP DD4hep ${DD4hep_COMPONENT_LIBRARIES} DDRec +) +#gaudi_add_module(Digi_Calo ${srcs} +# INCLUDE_DIRS FWCore GaudiKernel GaudiAlgLib CLHEP +# LINK_LIBRARIES FWCore GaudiKernel GaudiAlgLib CLHEP +#) diff --git a/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp new file mode 100644 index 00000000..1370dda8 --- /dev/null +++ b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "CaloDigiAlg.h" + + +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/Vector3f.h" + +#include "DD4hep/Detector.h" +#include <DD4hep/Objects.h> +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> + + +#include <math.h> +#include <cmath> +#include <algorithm> + +DECLARE_COMPONENT( CaloDigiAlg ) + +CaloDigiAlg::CaloDigiAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + + // Input collections + declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); + + // Output collections + declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); + + +} + +StatusCode CaloDigiAlg::initialize() +{ + + std::cout<<"CaloDigiAlg::m_scale="<<m_scale<<std::endl; + m_geosvc = service<IGeoSvc>("GeoSvc"); + if ( !m_geosvc ) throw "CaloDigiAlg :Failed to find GeoSvc ..."; + dd4hep::Detector* m_dd4hep = m_geosvc->lcdd(); + if ( !m_dd4hep ) throw "CaloDigiAlg :Failed to get dd4hep::Detector ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + try{ + const dd4hep::DetElement &detElement = m_dd4hep->detector("CaloDetector"); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>& layerLayout = Data->layers; + assert(layerLayout.size()>=1); + m_layerLayout = &layerLayout; + std::cout<<"saved m_layerLayout"<<std::endl; + } + catch(...) + { + throw "CaloDigiAlg :Failed to get LayeredCalorimeterData ..."; + } + return GaudiAlgorithm::initialize(); +} + +StatusCode CaloDigiAlg::execute() +{ + std::map<std::string, std::vector<edm4hep::SimCalorimeterHit> > id_vhit_map; + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); + if(SimHitCol == 0) + { + std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; + return StatusCode::SUCCESS; + } + std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; + float tot_sim_en = 0; + for( int i = 0; i < SimHitCol->size(); i++ ) + { + edm4hep::SimCalorimeterHit SimHit = SimHitCol->at(i); + float en = SimHit.getEnergy(); + tot_sim_en += en; + std::string id = GetCode(&SimHit); + //std::cout<<"sim i ="<< i<<",id="<< id<<",x="<<SimHit.getPosition().x<<",y="<<SimHit.getPosition().y<<",z="<<SimHit.getPosition().z <<std::endl; + if(id_vhit_map.find(id) != id_vhit_map.end()) id_vhit_map[id].push_back(SimHit); + else + { + std::vector<edm4hep::SimCalorimeterHit> vect; + vect.push_back(SimHit); + id_vhit_map[id] = vect; + } + } + float tot_en = 0; + for(std::map<std::string, std::vector <edm4hep::SimCalorimeterHit> >::iterator iter = id_vhit_map.begin(); iter != id_vhit_map.end(); iter++) + { + float energy = 0; + float x0 = 0; + float y0 = 0; + float z0 = 0; + for(int j=0; j < iter->second.size(); j++) + { + float hit_en = iter->second.at(j).getEnergy(); + energy += hit_en; + x0 += hit_en*iter->second.at(j).getPosition().x ; + y0 += hit_en*iter->second.at(j).getPosition().y ; + z0 += hit_en*iter->second.at(j).getPosition().z ; + } + x0 = x0/energy; + y0 = y0/energy; + z0 = z0/energy; + edm4hep::Vector3f pos(x0, y0, z0); + energy = energy*m_scale; + auto caloHit = caloVec->create(); + //caloHit.setCellID (iter->second.getCellID()); + caloHit.setEnergy (energy); + caloHit.setPosition(pos); + tot_en += caloHit.getEnergy(); + } + + std::cout<<"total sim e ="<< tot_sim_en <<std::endl; + std::cout<<"digi, output digi hit size="<< caloVec->size()<<",tot_en="<<tot_en <<std::endl; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode CaloDigiAlg::finalize() +{ + info() << "Processed " << _nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} + + +std::string CaloDigiAlg::GetCode(const edm4hep::SimCalorimeterHit *const pHit) const +{ + int layer = -1 ; + for (unsigned int i = 0, iMax = m_layerLayout->size(); i < iMax; ++i) + { + const float distance(m_layerLayout->at(i).distance); + const float sensitive_thickness(m_layerLayout->at(i).sensitive_thickness); + if( (distance - 0.5*sensitive_thickness) <= pHit->getPosition().x && pHit->getPosition().x <= (distance + 0.5*sensitive_thickness)) {layer = i ; break;} + } + if(layer==-1) + { + int lmax = m_layerLayout->size()-1; + std::cout<<"Error BarrelLayer, set to default 1, Hit.x="<<pHit->getPosition().x<<", min_x="<<m_layerLayout->at(0).distance-0.5*m_layerLayout->at(0).sensitive_thickness<<", max_x="<<m_layerLayout->at(lmax).distance+0.5*m_layerLayout->at(lmax).sensitive_thickness<<std::endl; + layer = 0; + } + float cellSize0 = m_layerLayout->at(layer).cellSize0; + float cellSize1 = m_layerLayout->at(layer).cellSize1; + int cell0 = floor((pHit->getPosition().y+0.5*cellSize0)/cellSize0); + int cell1 = floor((pHit->getPosition().z+0.5*cellSize1)/cellSize1); + std::string sl = std::to_string(layer); + std::string s0 = std::to_string(cell0); + std::string s1 = std::to_string(cell1); + std::string id = sl+"_"+s0+"_"+s1 ; + return id; +} diff --git a/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_id b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_id new file mode 100644 index 00000000..e25ad95b --- /dev/null +++ b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_id @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "CaloDigiAlg.h" + + +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" + +#include "DD4hep/Detector.h" +#include <DD4hep/Objects.h> + +#include <cmath> +#include <algorithm> + +DECLARE_COMPONENT( CaloDigiAlg ) + +CaloDigiAlg::CaloDigiAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + + // Input collections + declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); + + // Output collections + declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); + + +} + +StatusCode CaloDigiAlg::initialize() +{ + + m_geosvc = service<IGeoSvc>("GeoSvc"); + if ( !m_geosvc ) throw "CaloDigiAlg :Failed to find GeoSvc ..."; + dd4hep::Detector* m_dd4hep = m_geosvc->lcdd(); + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + + std::cout<<"m_scale="<<m_scale<<std::endl; + + return GaudiAlgorithm::initialize(); +} + +StatusCode CaloDigiAlg::execute() +{ + std::map<unsigned long long, edm4hep::SimCalorimeterHit> id_hit_map; + std::map<unsigned long long, int > test_map; + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); + double tot_e = 0 ; + if(SimHitCol == 0) + { + std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; + return StatusCode::SUCCESS; + } + std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; + for( int i = 0; i < SimHitCol->size(); i++ ) + { + edm4hep::SimCalorimeterHit SimHit = SimHitCol->at(i); + unsigned long long id = SimHit.getCellID(); + /* + dd4hep::Position gpos(SimHit.getPosition().x, SimHit.getPosition().y, SimHit.getPosition().z); + long long int cell_id = m_cellIDConverter->cellID(gpos); + signed long long id2 = (signed long long) SimHit.getCellID(); + std::cout<<"sim gpos x="<<gpos.x()<<",y="<<gpos.y()<<",z="<<gpos.z()<<",id0="<<id<<",id1="<<cell_id<<",id2="<<id2<<std::endl; + */ + float en = SimHit.getEnergy(); + tot_e += en; + test_map[id] = 1; + if ( id_hit_map.find(id) != id_hit_map.end()) id_hit_map[id].setEnergy(id_hit_map[id].getEnergy() + en); + else id_hit_map[id] = SimHit ; + } + for(std::map<unsigned long long, edm4hep::SimCalorimeterHit>::iterator iter = id_hit_map.begin(); iter != id_hit_map.end(); iter++) + { + auto caloHit = caloVec->create(); + caloHit.setCellID((iter->second).getCellID()); + caloHit.setEnergy((iter->second).getEnergy()*m_scale); + caloHit.setPosition((iter->second).getPosition()); + } + + std::cout<<"total sim e ="<< tot_e <<std::endl; + std::cout<<"digi, output digi hit size="<< caloVec->size() <<std::endl; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode CaloDigiAlg::finalize() +{ + info() << "Processed " << _nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} diff --git a/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_v1 b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_v1 new file mode 100644 index 00000000..d1d19a49 --- /dev/null +++ b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp_v1 @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "CaloDigiAlg.h" + + +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/Vector3f.h" + +#include "DD4hep/Detector.h" +#include <DD4hep/Objects.h> +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> + + +#include <cmath> +#include <algorithm> + +DECLARE_COMPONENT( CaloDigiAlg ) + +CaloDigiAlg::CaloDigiAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + + // Input collections + declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); + + // Output collections + declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); + + +} + +StatusCode CaloDigiAlg::initialize() +{ + + std::cout<<"CaloDigiAlg::m_scale="<<m_scale<<std::endl; + m_geosvc = service<IGeoSvc>("GeoSvc"); + if ( !m_geosvc ) throw "CaloDigiAlg :Failed to find GeoSvc ..."; + dd4hep::Detector* m_dd4hep = m_geosvc->lcdd(); + if ( !m_dd4hep ) throw "CaloDigiAlg :Failed to get dd4hep::Detector ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + try{ + const dd4hep::DetElement &detElement = m_dd4hep->detector("CaloDetector"); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>& layerLayout = Data->layers; + assert(layerLayout.size()>=1); + float cellSize0 = layerLayout.at(0).cellSize0; + float cellSize1 = layerLayout.at(0).cellSize1; + float cellThickness = layerLayout.at(0).sensitive_thickness; + m_length = sqrt(cellSize0*cellSize0 + cellSize1*cellSize1 + cellThickness*cellThickness); + std::cout<<"CaloDigiAlg::cellSize0="<<cellSize0<<",cellSize1="<<cellSize1<<",cellThickness="<<cellThickness<<",m_length="<<m_length<<std::endl; + } + catch(...) + { + throw "CaloDigiAlg :Failed to get LayeredCalorimeterData ..."; + } + return GaudiAlgorithm::initialize(); +} + +StatusCode CaloDigiAlg::execute() +{ + std::vector< edm4hep::SimCalorimeterHit > sim_vec; + std::map<unsigned long long, edm4hep::SimCalorimeterHit> id_hit_map; + std::map<unsigned long long, int > test_map; + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); + if(SimHitCol == 0) + { + std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; + return StatusCode::SUCCESS; + } + std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; + float tot_sim_en = 0; + for( int i = 0; i < SimHitCol->size(); i++ ) + { + int index = -1; + float dis_min = m_length;//10mm*10mm*10mm + bool found = false; + edm4hep::SimCalorimeterHit SimHit = SimHitCol->at(i); + float en = SimHit.getEnergy(); + tot_sim_en += en; + float x0 = SimHit.getPosition().x ; + float y0 = SimHit.getPosition().y ; + float z0 = SimHit.getPosition().z ; + //std::cout<<"x0="<<x0<<",y0="<<y0<<",z0="<<z0<<std::endl; + for(int j=0; j<sim_vec.size(); j++) + { + float x = sim_vec.at(j).getPosition().x ; + float y = sim_vec.at(j).getPosition().y ; + float z = sim_vec.at(j).getPosition().z ; + float dist = sqrt( (x-x0)*(x-x0) + (y-y0)*(y-y0) + (z-z0)*(z-z0) ); + if( dist < dis_min ){ dis_min = dist; index = j ; } + } + if(index==-1) sim_vec.push_back(SimHit); + else + { + float en_ori = sim_vec.at(index).getEnergy(); + float sum_en = en + en_ori ; + sim_vec.at(index).setEnergy(sum_en); + //std::cout<<"ori_x="<<sim_vec.at(index).getPosition().x<<",ori_y="<<sim_vec.at(index).getPosition().y<<",ori_z="<<sim_vec.at(index).getPosition().z<<std::endl; + float new_x = sim_vec.at(index).getPosition().x * en_ori/sum_en + SimHit.getPosition().x * en/sum_en; + float new_y = sim_vec.at(index).getPosition().y * en_ori/sum_en + SimHit.getPosition().y * en/sum_en; + float new_z = sim_vec.at(index).getPosition().z * en_ori/sum_en + SimHit.getPosition().z * en/sum_en; + edm4hep::Vector3f pos(new_x, new_y, new_z); + sim_vec.at(index).setPosition(pos); + //std::cout<<"new_x="<<sim_vec.at(index).getPosition().x<<",new_y="<<sim_vec.at(index).getPosition().y<<",new_z="<<sim_vec.at(index).getPosition().z<<std::endl; + } + } + float tot_en = 0; + for(std::vector< edm4hep::SimCalorimeterHit >::iterator iter = sim_vec.begin(); iter != sim_vec.end(); iter++) + { + auto caloHit = caloVec->create(); + caloHit.setCellID (iter->getCellID()); + caloHit.setEnergy (iter->getEnergy()*m_scale); + caloHit.setPosition(iter->getPosition()); + tot_en += caloHit.getEnergy(); + } + + std::cout<<"total sim e ="<< tot_sim_en <<std::endl; + std::cout<<"digi, output digi hit size="<< caloVec->size()<<",tot_en="<<tot_en <<std::endl; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode CaloDigiAlg::finalize() +{ + info() << "Processed " << _nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} diff --git a/Reconstruction/Digi_Calo/src/CaloDigiAlg.h b/Reconstruction/Digi_Calo/src/CaloDigiAlg.h new file mode 100644 index 00000000..5ecc0f68 --- /dev/null +++ b/Reconstruction/Digi_Calo/src/CaloDigiAlg.h @@ -0,0 +1,88 @@ +#ifndef Calo_DIGI_ALG_H +#define Calo_DIGI_ALG_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/SimCalorimeterHitConst.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" + +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include "DetInterface/IGeoSvc.h" + +/** ======= PlanarDigiProcessor / CaloDigiAlg ========== <br> + * Creates TrackerHits from SimTrackerHits, smearing them according to the input parameters. + * The SimTrackerHits should come from a planar detector like VXD, SIT, SET or FTD. + * + * WARNING: this processor depends on correctly set CellID0s and is NOT backwards compatible to + * SimTrackerHit output with wrong CellID0s!!! + * + * The positions of "digitized" TrackerHits are obtained by gaussian smearing positions + * of SimTrackerHits in u and v direction. + * <h4>Input collections and prerequisites</h4> + * Processor requires a collection of SimTrackerHits <br> + * <h4>Output</h4> + * Processor produces collection of smeared TrackerHits<br> + * @param SimTrackHitCollectionName The name of input collection of SimTrackerHits <br> + * (default name VXDCollection) <br> + * @param TrackerHitCollectionName The name of output collection of smeared TrackerHits <br> + * (default name VTXTrackerHits) <br> + * @param SimTrkHitRelCollection The name of the TrackerHit SimTrackerHit relation collection <br> + * (default name VTXTrackerHitRelations) <br> + * @param ResolutionU resolution in direction of u (in mm) <br> + * (default value 0.004) <br> + * @param ResolutionV Resolution in direction of v (in mm) <br> + * (default value 0.004) <br> + * @param IsStrip whether the hits are 1 dimensional strip measurements <br> + * (default value false)<br> + * <br> + * + */ + + + +class CaloDigiAlg : public GaudiAlgorithm +{ + +public: + + CaloDigiAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + /** Called for every event - the working horse. + */ + virtual StatusCode execute() ; + + /** Called after data processing for clean up. + */ + virtual StatusCode finalize() ; + + std::string GetCode(const edm4hep::SimCalorimeterHit *const pHit) const; + +protected: + + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>* m_layerLayout; + + SmartIF<IGeoSvc> m_geosvc; + typedef std::vector<float> FloatVec; + + int _nEvt ; + float m_length; + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + + Gaudi::Property<float> m_scale{ this, "Scale", 1 }; + + // Input collections + DataHandle<edm4hep::SimCalorimeterHitCollection> r_SimCaloCol{"SimCaloCol", Gaudi::DataHandle::Reader, this}; + // Output collections + DataHandle<edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml b/Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml new file mode 100644 index 00000000..9f2056ab --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml @@ -0,0 +1,20 @@ +clean: + end: 2018-09-04 10:38:21.535016 + finished: true + start: 2018-09-04 10:38:21.503623 +compile: + end: 2018-09-04 10:38:21.449716 + finished: true + start: 2018-09-04 10:38:07.382890 +download: + end: 2018-09-04 10:35:56.326883 + finished: true + start: 2018-09-04 10:35:55.941740 +extract: + end: 2018-09-04 10:35:56.510664 + finished: true + start: 2018-09-04 10:35:56.368258 +pre_compile: + end: 2018-09-04 10:37:33.127719 + finished: true + start: 2018-09-04 10:37:33.110630 diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced.cc b/Reconstruction/PFA/Pandora/CED/CED/ced.cc new file mode 100644 index 00000000..65444465 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced.cc @@ -0,0 +1,382 @@ +/* "C" event display. + * Communications related part. + * +*ik + * Alexey Zhelezov, DESY/ITEP, 2005 */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> + +#include <ced.h> + +//hauke +//#include <stropts.h> +#include <poll.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <netdb.h> +#include <sys/socket.h> /* for AF_INET */ +#include <iostream> + + +//http://www.rhyolite.com/pipermail/dcc/2004/001986.html +#ifndef POLLRDNORM //fg: should be defined in poll.h +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM 0x100 /* Writing now will not block. */ +# define POLLWRBAND 0x200 /* Priority data may be written. */ +#endif +//end hauke + +static int ced_fd=-1; // CED connection socket + +static unsigned short ced_port=7927; // port No of CED (assume localhost) +static char ced_host[30]; + +// Return 0 if can be connected, -1 otherwise. +/*static*/ int ced_connect(void){ + static time_t last_attempt=0; + time_t ct; + struct sockaddr_in addr; + + if(ced_fd>=0){ + return 0; // already connected; + } + time(&ct); + if(ct-last_attempt<5){ + return -1; // don't try reconnect all the time + } + addr.sin_family=AF_INET; + addr.sin_port=htons(ced_port); + addr.sin_addr.s_addr=inet_addr(ced_host); + memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); //not nessesary because sin_zero is not used! + + ced_fd=socket(PF_INET,SOCK_STREAM,0); + if(connect(ced_fd,(struct sockaddr *)&addr,sizeof(addr)) != 0){ + if(!last_attempt){ + perror("WARNING:CED: can't connect to CED"); + } + time(&last_attempt); + close(ced_fd); + ced_fd=-1; + return -1; + } + fprintf(stderr,"INFO:CED: connected to CED\n"); + return 0; +} + + +typedef struct { + unsigned size; // size of one item in bytes + unsigned char *b; // "body" - data are stored here + // (here is some trick :) + unsigned long count; // number of usefull items + unsigned long alloced; // number of allocated items + ced_draw_cb draw; // draw fucation, NOT used in CED client +} ced_element; + +typedef struct { + ced_element *e; + unsigned e_count; +} ced_event; + +//static ced_event eve = {0,0}; + +static ced_event eve = {0,0}; + +// NOT used in CED client +static ced_event ceve = {0,0}; // current event on screen + +// we reserve this size just before ced_element.b data +#define HDR_SIZE 8 + +unsigned ced_register_element(unsigned item_size,ced_draw_cb draw_func){ + ced_element *pe; + if(!(eve.e_count&0xf)){ + eve.e=(ced_element *) realloc(eve.e,(eve.e_count+0x10)*sizeof(ced_element)); + } + + pe=eve.e+eve.e_count; + memset(pe,0,sizeof(*pe)); + pe->size=item_size; + pe->draw=draw_func; + return eve.e_count++; +} + +static void ced_reset(void){ + unsigned i; + + for(i=0;i<eve.e_count;i++){ + eve.e[i].count=0; + // if( eve.e[i].alloced > 0){ + // eve.e[i].alloced=0; //hauke: 15.12.11 + // //free(eve.e[i].b-HDR_SIZE); + // } + } +} + +static void ced_buf_alloc(ced_element *pe,unsigned count){ + if(!pe->b){ + + //std::cout << "malloc requestet: " << count*pe->size+HDR_SIZE << "bytes" << std::endl; + pe->b=(unsigned char *) malloc(count*pe->size+HDR_SIZE); + //printf("malloc: ask for NEW %lu bytes pointer: %p\n ", count*pe->size+HDR_SIZE, pe->b); //hauke + if(pe->b==NULL){ //hauke + printf("ERROR: malloc failed!\n"); + exit(1); + } + }else{ + //free(pe->b-HDR_SIZE); + //pe->b=(unsigned char *) malloc(count*pe->size+HDR_SIZE); + + //std::cout << "realloc requestet: " << count*pe->size+HDR_SIZE << "bytes" << std::endl; + pe->b=(unsigned char *) realloc(pe->b-HDR_SIZE,count*pe->size+HDR_SIZE); + + //printf("malloc: ask for %lu bytes, pointer: %p\n", count*pe->size+HDR_SIZE,pe->b);//hauke + if(pe->b==NULL){ //hauke + printf("ERROR: malloc failed!\n"); + exit(1); + } + } + pe->b+=HDR_SIZE; + pe->alloced=count; +} + +void *ced_add(unsigned id){ + ced_element *pe; + if(id >= eve.e_count){ + fprintf(stderr,"BUG:CED: attempt to access not registered element\n"); + return 0; + } + pe=eve.e+id; + + if(pe->count==pe->alloced){ + ced_buf_alloc(pe,pe->alloced+256); + } + + return (pe->b+(pe->count++)*pe->size); +} + +static void ced_event_copy(ced_event *trg){ + unsigned i; + ced_element *pe; + //std::cout << "trg->e_count: " << trg->e_count << std::endl; + //std::cout << "eve.e_count: " << eve.e_count << std::endl; + + //eve.e_count = 0; + if(trg->e_count<eve.e_count){ + //free(trg->e); + trg->e=(ced_element*) realloc(trg->e,eve.e_count*sizeof(ced_element)); + + //trg->e=(ced_element*) malloc(eve.e_count*sizeof(ced_element)); + } + + + for(i=0;i<eve.e_count;i++){ + pe=trg->e+i; + if(i<trg->e_count){ + //if(pe->alloced > 0){ + // free(pe->b); + // pe->b=NULL; + // pe->alloced=0; + //} + + + //if(pe->alloced > 0){ + // std::cout << "try to free" << std::endl; + // free(pe->b-HDR_SIZE); + // pe->alloced = 0; + // std::cout << "finished" << std::endl; + //} + + if(pe->alloced<eve.e[i].alloced) { + ced_buf_alloc(pe,eve.e[i].alloced); + //std::cout << "test1 " << std::endl; + } + pe->count=eve.e[i].count; + + }else{ + memcpy(pe,eve.e+i,sizeof(ced_element)); + if(pe->b){ + pe->b=0; + // std::cout << "test2 " << std::endl; + ced_buf_alloc(pe,pe->alloced); + } + } + if(pe->count){ + memcpy(pe->b,eve.e[i].b,pe->count*pe->size); + } + } + trg->e_count=eve.e_count; +} + +void ced_do_draw_event(void){ + unsigned int i,j; + ced_element *pe; + unsigned char *pdata; + for(i=0;i<ceve.e_count;i++){ + //printf("ceve.e_count: %i\n", ceve.e_count); + //for(i=ceve.e_count-1; i >=0;i--){ //quick hack, change order so that the detector is drawn at last + //printf("i = %i\n", i); + + pe=ceve.e+i; + if(!pe->draw) + continue; + for(pdata=pe->b,j=0;j<pe->count;j++,pdata+=pe->size) + (*(pe->draw))(pdata); + } +} + +typedef enum { + DRAW_EVENT=10000 +} MSG_TYPE; + +int ced_process_input(void *data){ + struct _phdr{ + unsigned size; + unsigned type; + unsigned char b[4]; + } *hdr = (_phdr*) data; + unsigned count; + ced_element *pe; + + if(!data){ // new client is connected + ced_reset(); + return 0; + } + + if(hdr->type == DRAW_EVENT){ + ced_event_copy(&ceve); + ced_reset(); + return 1; + } + if(hdr->type>=eve.e_count){ + fprintf(stderr,"WARNING:CED: undefined element type (%u), ignored\n", + hdr->type); + return 0; + } + pe=eve.e+hdr->type; + if((hdr->size-HDR_SIZE)%pe->size){ + fprintf(stderr,"BUG:CED: size alignment is wrong for element %u\n", hdr->type); + return 0; + } + count=(hdr->size-HDR_SIZE)/pe->size; + if(!count) + return 0; + if(count>=pe->alloced) + ced_buf_alloc(pe,count+256); + memcpy(pe->b,hdr->b,count*pe->size); + pe->count=count; + return 0; +} + +void ced_send_event(void){ + struct _phdr{ + int size; + unsigned type; + } *hdr,draw_hdr; + unsigned i,problem=0; + int sent_sum; + char *buf; + int sent; + ced_element *pe; + + if(ced_connect()) + return; + for(i=0;i<eve.e_count && !problem;i++){ + //printf("i=%i\n",i); + pe=eve.e+i; + if(!pe->count) + continue; + + //unsigned hauke; + //printf("size of unsigned %i\n", sizeof(hauke)); + hdr=(struct _phdr *)(pe->b-HDR_SIZE); // !!! HERE is the trick :) + hdr->type=i; + //printf("pe->count %i, pe->size %i\n",pe->count, pe->size); + hdr->size=HDR_SIZE+pe->count*pe->size; + sent_sum=0; + //if(hdr->size > 10000000){printf("U P S! This data set is realy big! (%f kB)(%i counts)\n",(hdr->size)/1024.0,pe->count);} + buf=(char *)hdr; + //printf("hdr->size=%i\n",hdr->size); + while(sent_sum<hdr->size){ + //printf("sent_sum = %i, hdr->size=%i\n",sent_sum,hdr->size); + sent=write(ced_fd,buf+sent_sum,hdr->size-sent_sum); + + //printf("byte: %u\n", buf[sent_sum]); + if(sent<0){ + printf("send < 0\n"); + problem=1; + break; + } + sent_sum+=sent; + } + } + if(!problem){ + draw_hdr.size=HDR_SIZE; + draw_hdr.type=DRAW_EVENT; + if(write(ced_fd,&draw_hdr,HDR_SIZE)!=HDR_SIZE) + problem=1; + } + if(problem){ + perror("WARNING:CED: can't send event, till next time..."); + close(ced_fd); + ced_fd=-1; + } +} + + +//hauke +int ced_selected_id_noblock() { + int id=-1 ; + struct pollfd fds[1]; + fds[0].fd=ced_fd; + fds[0].events = POLLRDNORM | POLLIN; + if(poll(fds,1,0) > 0){ + if(recv(ced_fd, &id, sizeof(int) , 0 ) > 0){ + return id; + }else{ + return -1; + } + }else{ + return -1; + } +} + +int ced_selected_id() { + int id=-1 ; + if(recv(ced_fd, &id, sizeof(int) , 0 ) > 0){ + return id; + }else{ + return -1; + } +} +#include <signal.h> +// API +void ced_client_init(const char *hostname,unsigned short port){ + struct hostent *host = gethostbyname(hostname); + snprintf(ced_host, 30, "%u.%u.%u.%u\n",(unsigned char)host->h_addr[0] ,(unsigned char)host->h_addr[1] ,(unsigned char)host->h_addr[2] ,(unsigned char)host->h_addr[3]); + + + //printf("ip: %s\n", ced_host); + //ced_host=host->h_addr; + ced_port=port; + signal(SIGPIPE,SIG_IGN); +} + +void ced_new_event(void){ + ced_reset(); +} + +void ced_draw_event(void){ + ced_send_event(); + ced_reset(); +} diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced.h b/Reconstruction/PFA/Pandora/CED/CED/ced.h new file mode 100644 index 00000000..ccf355c2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced.h @@ -0,0 +1,146 @@ +/* "C" event display. + * Main part. + * + * Alexey Zhelezov, DESY/ITEP, 2005 */ + +/* + * This file is internal. It must not be + * included into enduser application. + */ + +#ifndef __CED_H +#define __CED_H + +#include "ced_cli.h" + +//#ifdef __cplusplus +// extern "C" { +//#endif + + +//char trusted_hosts[50]; +//extern static char testchar; + +typedef void (*ced_draw_cb)(void *data); + + +/* + * Register new element type. Order is important! + * Appropriate code must be defined in both + * client and server parts. + * + * item_size - size of one item in bytes. + * draw_func - function to call to draw one item, + * called from ced_do_draw_event() + * not used on client side. + */ +unsigned ced_register_element(unsigned item_size,ced_draw_cb draw_func); + +/* + * To be called from element functions + * on client side. + * Return allocated space for one item + * with size, specified by ced_register_element() + * + * Example: assume struct Dummy { int i; }; is item. + * + * DummyID=ced_register_element(sizeof(struct Dummy),0); + * ... + * struct Dummy *item=(struct Dummy *)ced_add_element(DummyID); + * item->i=0; + * This will add one Dummy item to the event + */ +void *ced_add(unsigned id); + +/* + * To be called in paint function + * + * It calls user defined functions for + * each item of all elements types. + */ +void ced_do_draw_event(void); + +/* + * Server side function. + * Must be used to process all incoming + * messages from client. + * + * It return positive value when + * new event must be drawn. + * + * Example: + * glut_tcp_server(7285,my_process_input) + * + * my_process_input(x){ + * if(ced_process_input(x)>0) + * <do redraw> + */ +int ced_process_input(void *data); + +//------------ +void addLayerDescriptionToMenu(int,char *);//glced.c +void selectFromMenu(int id);//glced.c +void toggleHelpWindow(void);//glced.c +void updateLayerEntryInPopupMenu(int); //glced.c +int buildMenuPopup(void);//glced.c + + +#define VERSION_CONFIG 3 +struct CEDsettings{ + bool trans; //grid or surface view + bool persp; //perspectivic view or flat projection + bool antia; //anti aliasing + bool light; //light source + bool picking_highlight; //marker at picking position + double detector_trans[NUMBER_DETECTOR_LAYER]; + double detector_cut_angle[NUMBER_DETECTOR_LAYER]; + double detector_cut_z[NUMBER_DETECTOR_LAYER]; + bool detector_picking; +// double cut_angle; //deprecated +// double trans_value; //deprecated +// double z_cutting; //deprecated + bool layer[CED_MAX_LAYER]; + bool phi_projection; + bool z_projection; + double view[3]; + double va; //vertical angle of view + double ha; //horionzional angle of view + bool fixed_view; + int win_h; //height of the window (pixel) + int win_w; //wight of the window (pixel) + double zoom; + double fisheye_alpha; + double world_size; + double fisheye_world_size; + double bgcolor[4]; + bool show_axes; + bool fps; + double screenshot_sections; + int font; //size of text (menu, shortcuts, text in ced window) + bool autoshot; // If true, generate screencapture in every new event + int autoshot_scale; // If true, generate screencapture in every new event +}; + +/* +//important: +// - sum of all layers must be smaler than max_layer! +// - number_popup_layer must be smaler than number_data_layer + +#define CED_MAX_LAYER 100 +#define NUMBER_POPUP_LAYER 20 +#define NUMBER_DATA_LAYER 25 +#define NUMBER_DETECTOR_LAYER 20 + + +#define CED_MAX_LAYER_CHAR 400 +*/ + +//------------- + +//#ifdef __cplusplus +// } +//#endif + + + +#endif /* __CED_H */ diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc new file mode 100644 index 00000000..8c063e12 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc @@ -0,0 +1,539 @@ +/* "C" event display. + * Client side elements definitions. + * + * Alexey Zhelezov, DESY/ITEP, 2005 */ +#include <string.h> + +#include <ced_cli.h> +#include <ced.h> +#include <stdio.h> +//#include <iostream> + +#include <math.h> + + +/* + * Hit element + */ + +static unsigned HIT_ID=0; + +void ced_hit(float x,float y,float z,unsigned type,unsigned size,unsigned color){ + ced_hit_ID(x,y,z, type & 0xFF,( type >> CED_LAYER_SHIFT ) & 0xFF, size,color, 0); +} + +//deprecated +void ced_hit_ID_old(float x,float y,float z,unsigned type, unsigned size,unsigned color, unsigned lcioID){ + ced_hit_ID(x,y,z,type & 0xFF,(type >> CED_LAYER_SHIFT) & 0xFF,size,color,lcioID); +} + +void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID){ + CED_Hit *h=(CED_Hit *)ced_add(HIT_ID); + if(!h) + return; + h->p.x=x; + h->p.y=y; + h->p.z=z; + h->type=type; + // if(layer > 255){ //downward compability + // h->layer=layer >> CED_LAYER_SHIFT; + // }else{ + h->layer=layer; + // } + h->size=size; + h->color=color; + h->lcioID=lcioID; +} + +/* + * Line element + */ + +static unsigned LINE_ID=0; + +void ced_line(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned type, unsigned width,unsigned color){ + ced_line_ID(x0,y0,z0,x1,y1,z1, type, width, color, 0); +} + +void ced_line_ID(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned layer, unsigned width,unsigned color, unsigned lcioID){ +// //test for picking +// //static int anz; +// float length=(x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) + (z1-z0)*(z1-z0); +// //printf("CEDLINE length: %f\n x0 %f y0 %f z0 %f, x1 %f, y1 %f z1 %f", length, x0, y0, z0, x1, y1, z1); +// +// if(length > 500.0){ +// //std::cout << "devide line (length=" << length << ")" << std::endl; +// ced_line_ID(x0,y0,z0, +// (x1-x0)/2.0+x0,(y1-y0)/2.0+y0,(z1-z0)/2.0+z0, +// layer, width, color, lcioID); +// ced_line_ID( +// (x1-x0)/2.0+x0,(y1-y0)/2.0+y0,(z1-z0)/2.0+z0, +// +// x1,y1,z1, +// layer, width, color, lcioID); +// //todo +// //printf("seperate line %i\n", anz++); +// return; +// +// } + +/* +//test + if( random()%100000 > 99990){ + double size[]={10,100,50}; + double position[]={x0,y0,z0}; + double rotate[] = {20,50,70}; + int color=1; + int lcio_id=5; + int layer=5; + //ced_geobox(size, position, color ); + ced_geobox_ID(size, position, layer, 0xff00ff, 5); + ced_geobox(size, position, color); + + } + +//end test +*/ + + CED_Line *l=(CED_Line *)ced_add(LINE_ID); + if(!l) + return; + l->p0.x=x0; + l->p0.y=y0; + l->p0.z=z0; + l->p1.x=x1; + l->p1.y=y1; + l->p1.z=z1; + if(layer > 255){ //downward compability + l->type=layer >> CED_LAYER_SHIFT; + }else{ + l->type=layer; + } + + //printf("layer pre: %i after: %i\n" , layer, l->type); + +// l->type=type; + l->width=width; + l->color=color; + l->lcioID=lcioID; +} +/* + * GeoCylinder + */ +static unsigned GEOC_ID=0; + +void ced_geocylinder(float d,unsigned sides,float rotate,float z,float shift, + unsigned color){ + CED_GeoCylinder *c=(CED_GeoCylinder *)ced_add(GEOC_ID); + if(!c) + return; + c->d=d; + c->sides=sides; + c->rotate=rotate; + c->z=z; + c->shift=shift; + c->color=color; +} + +/* + * Rotated Geocylinder + * Extension of the cylinder subject to a 3-DOF rotation + * @author: SD + * @date: 26.08.08 + */ +static unsigned GEOCR_ID=0; + +void ced_geocylinder_r(float d, double z, double * center, double * rotate, unsigned sides, + unsigned int color, int layer){ + int iDim; + CED_GeoCylinderR *c=(CED_GeoCylinderR *)ced_add(GEOCR_ID); + if(!c) return; + for (iDim = 0; iDim < 3; iDim ++ ) { + c->center[iDim] = center[iDim]; + c->rotate[iDim] = rotate[iDim]; + } + c->d=d; + c->sides=sides; + c->color=color; + c->z=z; + if(layer > 255){ //downward compability + c->layer=layer >> CED_LAYER_SHIFT; + }else{ + c->layer=layer; + } + + //c->layer=layer; +} + +void ced_geocylinders(unsigned n,CED_GeoCylinder *all){ + CED_GeoCylinder *c; + unsigned i; + for(i=0;i<n;i++){ + c=(CED_GeoCylinder *)ced_add(GEOC_ID); + if(!c) + return; + memcpy(c,all+i,sizeof(CED_GeoCylinder)); + } +} + +static unsigned GEOT_ID=0; + +void ced_geotubes(unsigned n,CED_GeoTube *all){ + CED_GeoTube *c; + unsigned i; + for(i=0;i<n;i++){ + c=(CED_GeoTube *)ced_add(GEOT_ID); + if(!c) + return; + memcpy(c,all+i,sizeof(CED_GeoTube)); + } +} + + +static unsigned GEOB_ID=0; + +void ced_geobox(double * sizes, double * center, unsigned int color ) { + int iDim; + CED_GeoBox * box = (CED_GeoBox*) ced_add(GEOB_ID); + if ( ! box ) return; + for ( iDim = 0; iDim < 3; iDim ++ ) { + box->sizes[iDim] = sizes[iDim]; + box->center[iDim] = center[iDim]; + } + box->color = color; + +} + +void rotate3d(double *vektor, double *rotate){ + //double cords2[3]; + double r_rad[3]={rotate[0]/360*2*3.14159265358979323846, rotate[1]/360*2*3.14159265358979323846, rotate[2]/360*2*3.14159265358979323846}; + double cords1[3] = {vektor[0], vektor[1], vektor[2]}; + + vektor[0] = ( cos(r_rad[1])*cos(r_rad[2]) )*cords1[0] + + (-cos(r_rad[0])*sin(r_rad[2]) + sin(r_rad[0])*sin(r_rad[1])*cos(r_rad[2]) )*cords1[1] + + ( sin(r_rad[0])*sin(r_rad[2]) + cos(r_rad[0])*sin(r_rad[1])*cos(r_rad[2]) )*cords1[2]; + vektor[1] = ( cos(r_rad[1])*sin(r_rad[2]) ) * cords1[0] + + ( cos(r_rad[0])*cos(r_rad[2]) + sin(r_rad[0])*sin(r_rad[1])*sin(r_rad[2])) * cords1[1] + + ( -sin(r_rad[0])*cos(r_rad[2]) + cos(r_rad[0])*sin(r_rad[1])*sin(r_rad[2]) ) * cords1[2]; + vektor[2] = (-sin(r_rad[1])) * cords1[0] + + ( sin(r_rad[0])*cos(r_rad[1])) * cords1[1] + + ( cos(r_rad[0])*cos(r_rad[1])) * cords1[2]; + +} + +void ced_geobox_r_ID(double *size, double *position, double *rotate, unsigned int layer, unsigned int color, unsigned int lcio_id) { + + int i; + double vektor1[3], vektor2[3]; + //unsigned int type = layer; //<< CED_LAYER_SHIFT; + //unsigned int type = layer; + + double cubematrix[12][6] ={ {-1,-1,-1, +1,-1,-1}, + {-1,-1,-1, -1,+1,-1}, + {-1,-1,-1, -1,-1,+1}, + {+1,-1,-1, +1,+1,-1}, + {+1,-1,-1, +1,-1,+1}, + {+1,+1,-1, +1,+1,+1}, + {+1,+1,-1, -1,+1,-1}, + {+1,+1,+1, -1,+1,+1}, + {+1,+1,+1, +1,-1,+1}, + {-1,+1,+1, -1,-1,+1}, + {-1,+1,+1, -1,+1,-1}, + {-1,-1,+1, +1,-1,+1} }; + + for(i=0;i<12;i++){ + vektor1[0] = cubematrix[i][0]*size[0]/2; + vektor1[1] = cubematrix[i][1]*size[1]/2; + vektor1[2] = cubematrix[i][2]*size[2]/2; + + vektor2[0] = cubematrix[i][3]*size[0]/2; + vektor2[1] = cubematrix[i][4]*size[1]/2; + vektor2[2] = cubematrix[i][5]*size[2]/2; + + rotate3d(vektor1,rotate); + rotate3d(vektor2,rotate); + + + ced_line_ID(position[0]+vektor1[0], position[1]+vektor1[1], position[2]+vektor1[2], + position[0]+vektor2[0], position[1]+vektor2[1], position[2]+vektor2[2], + layer, 1,color, lcio_id); + } +} + +void ced_geobox_ID(double *size, double *position, unsigned int layer, unsigned int color, unsigned int lcio_id) { + double rotate[3]={0.0, 0.0, 0.0}; + ced_geobox_r_ID(size, position, rotate, layer, color, lcio_id); +} + + +void ced_geoboxes(unsigned int nBox, CED_GeoBox * allBoxes ) { + + CED_GeoBox * box; + unsigned int iBox; + for ( iBox = 0; iBox < nBox ; iBox++ ) { + box = (CED_GeoBox *) ced_add(GEOB_ID); + if ( ! box ) return; + memcpy( box, allBoxes + iBox, sizeof(CED_GeoBox) ); + } +} + +static unsigned GEOBR_ID=0; + +void ced_geobox_r(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer) { + int iDim; + CED_GeoBoxR * box = (CED_GeoBoxR*) ced_add(GEOBR_ID); + if ( ! box ) return; + for ( iDim = 0; iDim < 3; iDim ++ ) { + box->sizes[iDim] = sizes[iDim]; + box->center[iDim] = center[iDim]; + box->rotate[iDim] = rotate[iDim]; + } + box->color = color; + + if(layer > 255){ //downward compability + box->layer=layer >> CED_LAYER_SHIFT; + }else{ + box->layer=layer; + } + +// box->layer = layer; +} + +static unsigned GEOBRS_ID=0; + +void ced_geobox_r_solid(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer) { + int iDim; + CED_GeoBoxR * box = (CED_GeoBoxR*) ced_add(GEOBRS_ID); + if ( ! box ) return; + for ( iDim = 0; iDim < 3; iDim ++ ) { + box->sizes[iDim] = sizes[iDim]; + box->center[iDim] = center[iDim]; + box->rotate[iDim] = rotate[iDim]; + } + box->color = color; + + if(layer > 255){ //downward compability + box->layer=layer >> CED_LAYER_SHIFT; + }else{ + box->layer=layer; + } + +// box->layer = layer; +} + +static unsigned LEGEND_ID=0; + +void ced_legend(float ene_min, float ene_max, unsigned int color_steps, unsigned int ** rgb_matrix, unsigned int ticks, char scale) { + CED_Legend * legend = (CED_Legend*) ced_add(LEGEND_ID); + if ( ! legend ) return; + + legend->ene_min = ene_min; + legend->ene_max = ene_max; + legend->color_steps = color_steps; + legend->ticks = ticks; + legend->scale = scale; + + const unsigned int numberOfColours = 3; + unsigned int i,j; + for (i = 0; i < numberOfColours; i ++ ) { + for (j = 0; j < color_steps; j ++ ) { + legend->rgb_matrix[j][i] = rgb_matrix[j][i]; + } + } +} +//hauke +static unsigned TEXT_ID=0; + +void ced_describe_layer(const char *message, int id) { + //printf("ced_describe layer id=%i text: %s\n", id, message); + + if(id >= CED_MAX_LAYER){ + printf("WARNING: ced_describe_layer: Index out of range!\n"); + return; + } + + CED_TEXT *text = (CED_TEXT*) ced_add(TEXT_ID); + if(!text){ + printf("WARNING: ced_describe_layer: cant register CED_TEXT"); + return; + } + + strncpy(text->text,message,CED_MAX_LAYER_CHAR-1); + text->text[CED_MAX_LAYER_CHAR-1] = 0; + text->id=id; + + //text->x=xCordinate; + //text->y=yCordinate; +} + +/* +static unsigned LAYER_TEXT_ID=0; + +void ced_layer_text(char *message, int id) { + LAYER_TEXT *obj = (LAYER_TEXT*) ced_add(LAYER_TEXT_ID); + if (!obj){ + printf("ced_layer_text FAILED\n"); + return; + } + strncpy(obj->str,message,CED_MAX_LAYER_CHAR-1); + obj->id=id; + //printf("ced_layer_text\n"); +} +*/ + +static unsigned PICKING_TEXT_ID=0; + +void ced_picking_text(const char *message, int id) { + CED_PICKING_TEXT *text = (CED_PICKING_TEXT*) ced_add(PICKING_TEXT_ID); + if(!text){ + printf("WARNING: ced_picking_text: cant register CED_PICKING_TEXT"); + return; + } + + strncpy(text->text,message,999); + text->id=id; + //text->text[CED_MAX_LAYER_CHAR-1] = 0; + //text->id=id; + //text->x=xCordinate; + //text->y=yCordinate; +} +//end hauke + +static unsigned CONER_ID=0; + +void ced_cone_r(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor) { + ced_cone_r_ID(base,height,center,rotate,layer, RGBAcolor, 0); +} + +void ced_cone_r_ID(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor, int lcioid) { + CED_ConeR * cone = (CED_ConeR*) ced_add(CONER_ID); + if ( ! cone ) return; + + cone->base = base; + cone->height = height; + + if(layer > 255){ //downward compability + cone->layer=layer >> CED_LAYER_SHIFT; + }else{ + cone->layer=layer; + } + +// cone->layer = layer; + cone->lcioid = lcioid; + + const unsigned int dim = 3; + const unsigned int channel = 4; + unsigned int i, j; + + // ced_line_ID(0,0,0, center[0], center[1], center[2], type, width, RGBAcolor, lcioid); + + //ced_line_ID(center[0], center[1], center[2], rotate[0], rotate[1], rotate[2], layer, 1, RGBAcolor, lcioid); + //printf("CONE: from %f %f %f to %f %f %f\n", center[0], center[1], center[2], rotate[0], rotate[1], rotate[2]); + + for (i = 0; i < dim; i ++ ) { + cone->center[i] = center[i]; + cone->rotate[i] = rotate[i]; + } + for (j = 0; j < channel; j ++ ) { + cone->RGBAcolor[j] = RGBAcolor[j]; + } +} + +static unsigned ELLIPSOID_ID=0; + +void ced_ellipsoid_r(double *size, double *center, double *rotate, unsigned int layer, int color) { + ced_ellipsoid_r_ID(size, center, rotate, layer, color, 0); +} + +void ced_ellipsoid_r_ID(double *size, double *center, double *rotate, unsigned int layer, int color, int lcioID) { + + CED_EllipsoidR * eli = (CED_EllipsoidR*) ced_add(ELLIPSOID_ID); + if ( ! eli ) return; + + const unsigned int dim = 3; + unsigned int i; + for (i = 0; i < dim; i ++ ) { + eli->center[i] = center[i]; + eli->rotate[i] = rotate[i]; + eli->size[i] = size[i]; + } + eli->color = color; + + if(layer > 255){ //downward compability + eli->layer=layer >> CED_LAYER_SHIFT; + }else{ + eli->layer=layer; + } + +// eli->layer = layer; + eli->lcioid = lcioID; +} + +static unsigned CLUELLIPSE_ID=0; + +void ced_cluellipse_r(float radius, float height, float *center, double *rotate, unsigned int layer, int color) { + ced_cluellipse_r_ID(radius, height, center, rotate, layer, color, 0); +} + +void ced_cluellipse_r_ID(float radius, float height, float *center, double *rotate, unsigned int layer, int color, int lcioid) { //hauke + + CED_CluEllipseR * eli = (CED_CluEllipseR*) ced_add(CLUELLIPSE_ID); + if ( ! eli ) return; + + const unsigned int dim = 3; + unsigned int i; + for (i = 0; i < dim; i ++ ) { + eli->center[i] = center[i]; + eli->rotate[i] = rotate[i]; + } + eli->radius = radius; + eli->height = height; + + if(layer > 255){ //downward compability + eli->layer=layer >> CED_LAYER_SHIFT; + }else{ + eli->layer=layer; + } + +// eli->layer = layer; + eli->color = color; + eli->lcioid=lcioid; +} + + +void ced_register_elements(void){ + + //1: + GEOC_ID =ced_register_element(sizeof(CED_GeoCylinder),0); + //2: + GEOCR_ID =ced_register_element(sizeof(CED_GeoCylinderR), 0); + //3: + LINE_ID =ced_register_element(sizeof(CED_Line),0); + //4: + HIT_ID =ced_register_element(sizeof(CED_Hit),0); + //5: + GEOB_ID =ced_register_element(sizeof(CED_GeoBox), 0); + //6: + GEOBR_ID =ced_register_element(sizeof(CED_GeoBoxR), 0); + //7: + GEOBRS_ID =ced_register_element(sizeof(CED_GeoBoxR), 0); + //8: + CONER_ID =ced_register_element(sizeof(CED_ConeR), 0); + //9: + ELLIPSOID_ID =ced_register_element(sizeof(CED_EllipsoidR), 0); + //10: + CLUELLIPSE_ID =ced_register_element(sizeof(CED_CluEllipseR), 0); + //11: + TEXT_ID =ced_register_element(sizeof(CED_TEXT),0); //hauke: the order of this items is important + //12: + LEGEND_ID =ced_register_element(sizeof(CED_Legend), 0); + //13: + GEOT_ID =ced_register_element(sizeof(CED_GeoTube),0); + //14: + PICKING_TEXT_ID =ced_register_element(sizeof(CED_PICKING_TEXT),0); +} + diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced_cli.h b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.h new file mode 100644 index 00000000..a92164b0 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.h @@ -0,0 +1,432 @@ +/* "C" event display. + * Enduser accessable API. + * + * Alexey Zhelezov, DESY/ITEP, 2005 + */ + +#ifndef __CED_CLI_H +#define __CED_CLI_H + +#include <ced_config.h> + + +//important: +// - sum of all layers must be smaler than max_layer! +// - number_popup_layer must be smaler than number_data_layer + +//#define CED_MAX_LAYER 100 +//#define NUMBER_POPUP_LAYER 20 +//#define NUMBER_DATA_LAYER 25 +//#define NUMBER_DETECTOR_LAYER 20 +// +// +//#define CED_MAX_LAYER_CHAR 400 + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This is the first function to call (before any other). + * + * host - host with CED (must be "localhost") + * port - server port number (let say 7285 :) + * + * NOTE: ced_register_elements() must be called + * separately. + */ +void ced_client_init(const char *host,unsigned short port); + +/* + * Cancel current event output. So, all elements + * queued will be discarded. + * + * Good to call at the begining of every event processing. + */ +void ced_new_event(void); + + +/* + * This function really attempt to display event in CED. + * When CED is not available, this function discard + * current event information. + * + * NOTE: between ced_new_event() and ced_draw_event() + * must be some element creation calls. + */ +void ced_draw_event(void); + +/* + * This function really attempt to display event in CED. + * Unlike ced_draw_event() does not reset the event. + * + * NOTE: between ced_new_event() and ced_draw_event() + * must be some element creation calls. + */ +void ced_send_event(void); + +int ced_selected_id(void); + +//hauke +int ced_selected_id_noblock(void); + + +/********************************************* + * + * The following is elements API. + * + *********************************************/ + +void ced_register_elements(void); + +typedef enum { + CED_TYPE_SHIFT=0x0, + CED_LAYER_SHIFT=0x8 +} CED_TYPE_BITS; + +/* +typedef enum { + CED_TYPE_SHIFT=0x0, + CED_LAYER_SHIFT=0x0 +} CED_TYPE_BITS; +*/ + + +typedef struct { + float x; + float y; + float z; +} CED_Point; + +//class CED_Point{ +// public: +// CED_Point(float _x, float _y, float _z){ +// x=_x; +// y=_y; +// z=_z; +// } +// +// CED_Point(void){ +// } +// float x; +// float y; +// float z; +//}; + + +/* + * Hit element + */ + +typedef enum { + CED_HIT_POINT=0, + CED_HIT_CROSS, + CED_HIT_STAR, + CED_HIT_BOX, + CED_HIT_VXD +} CED_HIT_TYPE; + +typedef struct { + CED_Point p; + unsigned type; // point, star, etc + unsigned layer; //layer + unsigned color; // in ARGB form (so, 0xff0000 is RED) + unsigned size; // size of point/size of cross + unsigned lcioID; // unique id of LICO object +} CED_Hit; + +void ced_hit(float x,float y,float z,unsigned type,unsigned size,unsigned color); + +//to give a bit of downward compatibility +void ced_hit_ID_old(float x,float y,float z,unsigned type, unsigned size,unsigned color, unsigned lcioID); + + +void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID); + +/* + * Line element + */ + +typedef struct { + CED_Point p0; + CED_Point p1; + unsigned type; // not yet defined... + unsigned width; // not yet defined... + unsigned color; // in ARGB form (so, 0xff0000 is RED) + unsigned lcioID; // unique id of LICO object + +} CED_Line; + +void ced_line(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned type,unsigned width,unsigned color); +void ced_line_ID(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned type,unsigned width,unsigned color, unsigned lcioID); + +/* + * GeoCylinder + */ +typedef struct { + float d; // radius + unsigned sides; // poligon order + float rotate; // angle degree + float z; // 1/2 length + float shift; // in z + unsigned color; +} CED_GeoCylinder; + +/* + * GeoTube + */ +typedef struct { + float r_o; // outer radius + float r_i; // inner radius + unsigned edges_o; // edges outer + unsigned edges_i; // edges inner + float rotate_o; // angle degree, rotate outer cylinder + float rotate_i; //rotate inner cylinder + float z; // 1/2 length + float shift; // shift in z + unsigned color; // color + unsigned type; //describes the layer where this element lies + bool classic_inner; //draw the outer detector lines in classic view? + bool classic_outer; //draw the inner detector lines in classic view? +} CED_GeoTube; + + +/** Same as CED_GeoTube but here as C++ struct with contstructor. This is allows + * to dynamically allocate the detector structure (in an std::vector using the constructor) + * without knowing the exact number of detector elements a priori (such as the #layers in the FTD). + * This wasn't poassible with the static allocation using the C type struct. + * ( Used in MArlinCED::drawGearDetector ). + */ +struct CEDGeoTube{ + CEDGeoTube(double r_out, + double r_in, + int edges_out, + int edges_in, + double rotate_out, + double rotate_in, + double zlength, + double zshift, + int col, + int layer, + bool classic_i, + bool classic_o ) : + r_o(r_out), + r_i(r_in), + edges_o(edges_out), + edges_i (edges_in), + rotate_o (rotate_out), + rotate_i (rotate_in), + z( zlength), + shift (zshift), + color (col), + type(layer), + classic_inner(classic_i), + classic_outer(classic_o) {} + float r_o; // outer radius + float r_i; // inner radius + unsigned edges_o; // edges outer + unsigned edges_i; // edges inner + float rotate_o; // angle degree, rotate outer cylinder + float rotate_i; //rotate inner cylinder + float z; // 1/2 length + float shift; // shift in z + unsigned color; // color + unsigned type; //describes the layer where this element lies + bool classic_inner; //draw the outer detector lines in classic view? + bool classic_outer; //draw the inner detector lines in classic view? +} ; + +void ced_geotubes(unsigned n,CED_GeoTube *all); + + +void ced_geocylinder(float d,unsigned sides,float rotate,float z,float shift, + unsigned color); + +void ced_geocylinders(unsigned n,CED_GeoCylinder *all); + +/* + * GeoCylinder rotatable + * @author: S.Daraszewicz (UoE) + * @date: 01.09.09 + */ +typedef struct { + float d; // radius + unsigned sides; // poligon order + float center[3]; // cylinder centre z,y,z + float rotate[3]; // rotation angles wrt x,y,z axis + float z; // length + unsigned color; // colour + unsigned layer; // layer the Cylinder to be displayed onto +} CED_GeoCylinderR; + + +void ced_geocylinder_r(float d, double z, double * center, double * rotate, unsigned sides, + unsigned int color, int layer); + + + /** GeoBox structure + */ + typedef struct { + /** The three box sizes in mm */ + double sizes[3]; + /** position of the center of the box*/ + double center[3]; + /** box color */ + unsigned int color; + } CED_GeoBox; + + /** Send/Draw a box at position center (x,y,z in mm) with lengths along the + * axes specified in sizes. + * + * @author A.Bulgheroni, INFN + */ + void ced_geobox(double * sizes, double * center, unsigned int color ); + void ced_geobox_ID(double *size, double *position, unsigned int layer, unsigned int color, unsigned int lcio_id); + void ced_geobox_r_ID(double *size, double *position, double *rotate, unsigned int layer, unsigned int color, unsigned int lcio_id); + void rotate3d(double *vektor, double *rotate); + + + + /* + * @author A.Bulgheroni, INFN + */ + void ced_geoboxes( unsigned int nBox, CED_GeoBox * allBoxes); + + typedef struct { + /** The three box sizes in mm */ + double sizes[3]; + /** position of the center of the box*/ + double center[3]; + /** box color */ + unsigned int color; + /** rotation angle in degrees */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + } CED_GeoBoxR; + +void ced_geobox_r(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer); +void ced_geobox_r_solid(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer); + +//hauke + typedef struct{ + char text[1000]; + int id; + } CED_PICKING_TEXT; + +void ced_picking_text(const char *, int number); + +//-------- + + typedef struct{ + char text[400]; + int id; + } CED_TEXT; + + +void ced_describe_layer(const char *, int); //, int, int); + + + typedef struct{ + char str[400]; + unsigned int id; + } LAYER_TEXT; + +void ced_layer_text(char *, int); +//end hauke + + +/* + * Energy spectrum colour map legend. + * @author: S.Daraszewicz (UoE) + * @date: 01.09.09 + */ + typedef struct { + /** min energy on the legend */ + float ene_max; + /** max energy on the legend */ + float ene_min; + /** number of ticks on the legend */ + unsigned int ticks; + /** spectrum colour steps */ + unsigned int color_steps; + /** spectrum colour matrix */ + unsigned int rgb_matrix[512][3]; //FIX ME: 512 size not changed with color_steps + /** LOG or LIN */ + char scale; + } CED_Legend; + +void ced_legend(float ene_min, float ene_max, unsigned int color_steps, unsigned int ** rgb_matrix, unsigned int ticks, char scale); + + typedef struct { + /** position of the centre of the base */ + double center[3]; + /** rotation matrix */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + /** base radius */ + float base; + /** height */ + float height; + /** RGBA color */ + float RGBAcolor[4]; + unsigned lcioid; //hauke + } CED_ConeR; + + +void ced_cone_r(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor); +void ced_cone_r_ID(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor, int lcioid); //hauke + + + typedef struct { + /** position of the centre of the base */ + double center[3]; + /** rotation matrix */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + /** xyz size */ + double size[3]; + /** RGBA color */ + int color; + unsigned lcioid; //hauke + } CED_EllipsoidR; + + +void ced_ellipsoid_r(double *size, double *center, double *rotate, unsigned int layer, int color); +void ced_ellipsoid_r_ID(double *size, double *center, double *rotate, unsigned int layer, int color, int lcioid); //hauke + + + typedef struct { + /** position of the centre of the base */ + double center[3]; + /** rotation matrix */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + /** base radius */ + float radius; + /** half height */ + float height; + /** RGBA color */ + int color; + unsigned lcioid; //hauke + } CED_CluEllipseR; + + +void ced_cluellipse_r(float radius, float height, float *center, double *rotate, unsigned int layer, int color); +void ced_cluellipse_r_ID(float radius, float height, float *center, double *rotate, unsigned int layer, int color, int lcioid); //hauke + + +#ifdef __cplusplus + } +#endif + + +#endif /* __CED_CLI_H */ diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced_config.h b/Reconstruction/PFA/Pandora/CED/CED/ced_config.h new file mode 100644 index 00000000..66214ead --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced_config.h @@ -0,0 +1,204 @@ +/********************************************************** +* ced_config.h, CED config file * +* Hauke Hoelbe, DESY, 2011 * +* Headerfile to adapt CED before the build. * +**********************************************************/ + +#ifndef __CED_CONFIG +#define __CED_CONFIG + +#include "ced_cli.h" + + +/********************************************************** +* Handling * +**********************************************************/ +//enable zoom function by right click and pull +#define ZOOM_RIGHT_CLICK 0 + +//time when 2 clicks should be a double click, in 1/1000000 secounds +#define DOUBLE_CLICK_TIME 300000 + +//data layer keys +#define DATALAYER_SHORTKEY_00 '0' +#define DATALAYER_SHORTKEY_01 '1' +#define DATALAYER_SHORTKEY_02 '2' +#define DATALAYER_SHORTKEY_03 '3' +#define DATALAYER_SHORTKEY_04 '4' +#define DATALAYER_SHORTKEY_05 '5' +#define DATALAYER_SHORTKEY_06 '6' +#define DATALAYER_SHORTKEY_07 '7' +#define DATALAYER_SHORTKEY_08 '8' +#define DATALAYER_SHORTKEY_09 '9' +#define DATALAYER_SHORTKEY_10 ')' +#define DATALAYER_SHORTKEY_11 '!' +#define DATALAYER_SHORTKEY_12 '@' +#define DATALAYER_SHORTKEY_13 '#' +#define DATALAYER_SHORTKEY_14 '$' +#define DATALAYER_SHORTKEY_15 '%' +#define DATALAYER_SHORTKEY_16 '^' +#define DATALAYER_SHORTKEY_17 '&' +#define DATALAYER_SHORTKEY_18 '*' +#define DATALAYER_SHORTKEY_19 '(' +#define DATALAYER_SHORTKEY_20 't' +#define DATALAYER_SHORTKEY_21 'y' +#define DATALAYER_SHORTKEY_22 'u' +#define DATALAYER_SHORTKEY_23 'i' +#define DATALAYER_SHORTKEY_24 'o' + +//detector layer keys +#define DETECTORLAYER_SHORTKEY_00 'j' +#define DETECTORLAYER_SHORTKEY_01 'k' +#define DETECTORLAYER_SHORTKEY_02 'l' +#define DETECTORLAYER_SHORTKEY_03 ';' +#define DETECTORLAYER_SHORTKEY_04 '\'' +#define DETECTORLAYER_SHORTKEY_05 'p' +#define DETECTORLAYER_SHORTKEY_06 '[' +#define DETECTORLAYER_SHORTKEY_07 ']' +#define DETECTORLAYER_SHORTKEY_08 '\\' +#define DETECTORLAYER_SHORTKEY_09 'T' +#define DETECTORLAYER_SHORTKEY_10 'Y' +#define DETECTORLAYER_SHORTKEY_11 'U' +#define DETECTORLAYER_SHORTKEY_12 'I' +#define DETECTORLAYER_SHORTKEY_13 'O' +#define DETECTORLAYER_SHORTKEY_14 'P' +#define DETECTORLAYER_SHORTKEY_15 '{' +#define DETECTORLAYER_SHORTKEY_16 '}' +#define DETECTORLAYER_SHORTKEY_17 '|' +#define DETECTORLAYER_SHORTKEY_18 'a' +#define DETECTORLAYER_SHORTKEY_19 'e' + + +/********************************************************** +* Colors and appearance * +**********************************************************/ +//size of the boarder line in filled (new view) of detector components. +#define CED_GEOTUBE_LINE_WIDTH 0.3 + +//maximal transparency of boarder lines +//#define CED_GEOTUBE_LINE_MAX_TRANS 0.2 +#define CED_GEOTUBE_LINE_MAX_TRANS 1.0 + + +//names and values of color apairs in popup menu +#define CED_BGCOLOR_OPTION1_NAME "Gainsboro" +#define CED_BGCOLOR_OPTION1_COLORCODE 0.862745,0.862745,0.862745,0 + +#define CED_BGCOLOR_OPTION2_NAME "Lightgrey" +#define CED_BGCOLOR_OPTION2_COLORCODE 0.827451,0.827451,0.827451,0 + +#define CED_BGCOLOR_OPTION3_NAME "Darkgray" +#define CED_BGCOLOR_OPTION3_COLORCODE 0.662745,0.662745,0.662745,0 + +#define CED_BGCOLOR_OPTION4_NAME "Gray" +#define CED_BGCOLOR_OPTION4_COLORCODE 0.501961,0.501961,0.501961,0 + +#define CED_BGCOLOR_OPTION5_NAME "Silver" +#define CED_BGCOLOR_OPTION5_COLORCODE 0.7529,0.7529,0.7529,0 + +#define CED_BGCOLOR_OPTION6_NAME "Dimgray" +#define CED_BGCOLOR_OPTION6_COLORCODE 0.4118,0.4118,0.4118,0 + +#define CED_BGCOLOR_OPTION7_NAME "Lightsteelblue" +#define CED_BGCOLOR_OPTION7_COLORCODE 0.6902,0.7686 ,0.8706,0 + +#define CED_BGCOLOR_OPTION8_NAME "Steelblue" +#define CED_BGCOLOR_OPTION8_COLORCODE 0.2745,0.5098,0.70588,0 + +#define CED_BGCOLOR_OPTION9_NAME "Seagreen" +#define CED_BGCOLOR_OPTION9_COLORCODE 0.18039,0.54509,0.34117,0 + +#define CED_BGCOLOR_OPTION10_NAME "Orange" +#define CED_BGCOLOR_OPTION10_COLORCODE 1,0.647,0,0 + +#define CED_BGCOLOR_OPTION11_NAME "Yellow" +#define CED_BGCOLOR_OPTION11_COLORCODE 1,1,0,0 + +#define CED_BGCOLOR_OPTION12_NAME "Violett" +#define CED_BGCOLOR_OPTION12_COLORCODE 0.9333,0.5098,0.9333,0 + +#define CED_BGCOLOR_OPTION13_NAME "Black" +#define CED_BGCOLOR_OPTION13_COLORCODE 0,0,0,0 + +#define CED_BGCOLOR_OPTION14_NAME "Blue" +#define CED_BGCOLOR_OPTION14_COLORCODE 0,0.2,0.4,0 + +#define CED_BGCOLOR_OPTION15_NAME "White" +#define CED_BGCOLOR_OPTION15_COLORCODE 1,1,1,0 + + + + +//Color of xyz axes +#define AXES_COLOR 0.2,0.2,0.8 + +//Width of xyz axes +#define AXES_LINE_SIZE 0.5 + + +//Help frame: Frame fill color, and transp +#define HELP_FRAME_FILL_COLOR 0.5,1,1,0.8 + +//Help frame: Frame boarder color and transp +#define HELP_FRAME_BOARDER_COLOR 0.1,0.8,1.0,0.8 + +//Help frame: Frame boarder line width +#define HELP_FRAME_BOARDER_LINE_SIZE 3. + +//Help frame: Text color, and transp +#define HELP_FRAME_TEXT_COLOR 0.0,0.0,0.0 + + + + +/********************************************************** +* Layers * +**********************************************************/ +//number of total number of layers +#define CED_MAX_LAYER 100 + +//number of layers shown in popup menu +#define NUMBER_POPUP_LAYER 20 + +//number of layers reserved for data +#define NUMBER_DATA_LAYER 25 + +//number of layers reserved for detector components +#define NUMBER_DETECTOR_LAYER 20 + +//layer description text: maximal number of chars for one entry +#define CED_MAX_LAYER_CHAR 400 + +/********************************************************** +* Graphics * +**********************************************************/ + +//Camera field of view, in degree +#define CAMERA_FIELD_OF_VIEW 45 + +//Camera min distance (hint: min and max should be close together) +#define CAMERA_MIN_DISTANCE 100 + +//Camera max distance (hint: min and max should be close together) +#define CAMERA_MAX_DISTANCE 50000.0*mm.sf+50000/mm.sf + +//Where the camera stands +#define CAMERA_POSITION 0,0,2000 + + + +//Fisheye alpha factor +#define FISHEYE_ALPHA 1e-3 +#define FISHEYE_ZOOM 8. + +/********************************************************** +* Debug * +**********************************************************/ + +//show pickable points: +//#define DEBUG_PICKING 1 + + + + +#endif diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt b/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt new file mode 100644 index 00000000..c60217b9 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt @@ -0,0 +1,51 @@ +gaudi_subdir(GaudiPandora v0r0) + +find_package(CLHEP REQUIRED) +#find_package(GSL REQUIRED )##don't use this, use CEPC LCIO version one , due to the ClusterShape.cc file which is from LCIO +#message("GSL: ${GSL_LIBRARIES} ") +set (gsl_include "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/include") +set (gsl_lib1 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgsl.so") +set (gsl_lib2 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgslcblas.so") +find_package(LCIO REQUIRED ) +find_package(GEAR REQUIRED) +message("ENV GEAR: $ENV{GEAR}") + + +find_package(EDM4HEP REQUIRED ) +include_directories(${EDM4HEP_INCLUDE_DIR}) +link_libraries("/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/externals/97.0.0/EDM4hep/lib64/libedm4hep.so") +find_package(PandoraSDK REQUIRED ) +include_directories(${PandoraSDK_INCLUDE_DIRS}) +link_libraries(${PandoraSDK_LIBRARIES}) +find_package(LCContent REQUIRED ) +include_directories(${LCContent_INCLUDE_DIRS}) +link_libraries(${LCContent_LIBRARIES}) + + +list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") +find_package(ROOT 5.26.00 REQUIRED COMPONENTS Eve Geom RGL EG) + +include_directories("../CED/CED/") +include_directories("../MarlinUtil/01-08/source/") + +gaudi_depends_on_subdirs( + Service/EventSeeder + Service/GearSvc +) + +set(dir_srcs + src/PandoraPFAlg.cpp + src/MCParticleCreator.cpp + src/GeometryCreator.cpp + src/CaloHitCreator.cpp + src/TrackCreator.cpp + src/PfoCreator.cpp + ../CED/CED/*.cc + ../MarlinUtil/01-08/source/*.cc +) +set(dir_include include) +# Modules +gaudi_add_module(GaudiPandora ${dir_srcs} + INCLUDE_DIRS ${gsl_include} ${dir_include} GaudiKernel FWCore CLHEP ${LCIO_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} gear + LINK_LIBRARIES ${gsl_lib1} ${gsl_lib2} GaudiKernel FWCore CLHEP ROOT ${LCIO_LIBRARIES} $ENV{GEAR}/lib/libgear.so $ENV{GEAR}/lib/libgearxml.so +) diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h new file mode 100644 index 00000000..4ea4e9b0 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h @@ -0,0 +1,282 @@ +/** + * @file MarlinPandora/include/CaloHitCreator.h + * + * @brief Header file for the calo hit creator class. + * + * $Log: $ + */ + +#ifndef CALO_HIT_CREATOR_H +#define CALO_HIT_CREATOR_H 1 + +#include "GaudiKernel/ISvcLocator.h" +#include "edm4hep/CalorimeterHit.h" + +#include "gear/LayerLayout.h" + +#include "Api/PandoraApi.h" + +#include <string> + +typedef std::vector<edm4hep::CalorimeterHit *> CalorimeterHitVector; + +namespace gear { class GearMgr; } + +class CollectionMaps; +/** + * @brief CaloHitCreator class + */ +class CaloHitCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_eCalCaloHitCollections; ///< The ecal calorimeter hit collections + StringVector m_hCalCaloHitCollections; ///< The hcal calorimeter hit collections + StringVector m_lCalCaloHitCollections; ///< The lcal calorimeter hit collections + StringVector m_lHCalCaloHitCollections; ///< The lhcal calorimeter hit collections + StringVector m_muonCaloHitCollections; ///< The muon calorimeter hit collections + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + float m_eCalToMip; ///< The calibration from deposited ECal energy to mip + float m_hCalToMip; ///< The calibration from deposited HCal energy to mip + float m_muonToMip; ///< The calibration from deposited Muon energy to mip + float m_eCalMipThreshold; ///< Threshold for creating calo hits in the ECal, units mip + float m_hCalMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + float m_muonMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + + float m_eCalToEMGeV; ///< The calibration from deposited ECal energy to EM energy + float m_eCalToHadGeVBarrel; ///< The calibration from deposited ECal barrel energy to hadronic energy + float m_eCalToHadGeVEndCap; ///< The calibration from deposited ECal endcap energy to hadronic energy + float m_hCalToEMGeV; ///< The calibration from deposited HCal energy to EM energy + float m_hCalToHadGeV; ///< The calibration from deposited HCal energy to hadronic energy + int m_muonDigitalHits; ///< Muon hits are treated as digital (energy from hit count) + float m_muonHitEnergy; ///< The energy for a digital muon calorimeter hit, units GeV + + float m_maxHCalHitHadronicEnergy; ///< The maximum hadronic energy allowed for a single hcal hit + int m_nOuterSamplingLayers; ///< Number of layers from edge for hit to be flagged as an outer layer hit + float m_layersFromEdgeMaxRearDistance; ///< Maximum number of layers from candidate outer layer hit to rear of detector + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD00 gear file) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD00 gear file) + + // For Strip Splitting method and hybrid ECAL. + int m_stripSplittingOn; ///< To use SSA, this should be true (default is false) + int m_useEcalScLayers; ///< To use scintillator layers ~ hybrid ECAL, this should be true (default is false) + float m_eCalSiToMip; ///< The calibration from deposited Si-layer energy to mip + float m_eCalScToMip; ///< The calibration from deposited Sc-layer energy to mip + float m_eCalSiMipThreshold; ///< Threshold for creating calo hits in the Si-layers of ECAL, units mip + float m_eCalScMipThreshold; ///< Threshold for creating calo hits in the Sc-layers of ECAL, units mip + float m_eCalSiToEMGeV; ///< The calibration from deposited Si-layer energy to EM energy + float m_eCalScToEMGeV; ///< The calibration from deposited Sc-layer energy to EM energy + float m_eCalSiToHadGeVBarrel; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVBarrel; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + float m_eCalSiToHadGeVEndCap; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVEndCap; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style); + + /** + * @brief Destructor + */ + ~CaloHitCreator(); + + /** + * @brief Create calo hits + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateCaloHits(const LCEvent *const pLCEvent); + pandora::StatusCode CreateCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get the calorimeter hit vector + * + * @return The calorimeter hit vector + */ + const CalorimeterHitVector &GetCalorimeterHitVector() const; + + /** + * @brief Reset the calo hit creator + */ + void Reset(); + +private: + /** + * @brief Create ecal calo hits + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateECalCaloHits(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode CreateECalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create hcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create muon calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateMuonCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateLCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lhcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateLHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get common calo hit properties: position, parent address, input energy and time + * + * @param pCaloHit the lcio calorimeter hit + * @param caloHitParameters the calo hit parameters to populate + */ + void GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const; + + /** + * @brief Get end cap specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + * @param pCaloHit the lcio calorimeter hit + * @param layerLayout the gear end cap layer layout + * @param caloHitParameters the calo hit parameters to populate + * @param absorberCorrection to receive the absorber thickness correction for the mip equivalent energy + */ + void GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const; + + /** + * @brief Get barrel specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + * @param pCaloHit the lcio calorimeter hit + * @param layerLayout the gear barrel layer layout + * @param barrelSymmetryOrder the barrel order of symmetry + * @param barrelPhi0 the barrel orientation + * @param staveNumber the stave number + * @param caloHitParameters the calo hit parameters to populate + * @param absorberCorrection to receive the absorber thickness correction for the mip equivalent energy + */ + void GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const; + + /** + * @brief Get number of active layers from position of a calo hit to the edge of the detector + * + * @param pCaloHit the lcio calorimeter hit + */ + int GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const; + + /** + * @brief Get the maximum radius of a calo hit in a polygonal detector structure + * + * @param pCaloHit the lcio calorimeter hit + * @param symmetryOrder the symmetry order + * @param phi0 the angular orientation + * + * @return the maximum radius + */ + float GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const; + + /** + * @brief Get the layer coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the layer coding string + */ + std::string GetLayerCoding(const std::string &encodingString) const; + + /** + * @brief Get the stave coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the stave coding string + */ + std::string GetStaveCoding(const std::string &encodingString) const; + + const Settings m_settings; ///< The calo hit creator settings + + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create calo hits + + float m_eCalBarrelOuterZ; ///< ECal barrel outer z coordinate + float m_hCalBarrelOuterZ; ///< HCal barrel outer z coordinate + float m_muonBarrelOuterZ; ///< Muon barrel outer z coordinate + float m_coilOuterR; ///< Coil outer r coordinate + + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi0 coordinate + unsigned int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_hCalBarrelInnerPhi0; ///< HCal barrel inner phi0 coordinate + unsigned int m_hCalBarrelInnerSymmetry; ///< HCal barrel inner symmetry order + float m_muonBarrelInnerPhi0; ///< Muon barrel inner phi0 coordinate + unsigned int m_muonBarrelInnerSymmetry; ///< Muon barrel inner symmetry order + + float m_hCalEndCapOuterR; ///< HCal endcap outer r coordinate + float m_hCalEndCapOuterZ; ///< HCal endcap outer z coordinate + float m_hCalBarrelOuterR; ///< HCal barrel outer r coordinate + float m_hCalBarrelOuterPhi0; ///< HCal barrel outer phi0 coordinate + unsigned int m_hCalBarrelOuterSymmetry; ///< HCal barrel outer symmetry order + + float m_hCalBarrelLayerThickness; ///< HCal barrel layer thickness + float m_hCalEndCapLayerThickness; ///< HCal endcap layer thickness + + CalorimeterHitVector m_calorimeterHitVector; ///< The calorimeter hit vector + std::string m_encoder_str; + std::string m_encoder_str_MUON ; + std::string m_encoder_str_LCal ; + std::string m_encoder_str_LHCal; + gear::GearMgr* _GEAR; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const CalorimeterHitVector &CaloHitCreator::GetCalorimeterHitVector() const +{ + return m_calorimeterHitVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void CaloHitCreator::Reset() +{ + m_calorimeterHitVector.clear(); +} + +#endif // #ifndef CALO_HIT_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h new file mode 100644 index 00000000..8be08e2f --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h @@ -0,0 +1,158 @@ +/** + * @file MarlinPandora/include/GeometryCreator.h + * + * @brief Header file for the geometry creator class. + * + * $Log: $ + */ + +#ifndef GEOMETRY_CREATOR_H +#define GEOMETRY_CREATOR_H 1 + +#include "Api/PandoraApi.h" + +#include "GaudiKernel/ISvcLocator.h" +//namespace gear { class CalorimeterParameters; } +namespace gear { class CalorimeterParameters; class GearMgr; } + +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief GeometryCreator class + */ +class GeometryCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + int m_eCalEndCapInnerSymmetryOrder; ///< ECal end cap inner symmetry order (missing from ILD gear files) + float m_eCalEndCapInnerPhiCoordinate; ///< ECal end cap inner phi coordinate (missing from ILD gear files) + int m_eCalEndCapOuterSymmetryOrder; ///< ECal end cap outer symmetry order (missing from ILD gear files) + float m_eCalEndCapOuterPhiCoordinate; ///< ECal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD gear files) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD gear files) + int m_hCalEndCapOuterSymmetryOrder; ///< HCal end cap outer symmetry order (missing from ILD gear files) + float m_hCalEndCapOuterPhiCoordinate; ///< HCal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalRingInnerSymmetryOrder; ///< HCal ring inner symmetry order (missing from ILD gear files) + float m_hCalRingInnerPhiCoordinate; ///< HCal ring inner phi coordinate (missing from ILD gear files) + int m_hCalRingOuterSymmetryOrder; ///< HCal ring outer symmetry order (missing from ILD gear files) + float m_hCalRingOuterPhiCoordinate; ///< HCal ring outer phi coordinate (missing from ILD gear files) + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~GeometryCreator(); + + /** + * @brief Create geometry + */ + //pandora::StatusCode CreateGeometry() const; + pandora::StatusCode CreateGeometry(ISvcLocator* svcloc); + +private: + typedef std::map<pandora::SubDetectorType, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorTypeMap; + typedef std::map<std::string, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorNameMap; + + /** + * @brief Set mandatory sub detector parameters + * + * @param subDetectorTypeMap the sub detector type map + */ + void SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Set additional sub detector parameters + * + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + void SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Set sub detector parameters to their gear default values + * + * @param inputParameters input parameters, from gear + * @param subDetectorName the sub detector name + * @param subDetectorType the sub detector type + * @param parameters the sub detector parameters + */ + void SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const; + + /** + * @brief Set positions of gaps in ILD detector and add information missing from GEAR parameters file + * + * @param subDetectorTypeMap the sub detector type map + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + pandora::StatusCode SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Add information missing from GEAR parameters file for ILD SDHCAL detector + * + * @param subDetectorTypeMap the sub detector type map + */ + pandora::StatusCode SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Specify positions of hcal barrel box gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelBoxGaps() const; + + /** + * @brief Specify positions of hcal end cap box gaps - ILD specific + */ + pandora::StatusCode CreateHCalEndCapBoxGaps() const; + + /** + * @brief Specify positions of hcal barrel concentric polygon gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelConcentricGaps() const; + + /** + * @brief Create box gaps at regular positions on polygonal prism, oriented along main z axis - ILD specific + * + * @param symmetryOrder the pandora geometry parameters + * @param phi0 the phi coordinate + * @param innerRadius the inner r coordinate + * @param outerRadius the outer r coordinate + * @param minZ the minimum z coordinate + * @param maxZ the maximum z coordinate + * @param gapWidth the gap width + * @param vertexOffset position offset for vertex that doesn't point back to origin of xy plane + */ + pandora::StatusCode CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, float minZ, + float maxZ, float gapWidth, pandora::CartesianVector vertexOffset = pandora::CartesianVector(0, 0, 0)) const; + + const Settings m_settings; ///< The geometry creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the geometry + gear::GearMgr* _GEAR; +}; + +#endif // #ifndef GEOMETRY_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h new file mode 100644 index 00000000..46dbb55e --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h @@ -0,0 +1,100 @@ +/** + * @file MarlinPandora/include/MCParticleCreator.h + * + * @brief Header file for the mc particle creator class. + * + * $Log: $ + */ + +#ifndef MC_PARTICLE_CREATOR_H +#define MC_PARTICLE_CREATOR_H 1 + +#include "edm4hep/MCParticle.h" +#include "Api/PandoraApi.h" + +#include "CaloHitCreator.h" +#include "TrackCreator.h" +/** + * @brief MCParticleCreator class + */ +//typedef std::map<unsigned int, edm4hep::MCParticle*> id_MCParticleMap; +//typedef std::map<unsigned int, const edm4hep::MCParticle*> id_MCParticleMap; + +class CollectionMaps; + +class MCParticleCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_mcParticleCollections; ///< The mc particle collections + StringVector m_CaloHitRelationCollections; ///< The SimCaloHit to CaloHit particle relations + StringVector m_TrackRelationCollections; ///< The SimTrackerHit to TrackerHit particle relations + float m_bField; ///< m_bField + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~MCParticleCreator(); + + /** + * @brief Create MCParticles + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateMCParticles(const EVENT::LCEvent *const pLCEvent) const; + //pandora::StatusCode CreateMCParticles(const std::map<std::string, const podio::CollectionBase*>& collectionMap ) const; + pandora::StatusCode CreateMCParticles(const CollectionMaps& collectionMaps ) const; + + /** + * @brief Create Track to mc particle relationships + * + * @param pLCEvent the lcio event + * @param trackVector the vector containing all tracks successfully passed to pandora + */ + // pandora::StatusCode CreateTrackToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const TrackVector &trackVector) const; + pandora::StatusCode CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const; + + void Reset(); + /** + * @brief Create calo hit to mc particle relationships + * + * @param pLCEvent the lcio event + * @param calorimeterHitVector the vector containing all calorimeter hits successfully passed to pandora + */ +// pandora::StatusCode CreateCaloHitToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const CalorimeterHitVector &calorimeterHitVector) const; + pandora::StatusCode CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const; + +private: + const Settings m_settings; ///< The mc particle creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the mc particles + const float m_bField; ///< The bfield + std::map<unsigned int, const edm4hep::MCParticle*>* m_id_pMC_map; +}; + +inline void MCParticleCreator::Reset() +{ + m_id_pMC_map->clear(); +} + +#endif // #ifndef MC_PARTICLE_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h new file mode 100644 index 00000000..8774006c --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h @@ -0,0 +1,320 @@ +#ifndef PandoraPFAlg_H +#define PandoraPFAlg_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include <gsl/gsl_rng.h> +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" +#include "edm4hep/MCRecoCaloAssociationCollection.h" +#include "edm4hep/MCRecoParticleAssociation.h" +#include "edm4hep/MCRecoParticleAssociationCollection.h" + +#include "Api/PandoraApi.h" + +#ifdef MONITORING +#include "TApplication.h" +#endif + +#include <iostream> +#include <random> +#include <string> +#include <unistd.h> + + +#include "CaloHitCreator.h" +#include "GeometryCreator.h" +#include "MCParticleCreator.h" +#include "PfoCreator.h" +#include "TrackCreator.h" + +#include "TROOT.h" +#include "TTree.h" +#include "TFile.h" + + +/* PandoraPFAlg ========== <br> + * + */ +namespace pandora {class Pandora;} + +class IEventSeeder; + +class CollectionMaps +{ +public: + /** + * @brief Default constructor + */ + CollectionMaps(); + void clear(); + std::map<std::string, const edm4hep::MCParticleCollection*> CollectionMap_MC; + std::map<std::string, const edm4hep::CalorimeterHitCollection*> CollectionMap_CaloHit; + std::map<std::string, const edm4hep::VertexCollection*> CollectionMap_Vertex; + std::map<std::string, const edm4hep::TrackCollection*> CollectionMap_Track; + + std::map<std::string, std::vector<edm4hep::MCParticle> > collectionMap_MC; + std::map<std::string, std::vector<edm4hep::CalorimeterHit> > collectionMap_CaloHit; + std::map<std::string, std::vector<edm4hep::Vertex> > collectionMap_Vertex; + std::map<std::string, std::vector<edm4hep::Track> > collectionMap_Track; + std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> > collectionMap_CaloRel; + std::map<std::string, std::vector<edm4hep::MCRecoTrackerAssociation> > collectionMap_TrkRel; +}; + + + +class PandoraPFAlg : public GaudiAlgorithm +{ + //friend class AlgFactory<PandoraPFAlg>;//gives error in 97 version + +public: + + PandoraPFAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + /** Called for every event - the working horse. + */ + virtual StatusCode execute() ; + + /** Called after data processing for clean up. + */ + virtual StatusCode finalize() ; + + //void FinaliseSteeringParameters(); + void FinaliseSteeringParameters(ISvcLocator* svcloc); + pandora::StatusCode RegisterUserComponents() const; + void Reset(); + typedef std::vector<float> FloatVector; + typedef std::vector<std::string> StringVector; + + + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_pandoraSettingsXmlFile; ///< The pandora settings xml file + + float m_innerBField; ///< The bfield in the main tracker, ecal and hcal, units Tesla + float m_muonBarrelBField; ///< The bfield in the muon barrel, units Tesla + float m_muonEndCapBField; ///< The bfield in the muon endcap, units Tesla + + FloatVector m_inputEnergyCorrectionPoints; ///< The input energy points for non-linearity energy correction + FloatVector m_outputEnergyCorrectionPoints; ///< The output energy points for non-linearity energy correction + }; + + + /** + * @brief Get address of the pandora instance + * + * @return address of the pandora instance + */ + const pandora::Pandora *GetPandora() const; + StatusCode updateMap(); + StatusCode updateMap(CollectionMaps & tmp_map); + StatusCode Ana(); + StatusCode CreateMCRecoParticleAssociation(); + //StatusCode Create_MC(); +protected: + + typedef std::vector<float> FloatVec; + + int _nEvt ; + + IEventSeeder * _SEEDER; + + + Gaudi::Property< std::string > m_PandoraSettingsXmlFile { this, "PandoraSettingsDefault_xml", "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" }; + Gaudi::Property<int> m_NEventsToSkip { this, "NEventsToSkip", 0 }; + + Gaudi::Property< std::vector<std::string> > m_TrackCollections{ this, "TrackCollections", {"MarlinTrkTracks"} }; + Gaudi::Property< std::vector<std::string> > m_ECalCaloHitCollections{ this, "ECalCaloHitCollections", {"ECALBarrel","ECALEndcap","ECALOther"} }; + Gaudi::Property< std::vector<std::string> > m_HCalCaloHitCollections{ this, "HCalCaloHitCollections", {"HCALBarrel","HCALEndcap","HCALOther"} }; + Gaudi::Property< std::vector<std::string> > m_LCalCaloHitCollections{ this, "LCalCaloHitCollections", {"LCAL"} }; + Gaudi::Property< std::vector<std::string> > m_LHCalCaloHitCollections{ this, "LHCalCaloHitCollections", {"LHCAL"} }; + Gaudi::Property< std::vector<std::string> > m_MuonCaloHitCollections{ this, "MuonCaloHitCollections", {"MUON"} }; + Gaudi::Property< std::vector<std::string> > m_MCParticleCollections{ this, "MCParticleCollections", {"MCParticle"} }; + Gaudi::Property< std::vector<std::string> > m_RelCaloHitCollections{ this, "RelCaloHitCollections", {"RelationCaloHit","RelationMuonHit"} }; + Gaudi::Property< std::vector<std::string> > m_RelTrackCollections{ this, "RelTrackCollections", {"MarlinTrkTracksMCTruthLink"} }; + Gaudi::Property< std::vector<std::string> > m_KinkVertexCollections{ this, "KinkVertexCollections", {"KinkVertices"} }; + Gaudi::Property< std::vector<std::string> > m_ProngVertexCollections{ this, "ProngVertexCollections", {"ProngVertices"} }; + Gaudi::Property< std::vector<std::string> > m_SplitVertexCollections{ this, "SplitVertexCollections", {"SplitVertices"} }; + Gaudi::Property< std::vector<std::string> > m_V0VertexCollections{ this, "V0VertexCollections", {"V0Vertices"} }; + Gaudi::Property< std::string > m_ClusterCollectionName { this, "ClusterCollectionName", "PandoraClusters" }; + Gaudi::Property< std::string > m_PFOCollectionName { this, "PFOCollectionName", "PandoraPFOs" }; + Gaudi::Property<float> m_ECalToMipCalibration{ this, "ECalToMipCalibration", 160.0 }; + Gaudi::Property<float> m_HCalToMipCalibration{ this, "HCalToMipCalibration", 34.8 }; + Gaudi::Property<float> m_ECalMipThreshold{ this, "ECalMipThreshold", 0.5 }; + Gaudi::Property<float> m_HCalMipThreshold{ this, "HCalMipThreshold", 0.3 }; + Gaudi::Property<float> m_ECalToEMGeVCalibration{ this, "ECalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_HCalToEMGeVCalibration{ this, "HCalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationBarrel{ this, "ECalToHadGeVCalibrationBarrel", 1.12 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationEndCap{ this, "ECalToHadGeVCalibrationEndCap", 1.12 }; + Gaudi::Property<float> m_HCalToHadGeVCalibration{ this, "HCalToHadGeVCalibration", 1.07 }; + Gaudi::Property<float> m_MuonToMipCalibration{ this, "MuonToMipCalibration", 10.0 }; + Gaudi::Property<int> m_DigitalMuonHits{ this, "DigitalMuonHits", 0 }; + Gaudi::Property<float> m_MaxHCalHitHadronicEnergy{ this, "MaxHCalHitHadronicEnergy", 1.0 }; + Gaudi::Property<int> m_UseOldTrackStateCalculation{ this, "UseOldTrackStateCalculation", 0 }; + + + Gaudi::Property<float> m_AbsorberRadLengthECal{ this, "AbsorberRadLengthECal", 0.2854 }; + Gaudi::Property<float> m_AbsorberIntLengthECal{ this, "AbsorberIntLengthECal", 0.0101 }; + Gaudi::Property<float> m_AbsorberRadLengthHCal{ this, "AbsorberRadLengthHCal", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthHCal{ this, "AbsorberIntLengthHCal", 0.006 }; + Gaudi::Property<float> m_AbsorberRadLengthOther{ this, "AbsorberRadLengthOther", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthOther{ this, "AbsorberIntLengthOther", 0.006 }; + Gaudi::Property< std::string > m_StartVertexCollectionName { this, "StartVertexCollectionName", "PandoraPFANewStartVertices" }; + Gaudi::Property< std::string > m_StartVertexAlgorithmName { this, "StartVertexAlgorithmName", "PandoraPFANew" }; + Gaudi::Property<float> m_EMStochasticTerm{ this, "EMStochasticTerm", 0.17 }; + Gaudi::Property<float> m_HadStochasticTerm{ this, "HadStochasticTerm", 0.6 }; + Gaudi::Property<float> m_EMConstantTerm{ this, "EMConstantTerm", 0.01 }; + Gaudi::Property<float> m_HadConstantTerm{ this, "HadConstantTerm", 0.03 }; + Gaudi::Property<float> m_MuonHitEnergy{ this, "MuonHitEnergy", 0.5 }; + Gaudi::Property<int> m_NOuterSamplingLayers{ this, "NOuterSamplingLayers", 3 }; + Gaudi::Property<float> m_LayersFromEdgeMaxRearDistance{ this, "LayersFromEdgeMaxRearDistance", 250.f }; + Gaudi::Property<float> m_MuonBarrelBField{ this, "MuonBarrelBField", -1.5f }; + Gaudi::Property<float> m_MuonEndCapBField{ this, "MuonEndCapBField", 0.01f }; + Gaudi::Property<int> m_ShouldFormTrackRelationships{ this, "ShouldFormTrackRelationships", 1 }; + Gaudi::Property<int> m_MinTrackHits{ this, "MinTrackHits", 5 }; + Gaudi::Property<int> m_MinFtdTrackHits{ this, "MinFtdTrackHits", 0 }; + Gaudi::Property<int> m_MaxTrackHits{ this, "MaxTrackHits", 5000 }; + Gaudi::Property<float> m_D0TrackCut{ this, "D0TrackCut", 50. }; + Gaudi::Property<float> m_Z0TrackCut{ this, "Z0TrackCut", 50. }; + Gaudi::Property<int> m_UseNonVertexTracks{ this, "UseNonVertexTracks", 1 }; + Gaudi::Property<int> m_UseUnmatchedNonVertexTracks{ this, "UseUnmatchedNonVertexTracks", 0 }; + Gaudi::Property<int> m_UseUnmatchedVertexTracks{ this, "UseUnmatchedVertexTracks", 1 }; + Gaudi::Property<float> m_UnmatchedVertexTrackMaxEnergy{ this, "UnmatchedVertexTrackMaxEnergy", 5. }; + Gaudi::Property<float> m_D0UnmatchedVertexTrackCut{ this, "D0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_Z0UnmatchedVertexTrackCut{ this, "Z0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_ZCutForNonVertexTracks{ this, "ZCutForNonVertexTracks", 250. }; + Gaudi::Property<int> m_ReachesECalNTpcHits{ this, "ReachesECalNTpcHits", 11 }; + Gaudi::Property<int> m_ReachesECalNFtdHits{ this, "ReachesECalNFtdHits", 4 }; + Gaudi::Property<float> m_ReachesECalTpcOuterDistance{ this, "ReachesECalTpcOuterDistance", -100. }; + Gaudi::Property<int> m_ReachesECalMinFtdLayer{ this, "ReachesECalMinFtdLayer", 9 }; + Gaudi::Property<float> m_ReachesECalTpcZMaxDistance{ this, "ReachesECalTpcZMaxDistance", -50. }; + Gaudi::Property<float> m_ReachesECalFtdZMaxDistance{ this, "ReachesECalFtdZMaxDistance", -1. }; + Gaudi::Property<float> m_CurvatureToMomentumFactor{ this, "CurvatureToMomentumFactor", 0.3 / 2000. }; + Gaudi::Property<float> m_MinTrackECalDistanceFromIp{ this, "MinTrackECalDistanceFromIp", 100. }; + + Gaudi::Property<float> m_MaxTrackSigmaPOverP { this, "MaxTrackSigmaPOverP", 0.15 }; + Gaudi::Property<float> m_MinMomentumForTrackHitChecks { this, "MinMomentumForTrackHitChecks", 1. }; + Gaudi::Property<float> m_TpcMembraneMaxZ { this, "TpcMembraneMaxZ", 10. }; + Gaudi::Property<float> m_MinTpcHitFractionOfExpected { this, "MinTpcHitFractionOfExpected", 0.20 }; + Gaudi::Property<int> m_MinFtdHitsForTpcHitFraction { this, "MinFtdHitsForTpcHitFraction", 2 }; + Gaudi::Property<float> m_MaxTpcInnerRDistance { this, "MaxTpcInnerRDistance", 50.0 }; + Gaudi::Property<int> m_ECalEndCapInnerSymmetryOrder { this, "ECalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_ECalEndCapInnerPhiCoordinate { this, "ECalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_ECalEndCapOuterSymmetryOrder { this, "ECalEndCapOuterSymmetryOrder", 8 }; + Gaudi::Property<float> m_ECalEndCapOuterPhiCoordinate { this, "ECalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapInnerSymmetryOrder { this, "HCalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_HCalEndCapInnerPhiCoordinate { this, "HCalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapOuterSymmetryOrder { this, "HCalEndCapOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalEndCapOuterPhiCoordinate { this, "HCalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingInnerSymmetryOrder { this, "HCalRingInnerSymmetryOrder", 8 }; + Gaudi::Property<float> m_HCalRingInnerPhiCoordinate { this, "HCalRingInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingOuterSymmetryOrder { this, "HCalRingOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalRingOuterPhiCoordinate { this, "HCalRingOuterPhiCoordinate", 0. }; + Gaudi::Property<bool> m_StripSplittingOn { this, "StripSplittingOn", false }; + Gaudi::Property<bool> m_UseEcalScLayers { this, "UseEcalScLayers", false }; + Gaudi::Property<float> m_ECalSiToMipCalibration { this, "ECalSiToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalScToMipCalibration { this, "ECalScToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalSiMipThreshold { this, "ECalSiMipThreshold", 0. }; + Gaudi::Property<float> m_ECalScMipThreshold { this, "ECalScMipThreshold", 0. }; + Gaudi::Property<float> m_ECalSiToEMGeVCalibration { this, "ECalSiToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalScToEMGeVCalibration { this, "ECalScToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationEndCap { this, "ECalSiToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationEndCap { this, "ECalScToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationBarrel { this, "ECalSiToHadGeVCalibrationBarrel", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationBarrel { this, "ECalScToHadGeVCalibrationBarrel", 1. }; + + Gaudi::Property<FloatVector> m_InputEnergyCorrectionPoints { this, "InputEnergyCorrectionPoints", {} }; + Gaudi::Property<FloatVector> m_OutputEnergyCorrectionPoints { this, "OutputEnergyCorrectionPoints", {} }; + + + static pandora::Pandora *m_pPandora; + GeometryCreator *m_pGeometryCreator; ///< The geometry creator + CaloHitCreator *m_pCaloHitCreator; ///< The calo hit creator + TrackCreator *m_pTrackCreator; ///< The track creator + MCParticleCreator *m_pMCParticleCreator; ///< The mc particle creator + PfoCreator *m_pPfoCreator; ///< The pfo creator + + Settings m_settings; ///< The settings for the pandora pfa new algo + CollectionMaps *m_CollectionMaps; ///< The settings for the pandora pfa new algo + GeometryCreator::Settings m_geometryCreatorSettings; ///< The geometry creator settings + TrackCreator::Settings m_trackCreatorSettings; ///< The track creator settings + CaloHitCreator::Settings m_caloHitCreatorSettings; ///< The calo hit creator settings + MCParticleCreator::Settings m_mcParticleCreatorSettings; ///< The mc particle creator settings + PfoCreator::Settings m_pfoCreatorSettings; ///< The pfo creator settings + + std::string m_detectorName; ///< The detector name + unsigned int m_nRun; ///< The run number + unsigned int m_nEvent; ///< The event number + //### For Ana ################# + TFile* m_fout; + TTree* m_tree; + std::vector<int > m_pReco_PID; + std::vector<float> m_pReco_mass; + std::vector<float> m_pReco_energy; + std::vector<float> m_pReco_px; + std::vector<float> m_pReco_py; + std::vector<float> m_pReco_pz; + std::vector<float> m_pReco_charge; + + std::vector<int> m_mc_p_size; + std::vector<int> m_mc_pid ; + std::vector<float> m_mc_mass ; + std::vector<float> m_mc_px ; + std::vector<float> m_mc_py ; + std::vector<float> m_mc_pz ; + std::vector<float> m_mc_charge; + int m_hasConversion; + + Gaudi::Property< std::string > m_AnaOutput{ this, "AnaOutput", "/junofs/users/wxfang/MyGit/CEPCSW/Reconstruction/PFA/Pandora/GaudiPandora/Ana.root" }; + //###################### + + DataHandle<edm4hep::MCParticleCollection> m_mcParCol_r {"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALBarrel_r{"ECALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALEndcap_r{"ECALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALOther_r {"ECALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALBarrel_r{"HCALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALEndcap_r{"HCALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALOther_r {"HCALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_MUON_r {"MUON", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LCAL_r {"LCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LHCAL_r {"LHCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_BCAL_r {"BCAL", Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::VertexCollection> m_KinkVertices_r {"KinkVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_ProngVertices_r {"ProngVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_SplitVertices_r {"SplitVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_V0Vertices_r {"V0Vertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackCollection> m_MarlinTrkTracks_r {"MarlinTrkTracks",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoCaloAssociationCollection> m_MCRecoCaloAssociation_r {"MCRecoCaloAssociation",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> m_MCRecoTrackerAssociation_r {"MCRecoTrackerAssociation",Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::ClusterCollection> m_ClusterCollection_w {"PandoraClusters",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::ReconstructedParticleCollection> m_ReconstructedParticleCollection_w {"PandoraPFOs" ,Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::VertexCollection> m_VertexCollection_w {"PandoraPFANewStartVertices",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoParticleAssociationCollection> m_MCRecoParticleAssociation_w {"pfoMCRecoParticleAssociation",Gaudi::DataHandle::Writer, this}; + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h new file mode 100644 index 00000000..85ba02dc --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h @@ -0,0 +1,221 @@ +/** + * @file MarlinPandora/include/PfoCreator.h + * + * @brief Header file for the pfo creator class. + * + * $Log: $ + */ + +#ifndef PFO_CREATOR_H +#define PFO_CREATOR_H 1 + +#include "FWCore/DataHandle.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/Cluster.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/ReconstructedParticle.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/Vertex.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/Track.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/CalorimeterHit.h" + +#include "ClusterShapes.h" +#include "Api/PandoraApi.h" + +//namespace IMPL { class ClusterImpl; class ReconstructedParticleImpl; } +//namespace EVENT { class LCEvent; } +class CollectionMaps; +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief PfoCreator class + */ +class PfoCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_clusterCollectionName; ///< The name of the cluster output collection + std::string m_pfoCollectionName; ///< The name of the pfo output collection + std::string m_startVertexCollectionName; ///< The name of the start vertex output collection + std::string m_startVertexAlgName; ///< The name of the algorithm to fill the start vertex output collection + float m_emStochasticTerm; ///< The stochastic term for EM shower energy resolution + float m_hadStochasticTerm; ///< The stochastic term for Hadronic shower energy resolution + float m_emConstantTerm; ///< The constant term for EM shower energy resolution + float m_hadConstantTerm; ///< The constant term for Hadronic shower energy resolution + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~PfoCreator(); + + /** + * @brief Create particle flow objects + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateParticleFlowObjects(EVENT::LCEvent *pLCEvent); + //pandora::StatusCode CreateParticleFlowObjects(const CollectionMaps& collectionMaps); + pandora::StatusCode CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection); + + CollectionMaps* m_collectionMaps; + +private: + /** + * @brief index for the subdetector + */ + enum Index + { + ECAL_INDEX = 0, + HCAL_INDEX = 1, + YOKE_INDEX = 2, + LCAL_INDEX = 3, + LHCAL_INDEX = 4, + BCAL_INDEX = 5 + }; + + /** + * @brief initialise sub detector name strings + * + * @param subDetectorNames to receive the list of sub detector names + */ + void InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const; + + /** + * @brief Set sub detector energies for a cluster + * + * @param subDetectorNames the list of sub detector names + * @param pLcioCluster the address of the lcio cluster to be set sub detector energies + * @param pandoraCaloHitList the pandora calorimeter hit list + * @param hitE the vector to receive the energy of hits + * @param hitX the vector to receive the x position of hits + * @param hitY the vector to receive the y position of hits + * @param hitZ the vector to receive the z position of hits + */ + void SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const pLcioCluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const; + + /** + * @brief Set cluster energies and errors + * + * @param pPandoraPfo the address of the pandora pfo + * @param pPandoraCluster the address of the pandora cluster + * @param pLcioCluster the address of the lcio cluster to be set energies and erros + * @param clusterCorrectEnergy a number to receive the cluster correct energy + */ + void SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const pLcioCluster, float &clusterCorrectEnergy) const; + + /** + * @brief Set cluster position, errors and other shape info, by calculating culster shape first + * + * @param nHitsInCluster number of hits in cluster + * @param hitE the vector of the energy of hits + * @param hitX the vector of the x position of hits + * @param hitY the vector of the y position of hits + * @param hitZ the vector of the z position of hits + * @param pLcioCluster the lcio cluster to be set positions and errors + * @param clusterPosition a CartesianVector to receive the cluster position + */ + void SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const pLcioCluster, pandora::CartesianVector &clusterPositionVec) const; + + /** + * @brief Calculate reference point for pfo with tracks + * + * @param pPandoraPfo the address of the pandora pfo + * @param referencePoint a CartesianVector to receive the reference point + */ + pandora::StatusCode CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const; + + /** + * @brief Set reference point of the reconstructed particle + * + * @param referencePoint a CartesianVector of the reference point + * @param pReconstructedParticle the address of the reconstructed particle to be reference point + */ + void SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Add tracks to reconstructed particle + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be added tracks + */ + void AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Set properties of reconstructed particle from pandora pfo + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be set properties + */ + void SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Whether parent and daughter tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether sibling tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether the track is the closest (of those associated with the same pfo) to the interaction point + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether at least one track sibling track is associated to the reconstructed particle + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + const Settings m_settings; ///< The pfo creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object from which to extract the pfos +}; + +#endif // #ifndef PFO_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h new file mode 100644 index 00000000..5e036715 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h @@ -0,0 +1,378 @@ +/** + * @file MarlinPandora/include/TrackCreator.h + * + * @brief Header file for the track creator class. + * + * $Log: $ + */ + +#ifndef TRACK_CREATOR_H +#define TRACK_CREATOR_H 1 + +//#include "lcio.h" + +//#include "IMPL/LCCollectionVec.h" +//#include "IMPL/LCFlagImpl.h" + +//#include "EVENT/LCEvent.h" +//#include "EVENT/Track.h" + +#include "GaudiKernel/ISvcLocator.h" + +#include "edm4hep/Track.h" +#include "edm4hep/TrackConst.h" +#include "edm4hep/TrackState.h" +#include "edm4hep/ReconstructedParticleConst.h" + +#include "Api/PandoraApi.h" +#include "Objects/Helix.h" + +namespace gear { class GearMgr; } + +class CollectionMaps; + +typedef std::vector<const edm4hep::Track *> TrackVector; +//typedef std::set<const edm4hep::Track *> TrackList; +typedef std::set<unsigned int> TrackList; +//typedef std::map<edm4hep::Track *, int> TrackToPidMap; +typedef std::map<edm4hep::ConstTrack, int> TrackToPidMap; +/* +inline LCCollectionVec *newTrkCol(const std::string &name, LCEvent *evt , bool isSubset) +{ + LCCollectionVec* col = new LCCollectionVec( LCIO::TRACK ) ; + + LCFlagImpl hitFlag(0) ; + hitFlag.setBit( LCIO::TRBIT_HITS ) ; + col->setFlag( hitFlag.getFlag() ) ; + evt->addCollection( col , name ) ; + col->setSubset( isSubset ) ; + + return col ; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief TrackCreator class + */ +class TrackCreator +{ +public: + typedef std::vector<double> DoubleVector; + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_trackCollections; ///< The reconstructed track collections + StringVector m_kinkVertexCollections; ///< The kink vertex collections + StringVector m_prongVertexCollections; ///< The prong vertex collections + StringVector m_splitVertexCollections; ///< The split vertex collections + StringVector m_v0VertexCollections; ///< The v0 vertex collections + + StringVector m_prongSplitVertexCollections; ///< Concatenated list of prong and split vertex collections + int m_shouldFormTrackRelationships; ///< Whether to form pandora track relationships using v0 and kink info + + int m_minTrackHits; ///< Track quality cut: the minimum number of track hits + int m_minFtdTrackHits; ///< Track quality cut: the minimum number of FTD track hits for FTD only tracks + int m_maxTrackHits; ///< Track quality cut: the maximum number of track hits + + float m_d0TrackCut; ///< Track d0 cut used to determine whether track can be used to form pfo + float m_z0TrackCut; ///< Track z0 cut used to determine whether track can be used to form pfo + + int m_usingNonVertexTracks; ///< Whether can form pfos from tracks that don't start at vertex + int m_usingUnmatchedNonVertexTracks; ///< Whether can form pfos from unmatched tracks that don't start at vertex + int m_usingUnmatchedVertexTracks; ///< Whether can form pfos from unmatched tracks that start at vertex + float m_unmatchedVertexTrackMaxEnergy; ///< Maximum energy for unmatched vertex track + + float m_d0UnmatchedVertexTrackCut; ///< d0 cut used to determine whether unmatched vertex track can form pfo + float m_z0UnmatchedVertexTrackCut; ///< z0 cut used to determine whether unmatched vertex track can form pfo + float m_zCutForNonVertexTracks; ///< Non vtx track z cut to determine whether track can be used to form pfo + + int m_reachesECalNTpcHits; ///< Minimum number of tpc hits to consider track as reaching ecal + int m_reachesECalNFtdHits; ///< Minimum number of ftd hits to consider track as reaching ecal + float m_reachesECalTpcOuterDistance; ///< Max distance from track to tpc r max to id whether track reaches ecal + int m_reachesECalMinFtdLayer; ///< Min layer in Ftd for tracks to be considered to have reached decal + float m_reachesECalTpcZMaxDistance; ///< Max distance from track to tpc z max to id whether track reaches ecal + float m_reachesECalFtdZMaxDistance; ///< Max distance from track hit to ftd z position to identify ftd hits + float m_curvatureToMomentumFactor; ///< Constant relating track curvature in b field to momentum + + float m_minTrackECalDistanceFromIp; ///< Sanity check on separation between ip and track projected ecal position + float m_maxTrackSigmaPOverP; ///< Track fraction momentum error cut + float m_minMomentumForTrackHitChecks; ///< Min track momentum required to perform final quality checks on number of hits + + float m_tpcMembraneMaxZ; ///< Tpc membrane max z coordinate + float m_maxTpcInnerRDistance; ///< Track cut on distance from tpc inner r to id whether track can form pfo + float m_minTpcHitFractionOfExpected; ///< Minimum fraction of TPC hits compared to expected + int m_minFtdHitsForTpcHitFraction; ///< Minimum number of FTD hits to ignore TPC hit fraction + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + //TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora); + TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc); + + /** + * @brief Destructor + */ + ~TrackCreator(); + + /** + * @brief Create associations between tracks, V0s, kinks, etc + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateTrackAssociations(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode CreateTrackAssociations(const CollectionMaps& collectionMaps); + + /** + * @brief Create tracks, insert user code here + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateTracks(EVENT::LCEvent *pLCEvent); + pandora::StatusCode CreateTracks(const CollectionMaps& collectionMaps); + + /** + * @brief Get the track vector + * + * @return The track vector + */ + const TrackVector &GetTrackVector() const; + + /** + * @brief Reset the track creator + */ + void Reset(); + +private: + /** + * @brief Extract kink information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractKinks(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode ExtractKinks(const CollectionMaps& collectionMaps); + + /** + * @brief Extract prong and split information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Extract v0 information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractV0s(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Whether the track vertex conflicts with previously provided relationship information + * + * @param trackVec the vector of tracks associated with the vertex + */ + //bool IsConflictingRelationship(const EVENT::TrackVec &trackVec) const; + //bool IsConflictingRelationship(edm4hep::ConstTrack &trackVec) const; + bool IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const; + + /** + * @brief Whether a track is a v0 track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsV0(const EVENT::Track *const pTrack) const; + bool IsV0(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a parent track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsParent(const EVENT::Track *const pTrack) const; + bool IsParent(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a daughter track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsDaughter(const EVENT::Track *const pTrack) const; + bool IsDaughter(unsigned int pTrack_id) const; + + /** + * @brief Copy track states stored in lcio tracks to pandora track parameters + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void GetTrackStates(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Copy track state from lcio track state instance to pandora input track state + * + * @param pTrackState the lcio track state instance + * @param inputTrackState the pandora input track state + */ + //void CopyTrackState(const TrackState *const pTrackState, pandora::InputTrackState &inputTrackState) const; + void CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const; + + /** + * @brief Obtain track time when it reaches ECAL + * + * @param pTrack the lcio track + */ + //float CalculateTrackTimeAtCalorimeter(const EVENT::Track *const pTrack) const; + float CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const; + + /** + * @brief Decide whether track reaches the ecal surface + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void TrackReachesECAL(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + //void TrackReachesECAL(const edm4hep::Track& pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Determine whether a track can be used to form a pfo under the following conditions: + * 1) if the track proves to be associated with a cluster, OR + * 2) if the track proves to have no cluster associations + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void DefineTrackPfoUsage(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Whether track passes the quality cuts required in order to be used to form a pfo + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + * + * @return boolean + */ + //bool PassesQualityCuts(const EVENT::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + bool PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Get number of hits in TPC of a track + * + * @param pTrack the lcio track + * + * @return number of hits in TPC of a track + */ + //int GetNTpcHits(const EVENT::Track *const pTrack) const; + int GetNTpcHits(const edm4hep::Track *const pTrack) const; + + /** + * @brief Get number of hits in FTD of a track + * + * @param pTrack the lcio track + * + * @return number of hits in FTDof a track + */ + //int GetNFtdHits(const EVENT::Track *const pTrack) const; + int GetNFtdHits(const edm4hep::Track *const pTrack) const; + + const Settings m_settings; ///< The track creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create tracks and track relationships + + float m_bField; ///< The bfield + + float m_tpcInnerR; ///< The tpc inner radius + float m_tpcOuterR; ///< The tpc outer radius + unsigned int m_tpcMaxRow; ///< The tpc maximum row number + float m_tpcZmax; ///< The tpc maximum z coordinate + float m_cosTpc; ///< Cos(theta) value at end of tpc + + DoubleVector m_ftdInnerRadii; ///< List of ftd inner radii + DoubleVector m_ftdOuterRadii; ///< List of ftd outer radii + DoubleVector m_ftdZPositions; ///< List of ftd z positions + unsigned int m_nFtdLayers; ///< Number of ftd layers + float m_tanLambdaFtd; ///< Tan lambda for first ftd layer + + int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi 0 + float m_eCalBarrelInnerR; ///< ECal barrel inner radius + float m_eCalEndCapInnerZ; ///< ECal endcap inner z + + float m_minEtdZPosition; ///< Min etd z position + float m_minSetRadius; ///< Min set radius + + TrackVector m_trackVector; ///< The track vector + TrackList m_v0TrackList; ///< The list of v0 tracks + TrackList m_parentTrackList; ///< The list of parent tracks + TrackList m_daughterTrackList; ///< The list of daughter tracks + TrackToPidMap m_trackToPidMap; ///< The map from track addresses to particle ids, where set by kinks/V0s + gear::GearMgr* _GEAR; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const TrackVector &TrackCreator::GetTrackVector() const +{ + return m_trackVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void TrackCreator::Reset() +{ + m_trackVector.clear(); + m_v0TrackList.clear(); + m_parentTrackList.clear(); + m_daughterTrackList.clear(); + m_trackToPidMap.clear(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsV0(const Track *const pTrack) const +inline bool TrackCreator::IsV0(unsigned int pTrack_id) const // should check here, if id is correct one to do this +{ + //return (m_v0TrackList.end() != m_v0TrackList.find(pTrack)); + return (m_v0TrackList.end() != m_v0TrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsParent(const Track *const pTrack) const +inline bool TrackCreator::IsParent(unsigned int pTrack_id) const +{ + //return (m_parentTrackList.end() != m_parentTrackList.find(pTrack)); + return (m_parentTrackList.end() != m_parentTrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsDaughter(const Track *const pTrack) const +inline bool TrackCreator::IsDaughter(unsigned int pTrack_id) const +{ + //return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack)); + return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack_id)); +} + +#endif // #ifndef TRACK_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h new file mode 100644 index 00000000..0bd75b5d --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h @@ -0,0 +1,6 @@ +#ifndef MYUTILITY +#define MYUTILITY 1 + +#include <sstream> +std::string Convert (float number); +#endif diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h new file mode 100644 index 00000000..f1515996 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h @@ -0,0 +1,127 @@ +#ifndef cellIDDecoder_h +#define cellIDDecoder_h 1 + +//#include <vector> +//#include "EVENT/LCObject.h" +#include "EVENT/LCCollection.h" +//#include "EVENT/SimTrackerHit.h" +#include "UTIL/BitField64.h" +#include "lcio.h" +#include <string> + +// fixes problem in gcc 4.0.3 +#include "EVENT/LCParameters.h" + +//#include <sstream> +//#include <typeinfo> + +//##################### changed for EMD4HEP ######## +//need check !! + +namespace ID_UTIL{ + + + /** Convenient class for decoding cellIDs from collection parameter LCIO::CellIDEncoding. + * See UTIL::BitField64 for a description of the encoding string. + * + * @see BitField64 + * @version $Id: CellIDDecoder.h,v 1.9.16.1 2011-03-04 14:09:07 engels Exp $ + */ + template <class T> + class CellIDDecoder { + + public: + + CellIDDecoder() = default ; + CellIDDecoder(const CellIDDecoder& ) = delete ; + CellIDDecoder& operator=(const CellIDDecoder& ) = delete ; + + + /** Constructor takes encoding string as argument. + */ + CellIDDecoder( const std::string& encoder_str ) : _oldHit(0) { + + if( encoder_str.length() == 0 ){ + throw( lcio::Exception( "CellIDDecoder : string of length zero provided as encoder string" ) ) ; + } + _b = new UTIL::BitField64( encoder_str ) ; + + } + + /** Constructor reads encoding string from collection parameter LCIO::CellIDEncoding. + */ + CellIDDecoder( const EVENT::LCCollection* col ) : _oldHit(0) { + + std::string initString("") ; + + if( col !=0 ) + initString = col->getParameters().getStringVal( lcio::LCIO::CellIDEncoding ) ; + + if( initString.size() == 0 ) { + + initString = _defaultEncoding ; + + std::cout << " ----------------------------------------- " << std::endl + << " WARNING: CellIDDecoder - no CellIDEncoding parameter in collection ! " + << std::endl + << " -> using default : \"" << initString << "\"" + << std::endl + << " ------------------------------------------ " + << std::endl ; + } + + _b = new UTIL::BitField64( initString ) ; + } + + ~CellIDDecoder(){ + + delete _b ; + } + + + /** Provides access to the bit fields, e.g. <br> + * int layer = myCellIDEncoding( hit )[ "layer" ] ; + * + */ + inline const UTIL::BitField64 & operator()( const T* hit ){ + + if( hit != _oldHit && hit ) { + auto id = hit->getCellID(); + unsigned int id0 = id&0xFFFFFFFF; + unsigned int id1 = id>>32; + //lcio::long64 val = lcio::long64( hit->getCellID0() & 0xffffffff ) | ( lcio::long64( hit->getCellID1() ) << 32 ) ; + lcio::long64 val = lcio::long64( id0 & 0xffffffff ) | ( lcio::long64( id1 ) << 32 ) ; + + _b->setValue( val ) ; + + _oldHit = hit ; + } + + return *_b ; + } + + + /** This can be used to set the default encoding that is used if no + * CellIDEncoding parameter is set in the collection, e.g. in older lcio files. + */ + static void setDefaultEncoding(const std::string& defaultEncoding ) { + + _defaultEncoding = std::string( defaultEncoding ) ; + } + + protected: + UTIL::BitField64* _b{} ; + const T* _oldHit{NULL} ; + + static std::string _defaultEncoding; + } ; + + template <class T> + std::string CellIDDecoder<T>::_defaultEncoding + = std::string("byte0:8,byte1:8,byte2:8,byte3:8,byte4:8,byte5:8,byte6:8,byte7:8") ; + + +} // namespace +#endif + + diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp new file mode 100644 index 00000000..e4dc0e2a --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp @@ -0,0 +1,867 @@ +/** + * @file MarlinPandora/src/CaloHitCreator.cc + * + * @brief Implementation of the calo hit creator class. + * + * $Log: $ + */ + + +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/GearDistanceProperties.h" +#include "gear/GearPointProperties.h" +#include "gear/GEAR.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include "UTIL/CellIDDecoder.h" +#include "cellIDDecoder.h" +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" + +#include "PandoraPFAlg.h" +#include "CaloHitCreator.h" + +#include <algorithm> +#include <cmath> +#include <limits> +/* +template<typename T> +static float* FloatFromFloatThree(T vec, float &){ + float tmp[3]; + for(unsigned i=0; i<3; i++){ + tmp[i] = vec[i]; + } + return tmp; +} +*/ + + +CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style) : + m_settings(settings), + m_pPandora(pPandora) +{ + m_encoder_str = ""; + m_encoder_str_MUON = ""; + m_encoder_str_LCal = ""; + m_encoder_str_LHCal = ""; + if(encoder_style==0) + { + m_encoder_str = "M:3,S-1:3,I:9,J:9,K-1:6";// LCIO style + m_encoder_str_MUON="S-1:4,M:3,K-1:6,I:16,GRZone:3,J:32:16"; + m_encoder_str_LCal="I:10,J:10,K:10,S-1:2"; + m_encoder_str_LHCal=m_encoder_str; + } + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + m_eCalBarrelOuterZ = (_GEAR->getEcalBarrelParameters().getExtent()[3]); + m_hCalBarrelOuterZ = (_GEAR->getHcalBarrelParameters().getExtent()[3]); + m_muonBarrelOuterZ = (_GEAR->getYokeBarrelParameters().getExtent()[3]); + m_coilOuterR = (_GEAR->getGearParameters("CoilParameters").getDoubleVal("Coil_cryostat_outer_radius")); + m_eCalBarrelInnerPhi0 = (_GEAR->getEcalBarrelParameters().getPhi0()); + m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder()); + m_hCalBarrelInnerPhi0 = (_GEAR->getHcalBarrelParameters().getPhi0()); + m_hCalBarrelInnerSymmetry = (_GEAR->getHcalBarrelParameters().getSymmetryOrder()); + m_muonBarrelInnerPhi0 = (_GEAR->getYokeBarrelParameters().getPhi0()); + m_muonBarrelInnerSymmetry = (_GEAR->getYokeBarrelParameters().getSymmetryOrder()); + m_hCalEndCapOuterR = (_GEAR->getHcalEndcapParameters().getExtent()[1]); + m_hCalEndCapOuterZ = (_GEAR->getHcalEndcapParameters().getExtent()[3]); + m_hCalBarrelOuterR = (_GEAR->getHcalBarrelParameters().getExtent()[1]); + m_hCalBarrelOuterPhi0 =((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_phi0") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_phi0") + : 0)); + m_hCalBarrelOuterSymmetry = ((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_order") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_order") + : 0)); + + + const gear::LayerLayout &hCalEndCapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + m_hCalEndCapLayerThickness = hCalEndCapLayerLayout.getThickness(hCalEndCapLayerLayout.getNLayers() - 1); + m_hCalBarrelLayerThickness = hCalBarrelLayerLayout.getThickness(hCalBarrelLayerLayout.getNLayers() - 1); + if ((m_hCalEndCapLayerThickness < std::numeric_limits<float>::epsilon()) || (m_hCalBarrelLayerThickness < std::numeric_limits<float>::epsilon())) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::~CaloHitCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateCaloHits(const CollectionMaps& collectionMaps) +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateECalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateMuonCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLHCalCaloHits(collectionMaps)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& collectionMaps) +{ + std::cout<<"start CreateECalCaloHits:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_eCalCaloHitCollections.begin(), iterEnd = m_settings.m_eCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getEcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getEcalBarrelParameters().getLayerLayout()); + + //UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateECalCaloHits pCaloHit Collection type mismatch"); + + float eCalToMip(m_settings.m_eCalToMip), eCalMipThreshold(m_settings.m_eCalMipThreshold), eCalToEMGeV(m_settings.m_eCalToEMGeV), + eCalToHadGeVBarrel(m_settings.m_eCalToHadGeVBarrel), eCalToHadGeVEndCap(m_settings.m_eCalToHadGeVEndCap); + + // Hybrid ECAL including pure ScECAL. + if (m_settings.m_useEcalScLayers) + { + std::string collectionName(*iter); + std::transform(collectionName.begin(), collectionName.end(), collectionName.begin(), ::tolower); + + if (collectionName.find("ecal", 0) == std::string::npos) + std::cout << "WARNING: mismatching hybrid Ecal collection name. " << collectionName << std::endl; + + if (collectionName.find("si", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalSiToMip; + eCalMipThreshold = m_settings.m_eCalSiMipThreshold; + eCalToEMGeV = m_settings.m_eCalSiToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalSiToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalSiToHadGeVEndCap; + } + else if (collectionName.find("sc", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalScToMip; + eCalMipThreshold = m_settings.m_eCalScMipThreshold; + eCalToEMGeV = m_settings.m_eCalScToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalScToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalScToHadGeVEndCap; + } + } + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false;//why false ? + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1;//FIXME, should use + 1? because the decoded layer is start from 0. + //std::cout << "ECAL layer=" << caloHitParameters.m_layer.Get() << std::endl; + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_eCalBarrelOuterZ) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_eCalBarrelInnerSymmetry, m_eCalBarrelInnerPhi0, + cellIdDecoder(pCaloHit)[ staveCoding], caloHitParameters, absorberCorrection); + + caloHitParameters.m_hadronicEnergy = eCalToHadGeVBarrel * pCaloHit->getEnergy(); + + //std::cout << "ECAL: eCalToHadGeVBarrel="<<eCalToHadGeVBarrel<< std::endl; + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + caloHitParameters.m_hadronicEnergy = eCalToHadGeVEndCap * pCaloHit->getEnergy(); + //std::cout << "ECAL: eCalToHadGeVEndCap="<<eCalToHadGeVEndCap<< std::endl; + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = eCalToEMGeV * pCaloHit->getEnergy(); + //std::cout << "ECAL: eCalToEMGeV="<<eCalToEMGeV<< std::endl; + + // ATTN If using strip splitting, must correct cell sizes for use in PFA to minimum of strip width and strip length + if (m_settings.m_stripSplittingOn) + { + const float splitCellSize(std::min(caloHitParameters.m_cellSize0.Get(), caloHitParameters.m_cellSize1.Get())); + caloHitParameters.m_cellSize0 = splitCellSize; + caloHitParameters.m_cellSize1 = splitCellSize; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + /* + std::cout<<"i="<<i<<"\n" + <<",layer="<<caloHitParameters.m_layer.Get()<<"\n" + <<",m_hadronicEnergy="<<caloHitParameters.m_hadronicEnergy.Get()<<"\n" + <<",m_electromagneticEnergy="<<caloHitParameters.m_electromagneticEnergy.Get()<<"\n" + <<",m_mipEquivalentEnergy="<<caloHitParameters.m_mipEquivalentEnergy.Get()<<"\n" + <<",m_inputEnergy="<<caloHitParameters.m_inputEnergy.Get()<<"\n" + <<",m_positionVector0="<<caloHitParameters.m_positionVector.Get().GetX()<<"\n" + <<",m_positionVector1="<<caloHitParameters.m_positionVector.Get().GetY()<<"\n" + <<",m_positionVector2="<<caloHitParameters.m_positionVector.Get().GetZ()<<"\n" + <<std::endl; + */ + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract ecal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract ecal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout<< "Failed to extract ecal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_hCalCaloHitCollections.begin(), iterEnd = m_settings.m_hCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + + //UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateHCalCaloHits Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_hCalBarrelOuterZ) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_hCalBarrelInnerSymmetry, m_hCalBarrelInnerPhi0, + m_hCalBarrelInnerSymmetry - int(cellIdDecoder(pCaloHit)[ staveCoding] / 2), caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Error, Failed to extract hcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract hcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract hcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateMuonCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_muonCaloHitCollections.begin(), iterEnd = m_settings.m_muonCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getYokeEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getYokeBarrelParameters().getLayerLayout()); + const gear::LayerLayout &plugLayerLayout(_GEAR->getYokePlugParameters().getLayerLayout()); + + //UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_MUON); + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_MUON); + const std::string layerCodingString(m_encoder_str_MUON); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("Muon Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::MUON; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1;//FIXME, should use +1? it starts from 0. + caloHitParameters.m_isInOuterSamplingLayer = true; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + const float radius(std::sqrt(pCaloHit->getPosition()[0] * pCaloHit->getPosition()[0] + + pCaloHit->getPosition()[1] * pCaloHit->getPosition()[1])); + + const bool isWithinCoil(radius < m_coilOuterR); + const bool isInBarrelRegion(std::fabs(pCaloHit->getPosition()[2]) < m_muonBarrelOuterZ); + + float absorberCorrection(1.); + + if (isInBarrelRegion && isWithinCoil) + { + this->GetEndCapCaloHitProperties(pCaloHit, plugLayerLayout, caloHitParameters, absorberCorrection); + } + else if (isInBarrelRegion) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_muonBarrelInnerSymmetry, m_muonBarrelInnerPhi0, + cellIdDecoder(pCaloHit)[ staveCoding ], caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + if (m_settings.m_muonDigitalHits > 0) + { + caloHitParameters.m_isDigital = true; + caloHitParameters.m_inputEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_hadronicEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_electromagneticEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_mipEquivalentEnergy = 1.f; + } + else + { + caloHitParameters.m_isDigital = false; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_electromagneticEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_muonToMip; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract muon hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract muon hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract muon hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lCalCaloHitCollections.begin(), iterEnd = m_settings.m_lCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLcalParameters().getLayerLayout()); + + //UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LCal); + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LCal); + const std::string layerCodingString(m_encoder_str_LCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = m_settings.m_eCalToEMGeV * pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = m_settings.m_eCalToHadGeVEndCap * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lHCalCaloHitCollections.begin(), iterEnd = m_settings.m_lHCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLHcalParameters().getLayerLayout()); + + //UTIL::CellIDDecoder<edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LHCal); + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LHCal); + const std::string layerCodingString(m_encoder_str_LHCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LHCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lhcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const +{ + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + const pandora::CartesianVector positionVector(pCaloHitPosition[0], pCaloHitPosition[1], pCaloHitPosition[2]); + + caloHitParameters.m_cellGeometry = pandora::RECTANGULAR; + caloHitParameters.m_positionVector = positionVector; + caloHitParameters.m_expectedDirection = positionVector.GetUnitVector(); + //caloHitParameters.m_pParentAddress = (void*)pCaloHit; + caloHitParameters.m_pParentAddress = pCaloHit; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_time = pCaloHit->getTime(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::ENDCAP; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + //std::cout<<"interactionLength="<<interactionLength<<",layerAbsorberThickness="<<layerAbsorberThickness<<",radiationLength="<<radiationLength<<",physicalLayer="<<physicalLayer<<std::endl; + std::cout<<"WARNING CaloHitCreator::GetEndCapCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + caloHitParameters.m_cellNormalVector = (pCaloHit->getPosition()[2] > 0) ? pandora::CartesianVector(0, 0, 1) : + pandora::CartesianVector(0, 0, -1); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::BARREL; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + //std::cout<<"m_layer="<<caloHitParameters.m_layer.Get()<<",layerLayout.getNLayers() - 1="<<layerLayout.getNLayers() - 1<<",layerAbsorberThickness="<<layerAbsorberThickness<<std::endl; + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"interactionLength="<<interactionLength<<",layerAbsorberThickness="<<layerAbsorberThickness<<",radiationLength="<<radiationLength<<",physicalLayer="<<physicalLayer<<",l1="<<caloHitParameters.m_layer.Get()<<",l2="<<layerLayout.getNLayers()-1<<std::endl; + std::cout<<"WARNIN CaloHitCreator::GetBarrelCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + if (barrelSymmetryOrder > 2) + { + const float phi = barrelPhi0 + (2. * M_PI * static_cast<float>(staveNumber) / static_cast<float>(barrelSymmetryOrder)); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(-std::sin(phi), std::cos(phi), 0); + } + else + { + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + + if (pCaloHitPosition[1] != 0) + { + const float phi = barrelPhi0 + std::atan(pCaloHitPosition[0] / pCaloHitPosition[1]); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(std::sin(phi), std::cos(phi), 0); + } + else + { + caloHitParameters.m_cellNormalVector = (pCaloHitPosition[0] > 0) ? pandora::CartesianVector(1, 0, 0) : + pandora::CartesianVector(-1, 0, 0); + } + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int CaloHitCreator::GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const +{ + // Calo hit coordinate calculations + const float barrelMaximumRadius(this->GetMaximumRadius(pCaloHit, m_hCalBarrelOuterSymmetry, m_hCalBarrelOuterPhi0)); + const float endCapMaximumRadius(this->GetMaximumRadius(pCaloHit, m_settings.m_hCalEndCapInnerSymmetryOrder, m_settings.m_hCalEndCapInnerPhiCoordinate)); + const float caloHitAbsZ(std::fabs(pCaloHit->getPosition()[2])); + + // Distance from radial outer + float radialDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ < m_eCalBarrelOuterZ) + { + radialDistanceToEdge = (m_hCalBarrelOuterR - barrelMaximumRadius) / m_hCalBarrelLayerThickness; + } + else + { + radialDistanceToEdge = (m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness; + } + + // Distance from rear of endcap outer + float rearDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ >= m_eCalBarrelOuterZ) + { + rearDistanceToEdge = (m_hCalEndCapOuterZ - caloHitAbsZ) / m_hCalEndCapLayerThickness; + } + else + { + const float rearDistance((m_eCalBarrelOuterZ - caloHitAbsZ) / m_hCalBarrelLayerThickness); + + if (rearDistance < m_settings.m_layersFromEdgeMaxRearDistance) + { + const float overlapDistance((m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness); + rearDistanceToEdge = std::max(rearDistance, overlapDistance); + } + } + + return static_cast<int>(std::min(radialDistanceToEdge, rearDistanceToEdge)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float CaloHitCreator::GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const +{ + + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + if (symmetryOrder <= 2) + return std::sqrt((pCaloHitPosition[0] * pCaloHitPosition[0]) + (pCaloHitPosition[1] * pCaloHitPosition[1])); + + float maximumRadius(0.f); + const float twoPi(2.f * M_PI); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + i * twoPi / static_cast<float>(symmetryOrder); + float radius = pCaloHitPosition[0] * std::cos(phi) + pCaloHitPosition[1] * std::sin(phi); + + if (radius > maximumRadius) + maximumRadius = radius; + } + + return maximumRadius; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetLayerCoding(const std::string &encodingString) const +{ + if (encodingString.find("layer") != std::string::npos) + return std::string("layer"); + + if (encodingString.find("K-1") != std::string::npos) + return std::string("K-1"); + + if (encodingString.find("K") != std::string::npos) + return std::string("K"); + + return std::string("unknown_layer_encoding"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetStaveCoding(const std::string &encodingString) const +{ + if (encodingString.find("stave") != std::string::npos) + return std::string("stave"); + + if (encodingString.find("S-1") != std::string::npos) + return std::string("S-1"); + + return std::string("unknown_stave_encoding") ; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalToMip(1.f), + m_hCalToMip(1.f), + m_muonToMip(1.f), + m_eCalMipThreshold(0.f), + m_hCalMipThreshold(0.f), + m_muonMipThreshold(0.f), + m_eCalToEMGeV(1.f), + m_eCalToHadGeVBarrel(1.f), + m_eCalToHadGeVEndCap(1.f), + m_hCalToEMGeV(1.f), + m_hCalToHadGeV(1.f), + m_muonDigitalHits(1), + m_muonHitEnergy(0.5f), + m_maxHCalHitHadronicEnergy(10000.f), + m_nOuterSamplingLayers(3), + m_layersFromEdgeMaxRearDistance(250.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_stripSplittingOn(0), + m_useEcalScLayers(0), + m_eCalSiToMip(1.f), + m_eCalScToMip(1.f), + m_eCalSiMipThreshold(0.f), + m_eCalScMipThreshold(0.f), + m_eCalSiToEMGeV(1.f), + m_eCalScToEMGeV(1.f), + m_eCalSiToHadGeVBarrel(1.f), + m_eCalScToHadGeVBarrel(1.f), + m_eCalSiToHadGeVEndCap(1.f), + m_eCalScToHadGeVEndCap(1.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp new file mode 100644 index 00000000..35e8fedb --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp @@ -0,0 +1,433 @@ +/** + * @file MarlinPandora/src/GeometryCreator.cc + * + * @brief Implementation of the geometry creator class. + * + * $Log: $ + */ +#include "GaudiKernel/IService.h" + +#include "GearSvc/IGearSvc.h" +#include "gear/BField.h" +#include "gear/GEAR.h" +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include "GeometryCreator.h" +//#include "PandoraPFANewProcessor.h" + +GeometryCreator::GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::~GeometryCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//pandora::StatusCode GeometryCreator::CreateGeometry() const +//pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) const +pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) +{ + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + //auto _gear = service<IGearSvc>("GearSvc"); + //if ( !_gear ) + //{ + // throw "Failed to find GearSvc ..."; + //} + //_GEAR = _gear->getGearMgr(); + + + try + { + SubDetectorTypeMap subDetectorTypeMap; + this->SetMandatorySubDetectorParameters(subDetectorTypeMap); + + SubDetectorNameMap subDetectorNameMap; + this->SetAdditionalSubDetectorParameters(subDetectorNameMap); + + if (std::string::npos != _GEAR->getDetectorName().find("ILD")) + this->SetILDSpecificGeometry(subDetectorTypeMap, subDetectorNameMap); + + for (SubDetectorTypeMap::const_iterator iter = subDetectorTypeMap.begin(), iterEnd = subDetectorTypeMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + + for (SubDetectorNameMap::const_iterator iter = subDetectorNameMap.begin(), iterEnd = subDetectorNameMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + } + catch (gear::Exception &exception) + { + std::cout << "Failure in marlin pandora geometry creator, gear exception: " << exception.what() << std::endl; + throw exception; + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const +{ + std::cout << "Begin SetMandatorySubDetectorParameters:" << std::endl; + PandoraApi::Geometry::SubDetector::Parameters eCalBarrelParameters, eCalEndCapParameters, hCalBarrelParameters, hCalEndCapParameters, + muonBarrelParameters, muonEndCapParameters; + + this->SetDefaultSubDetectorParameters(_GEAR->getEcalBarrelParameters(), "ECalBarrel", pandora::ECAL_BARREL, eCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getEcalEndcapParameters(), "ECalEndCap", pandora::ECAL_ENDCAP, eCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalBarrelParameters(), "HCalBarrel", pandora::HCAL_BARREL, hCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalEndcapParameters(), "HCalEndCap", pandora::HCAL_ENDCAP, hCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeBarrelParameters(), "MuonBarrel", pandora::MUON_BARREL, muonBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeEndcapParameters(), "MuonEndCap", pandora::MUON_ENDCAP, muonEndCapParameters); + + subDetectorTypeMap[pandora::ECAL_BARREL] = eCalBarrelParameters; + subDetectorTypeMap[pandora::ECAL_ENDCAP] = eCalEndCapParameters; + subDetectorTypeMap[pandora::HCAL_BARREL] = hCalBarrelParameters; + subDetectorTypeMap[pandora::HCAL_ENDCAP] = hCalEndCapParameters; + subDetectorTypeMap[pandora::MUON_BARREL] = muonBarrelParameters; + subDetectorTypeMap[pandora::MUON_ENDCAP] = muonEndCapParameters; + + PandoraApi::Geometry::SubDetector::Parameters trackerParameters; + const gear::TPCParameters &tpcParameters(_GEAR->getTPCParameters()); + trackerParameters.m_subDetectorName = "Tracker"; + trackerParameters.m_subDetectorType = pandora::INNER_TRACKER; + trackerParameters.m_innerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[0]; + trackerParameters.m_innerZCoordinate = 0.f; + trackerParameters.m_innerPhiCoordinate = 0.f; + trackerParameters.m_innerSymmetryOrder = 0; + trackerParameters.m_outerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[1]; + trackerParameters.m_outerZCoordinate = tpcParameters.getMaxDriftLength(); + trackerParameters.m_outerPhiCoordinate = 0.f; + trackerParameters.m_outerSymmetryOrder = 0; + trackerParameters.m_isMirroredInZ = true; + trackerParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::INNER_TRACKER] = trackerParameters; + + PandoraApi::Geometry::SubDetector::Parameters coilParameters; + const gear::GearParameters &gearParameters(_GEAR->getGearParameters("CoilParameters")); + coilParameters.m_subDetectorName = "Coil"; + coilParameters.m_subDetectorType = pandora::COIL; + coilParameters.m_innerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_inner_radius"); + coilParameters.m_innerZCoordinate = 0.f; + coilParameters.m_innerPhiCoordinate = 0.f; + coilParameters.m_innerSymmetryOrder = 0; + coilParameters.m_outerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_outer_radius"); + coilParameters.m_outerZCoordinate = gearParameters.getDoubleVal("Coil_cryostat_half_z"); + coilParameters.m_outerPhiCoordinate = 0.f; + coilParameters.m_outerSymmetryOrder = 0; + coilParameters.m_isMirroredInZ = true; + coilParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::COIL] = coilParameters; + std::cout << "End SetMandatorySubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const +{ + std::cout << "Begin SetAdditionalSubDetectorParameters:" << std::endl; + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getEcalPlugParameters(), "ECalPlug", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << " warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getHcalRingParameters(), "HCalRing", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout<< "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLcalParameters(), "LCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLHcalParameters(), "LHCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + std::cout << "End SetAdditionalSubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const +{ + const gear::LayerLayout &layerLayout = inputParameters.getLayerLayout(); + + parameters.m_subDetectorName = subDetectorName; + parameters.m_subDetectorType = subDetectorType; + parameters.m_innerRCoordinate = inputParameters.getExtent()[0]; + parameters.m_innerZCoordinate = inputParameters.getExtent()[2]; + parameters.m_innerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_innerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_outerRCoordinate = inputParameters.getExtent()[1]; + parameters.m_outerZCoordinate = inputParameters.getExtent()[3]; + parameters.m_outerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_outerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_isMirroredInZ = true; + parameters.m_nLayers = layerLayout.getNLayers(); + //std::cout << "m_nLayers="<<layerLayout.getNLayers() << std::endl; + + // ATTN Not always going to be correct for any optional subdetectors, but impact of this is negligible for ILD + const float radiationLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + for (int i = 0; i < layerLayout.getNLayers(); ++i) + { + PandoraApi::Geometry::LayerParameters layerParameters; + layerParameters.m_closestDistanceToIp = layerLayout.getDistance(i) + (0.5 * (layerLayout.getThickness(i) + layerLayout.getAbsorberThickness(i))); + layerParameters.m_nRadiationLengths = radiationLength * layerLayout.getAbsorberThickness(i); + layerParameters.m_nInteractionLengths = interactionLength * layerLayout.getAbsorberThickness(i); + parameters.m_layerParametersVector.push_back(layerParameters); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const +{ + // Set positions of gaps in ILD detector and add information missing from GEAR parameters file + try + { + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + } + catch (gear::Exception &) + { + // aLaVideauGeometry + return this->SetILD_SDHCALSpecificGeometry(subDetectorTypeMap); + } + + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + subDetectorNameMap["HCalRing"].m_innerSymmetryOrder = m_settings.m_hCalRingInnerSymmetryOrder; + subDetectorNameMap["HCalRing"].m_innerPhiCoordinate = m_settings.m_hCalRingInnerPhiCoordinate; + subDetectorNameMap["HCalRing"].m_outerSymmetryOrder = m_settings.m_hCalRingOuterSymmetryOrder; + subDetectorNameMap["HCalRing"].m_outerPhiCoordinate = m_settings.m_hCalRingOuterPhiCoordinate; + + // Gaps in detector active material + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalEndCapBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelConcentricGaps()); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const +{ + // Non-default values (and those missing from GEAR parameters file)... + // The following 2 parameters have no sense for Videau Geometry, set them to 0 + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = 0; + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = 0; + + // Endcap is identical to standard ILD geometry, only HCAL barrel is different + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + // TODO implement gaps between modules + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelBoxGaps() const +{ + const std::string detectorName(_GEAR->getDetectorName()); + + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const unsigned int innerSymmetryOrder(hCalBarrelParameters.getSymmetryOrder()); + const unsigned int outerSymmetryOrder(hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order")); + + if ((0 == innerSymmetryOrder) || (2 != outerSymmetryOrder / innerSymmetryOrder)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float innerRadius(hCalBarrelParameters.getExtent()[0]); + const float outerRadius(hCalBarrelParameters.getExtent()[1]); + const float outerZ(hCalBarrelParameters.getExtent()[3]); + const float phi0(hCalBarrelParameters.getPhi0()); + + const float staveGap(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, phi0, innerRadius, outerRadius, + -outerZ, outerZ, staveGap)); + + const float outerPseudoPhi0(M_PI / static_cast<float>(innerSymmetryOrder)); + const float cosOuterPseudoPhi0(std::cos(outerPseudoPhi0)); + + if ((0 == outerPseudoPhi0) || (0.f == cosOuterPseudoPhi0)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float middleStaveGap(hCalBarrelParameters.getDoubleVal("Hcal_middle_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, outerPseudoPhi0, + innerRadius / cosOuterPseudoPhi0, outerRadius, -outerZ, outerZ, middleStaveGap)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalEndCapBoxGaps() const +{ + const gear::CalorimeterParameters &hCalEndCapParameters = _GEAR->getHcalEndcapParameters(); + + const float staveGap(hCalEndCapParameters.getDoubleVal("Hcal_stave_gaps")); + const float innerRadius(hCalEndCapParameters.getExtent()[0]); + const float outerRadius(hCalEndCapParameters.getExtent()[1]); + const float innerZ(hCalEndCapParameters.getExtent()[2]); + const float outerZ(hCalEndCapParameters.getExtent()[3]); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, innerZ, outerZ, staveGap, + pandora::CartesianVector(-innerRadius, 0, 0))); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, -outerZ, -innerZ, staveGap, + pandora::CartesianVector(innerRadius, 0, 0))); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelConcentricGaps() const +{ + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const float gapWidth(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + + PandoraApi::Geometry::ConcentricGap::Parameters gapParameters; + + gapParameters.m_minZCoordinate = -0.5f * gapWidth; + gapParameters.m_maxZCoordinate = 0.5f * gapWidth; + gapParameters.m_innerRCoordinate = hCalBarrelParameters.getExtent()[0]; + gapParameters.m_innerPhiCoordinate = hCalBarrelParameters.getPhi0(); + gapParameters.m_innerSymmetryOrder = hCalBarrelParameters.getSymmetryOrder(); + gapParameters.m_outerRCoordinate = hCalBarrelParameters.getExtent()[1]; + gapParameters.m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + gapParameters.m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::ConcentricGap::Create(*m_pPandora, gapParameters)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, + float minZ, float maxZ, float gapWidth, pandora::CartesianVector vertexOffset) const +{ + const pandora::CartesianVector basicGapVertex(pandora::CartesianVector(-0.5f * gapWidth, innerRadius, minZ) + vertexOffset); + const pandora::CartesianVector basicSide1(gapWidth, 0, 0); + const pandora::CartesianVector basicSide2(0, outerRadius - innerRadius, 0); + const pandora::CartesianVector basicSide3(0, 0, maxZ - minZ); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + (2. * M_PI * static_cast<float>(i) / static_cast<float>(symmetryOrder)); + const float sinPhi(std::sin(phi)); + const float cosPhi(std::cos(phi)); + + PandoraApi::Geometry::BoxGap::Parameters gapParameters; + + gapParameters.m_vertex = pandora::CartesianVector(cosPhi * basicGapVertex.GetX() + sinPhi * basicGapVertex.GetY(), + -sinPhi * basicGapVertex.GetX() + cosPhi * basicGapVertex.GetY(), basicGapVertex.GetZ()); + gapParameters.m_side1 = pandora::CartesianVector(cosPhi * basicSide1.GetX() + sinPhi * basicSide1.GetY(), + -sinPhi * basicSide1.GetX() + cosPhi * basicSide1.GetY(), basicSide1.GetZ()); + gapParameters.m_side2 = pandora::CartesianVector(cosPhi * basicSide2.GetX() + sinPhi * basicSide2.GetY(), + -sinPhi * basicSide2.GetX() + cosPhi * basicSide2.GetY(), basicSide2.GetZ()); + gapParameters.m_side3 = pandora::CartesianVector(cosPhi * basicSide3.GetX() + sinPhi * basicSide3.GetY(), + -sinPhi * basicSide3.GetX() + cosPhi * basicSide3.GetY(), basicSide3.GetZ()); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::BoxGap::Create(*m_pPandora, gapParameters)); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalEndCapInnerSymmetryOrder(4), + m_eCalEndCapInnerPhiCoordinate(0.f), + m_eCalEndCapOuterSymmetryOrder(8), + m_eCalEndCapOuterPhiCoordinate(0.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_hCalEndCapOuterSymmetryOrder(16), + m_hCalEndCapOuterPhiCoordinate(0.f), + m_hCalRingInnerSymmetryOrder(8), + m_hCalRingInnerPhiCoordinate(0.f), + m_hCalRingOuterSymmetryOrder(16), + m_hCalRingOuterPhiCoordinate(0.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp new file mode 100644 index 00000000..a19788b3 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp @@ -0,0 +1,378 @@ +/** + * @file MarlinPandora/src/MCParticleCreator.cc + * + * @brief Implementation of the mc particle creator class. + * + * $Log: $ + */ + + +#include "edm4hep/MCParticleConst.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/SimCalorimeterHitConst.h" +#include "edm4hep/CaloHitContributionConst.h" +#include "edm4hep/Track.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/SimTrackerHitConst.h" + + +//#include "UTIL/LCRelationNavigator.h" + +//#include "gear/BField.h" + +#include "PandoraPFAlg.h" +//#include "CaloHitCreator.h" +//#include "TrackCreator.h" +#include "MCParticleCreator.h" + +#include <cmath> +#include <limits> +#include <assert.h> + +MCParticleCreator::MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora), + //m_bField(marlin::Global::GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z()) + m_bField(settings.m_bField) +{ +m_id_pMC_map = new std::map<unsigned int, const edm4hep::MCParticle*>; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::~MCParticleCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode MCParticleCreator::CreateMCParticles(const CollectionMaps& collectionMaps ) const +{ + for (StringVector::const_iterator iter = m_settings.m_mcParticleCollections.begin(), iterEnd = m_settings.m_mcParticleCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_MC.find(*iter) == collectionMaps.collectionMap_MC.end()) continue; + try + { + const std::vector<edm4hep::MCParticle>& pMCParticleCollection = (collectionMaps.collectionMap_MC.find(*iter))->second; + std::cout<<"Do CreateMCParticles, collection:"<<(*iter)<<", size="<<pMCParticleCollection.size()<<std::endl; + for (int im = 0; im < pMCParticleCollection.size(); im++) + { + try + { + const edm4hep::MCParticle& pMcParticle = pMCParticleCollection.at(im); + PandoraApi::MCParticle::Parameters mcParticleParameters; + mcParticleParameters.m_energy = sqrt(pMcParticle.getMomentum()[0] * pMcParticle.getMomentum()[0] + pMcParticle.getMomentum()[1] * pMcParticle.getMomentum()[1] + pMcParticle.getMomentum()[2] * pMcParticle.getMomentum()[2] + pMcParticle.getMass() * pMcParticle.getMass()); + mcParticleParameters.m_particleId = pMcParticle.getPDG(); + mcParticleParameters.m_mcParticleType = pandora::MC_3D; + mcParticleParameters.m_pParentAddress = &pMcParticle; + unsigned int p_id = pMcParticle.id(); + const edm4hep::MCParticle* p_mc = &pMcParticle; + //m_id_pMC_map [pMcParticle.id()] = &pMcParticle; + (*m_id_pMC_map) [p_id] = p_mc; + mcParticleParameters.m_momentum = pandora::CartesianVector(pMcParticle.getMomentum()[0], pMcParticle.getMomentum()[1], + pMcParticle.getMomentum()[2]); + mcParticleParameters.m_vertex = pandora::CartesianVector(pMcParticle.getVertex()[0], pMcParticle.getVertex()[1], + pMcParticle.getVertex()[2]); + mcParticleParameters.m_endpoint = pandora::CartesianVector(pMcParticle.getEndpoint()[0], pMcParticle.getEndpoint()[1], + pMcParticle.getEndpoint()[2]); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*m_pPandora, mcParticleParameters)); + + // Create parent-daughter relationships + for(std::vector<edm4hep::ConstMCParticle>::const_iterator itDaughter = pMcParticle.daughters_begin(), + itDaughterEnd = pMcParticle.daughters_end(); itDaughter != itDaughterEnd; ++itDaughter) + { + for (int ida = 0; ida < pMCParticleCollection.size(); ida++) + { + if(pMCParticleCollection.at(ida).id()==(*itDaughter).id()) + { + + const edm4hep::MCParticle& dMcParticle = pMCParticleCollection.at(ida); + if(&pMcParticle == &dMcParticle){std::cout<< "error, mother and daughter are the same mc particle, don't save SetMCParentDaughterRelationship"<<std::endl;} + else PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*m_pPandora, &pMcParticle, &dMcParticle)); + break; + } + } + } + + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract MCParticle: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract MCParticle: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract MCParticles collection: " << *iter << ", " << std::endl; + } + } + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const TrackVector &trackVector) const +{ + for (StringVector::const_iterator iter = m_settings.m_lcTrackRelationCollections.begin(), iterEnd = m_settings.m_lcTrackRelationCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pMCRelationCollection = pLCEvent->getCollection(*iter); + UTIL::LCRelationNavigator navigate(pMCRelationCollection); + + for (TrackVector::const_iterator trackIter = trackVector.begin(), trackIterEnd = trackVector.end(); + trackIter != trackIterEnd; ++trackIter) + { + try + { + EVENT::Track *pTrack = *trackIter; + const EVENT::LCObjectVec &objectVec = navigate.getRelatedToObjects(*trackIter); + + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getPhi(), pTrack->getD0(), pTrack->getZ0(), pTrack->getOmega(), pTrack->getTanLambda(), m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + + // Use momentum magnitude to identify best mc particle + MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + + for (EVENT::LCObjectVec::const_iterator itRel = objectVec.begin(), itRelEnd = objectVec.end(); itRel != itRelEnd; ++itRel) + { + EVENT::MCParticle *pMCParticle = NULL; + pMCParticle = dynamic_cast<MCParticle *>(*itRel); + + if (NULL == pMCParticle) + continue; + + const float trueMomentum(pandora::CartesianVector(pMCParticle->getMomentum()[0], pMCParticle->getMomentum()[1], + pMCParticle->getMomentum()[2]).GetMagnitude()); + + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle = pMCParticle; + bestDeltaMomentum = deltaMomentum; + } + } + + if (NULL == pBestMCParticle) + continue; + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, + pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + streamlog_out(ERROR) << "Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract track to mc particle relationship: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract track to mc particle relationships collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const CalorimeterHitVector &calorimeterHitVector) const +{ + typedef std::map<MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_lcCaloHitRelationCollections.begin(), iterEnd = m_settings.m_lcCaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pMCRelationCollection = pLCEvent->getCollection(*iter); + UTIL::LCRelationNavigator navigate(pMCRelationCollection); + + for (CalorimeterHitVector::const_iterator caloHitIter = calorimeterHitVector.begin(), + caloHitIterEnd = calorimeterHitVector.end(); caloHitIter != caloHitIterEnd; ++caloHitIter) + { + try + { + mcParticleToEnergyWeightMap.clear(); + const EVENT::LCObjectVec &objectVec = navigate.getRelatedToObjects(*caloHitIter); + + for (EVENT::LCObjectVec::const_iterator itRel = objectVec.begin(), itRelEnd = objectVec.end(); itRel != itRelEnd; ++itRel) + { + EVENT::SimCalorimeterHit *pSimHit = dynamic_cast<SimCalorimeterHit *>(*itRel); + + if (NULL == pSimHit) + continue; + + for (int iCont = 0, iEnd = pSimHit->getNMCContributions(); iCont < iEnd; ++iCont) + { + mcParticleToEnergyWeightMap[pSimHit->getParticleCont(iCont)] += pSimHit->getEnergyCont(iCont); + } + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + *caloHitIter, mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + streamlog_out(ERROR) << "Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract calo hit to mc particle relationship: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract calo hit to mc particle relationships collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ + +//-------------- using sim calo hit and digi calo hit, no weight here--------------------------------------------------------------------------------------------------------------- +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const +{ + std::cout<<"Do CreateCaloHitToMCParticleRelationships"<<std::endl; + typedef std::map<const edm4hep::MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_CaloHitRelationCollections.begin(), iterEnd = m_settings.m_CaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloRel.find(*iter) == collectionMaps.collectionMap_CaloRel.end()) continue; + try + { + const std::vector<edm4hep::MCRecoCaloAssociation>& pMCRecoCaloAssociationCollection = (collectionMaps.collectionMap_CaloRel.find(*iter))->second; + + for (unsigned i_calo=0; i_calo < calorimeterHitVector.size(); i_calo++) + { + try + { + mcParticleToEnergyWeightMap.clear(); + for(unsigned ic=0; ic < pMCRecoCaloAssociationCollection.size(); ic++) + { + if( pMCRecoCaloAssociationCollection.at(ic).getRec().id() != (*(calorimeterHitVector.at(i_calo))).id() ) continue; + + const edm4hep::ConstSimCalorimeterHit pSimHit = pMCRecoCaloAssociationCollection.at(ic).getSim(); + for (int iCont = 0, iEnd = pSimHit.contributions_size(); iCont < iEnd; ++iCont) + { + edm4hep::ConstCaloHitContribution conb = pSimHit.getContributions(iCont); + const edm4hep::ConstMCParticle ipa = conb.getParticle(); + float ien = conb.getEnergy(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const edm4hep::MCParticle * p_tmp = (*m_id_pMC_map)[ipa.id()]; + mcParticleToEnergyWeightMap[p_tmp] += ien; + } + + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + calorimeterHitVector.at(i_calo), mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract calo hit to mc particle relationship " << std::endl; + } + } + } + catch (...) + { + std::cout<<"DEBUG5 Failed to extract calo hit to mc particle relationships collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + + +//-------------- using sim tracker hit and tracker hit, no weight here--------------------------------------------------------------------------------------------------------------- +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const +{ + std::cout<<"Do CreateTrackToMCParticleRelationships"<<std::endl; + for (unsigned ik = 0; ik < trackVector.size(); ik++) + { + const edm4hep::Track *pTrack = trackVector.at(ik); + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + // Use momentum magnitude to identify best mc particle + edm4hep::MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + try + { + for (StringVector::const_iterator iter = m_settings.m_TrackRelationCollections.begin(), iterEnd = m_settings.m_TrackRelationCollections.end(); iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_TrkRel.find(*iter) == collectionMaps.collectionMap_TrkRel.end()) continue; + const std::vector<edm4hep::MCRecoTrackerAssociation>& pMCRecoTrackerAssociationCollection = (collectionMaps.collectionMap_TrkRel.find(*iter))->second; + for(unsigned ith=0 ; ith<pTrack->trackerHits_size(); ith++) + { + for(unsigned ic=0; ic < pMCRecoTrackerAssociationCollection.size(); ic++) + { + if( pMCRecoTrackerAssociationCollection.at(ic).getRec().id() != pTrack->getTrackerHits(ith).id() ) continue; + const edm4hep::ConstSimTrackerHit pSimHit = pMCRecoTrackerAssociationCollection.at(ic).getSim(); + const edm4hep::ConstMCParticle ipa = pSimHit.getMCParticle(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const float trueMomentum(pandora::CartesianVector(ipa.getMomentum()[0], ipa.getMomentum()[1], ipa.getMomentum()[2]).GetMagnitude()); + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle =const_cast<edm4hep::MCParticle*>((*m_id_pMC_map)[ipa.id()]); + bestDeltaMomentum = deltaMomentum; + } + } + } + } + + if (NULL == pBestMCParticle) continue; + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract track to mc particle relationship: " << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::Settings::Settings() +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp new file mode 100644 index 00000000..401a6e7a --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp @@ -0,0 +1,910 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "GearSvc/IGearSvc.h" +#include "PandoraPFAlg.h" +#include "EventSeeder/IEventSeeder.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/Vector3d.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CaloHitContribution.h" +#include "edm4hep/ClusterConst.h" +#include "UTIL/ILDConf.h" +#include <cmath> +#include <algorithm> +#include "gear/BField.h" +#include <gear/GEAR.h> + +#include "LCContent.h" + + +pandora::Pandora* PandoraPFAlg::m_pPandora=0; + +DECLARE_COMPONENT( PandoraPFAlg ) + +template<typename T ,typename T1> +StatusCode getCol(T & t, T1 & t1) +{ + try { + t1 = t.get(); + } + catch ( GaudiException &e ) { + std::cout << "Collection " << t.fullKey() << " is unavailable in event " << std::endl; + } + return StatusCode::SUCCESS; +} + + + +PandoraPFAlg::PandoraPFAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + m_CollectionMaps = new CollectionMaps(); + + declareProperty("ReadMCParticle" , m_mcParCol_r, "Handle of the MCParticle input collection" ); + declareProperty("ReadECALBarrel" , m_ECALBarrel_r, "Handle of the ECALBarrel input collection" ); + declareProperty("ReadECALEndcap" , m_ECALEndcap_r, "Handle of the ECALEndcap input collection" ); + declareProperty("ReadECALOther" , m_ECALOther_r, "Handle of the ECALOther input collection" ); + declareProperty("ReadHCALBarrel" , m_HCALBarrel_r, "Handle of the HCALBarrel input collection" ); + declareProperty("ReadHCALEndcap" , m_HCALEndcap_r, "Handle of the HCALEndcap input collection" ); + declareProperty("ReadHCALOther" , m_HCALOther_r, "Handle of the HCALOther input collection" ); + declareProperty("ReadMUON" , m_MUON_r, "Handle of the MUON input collection" ); + declareProperty("ReadLCAL" , m_LCAL_r, "Handle of the LCAL input collection" ); + declareProperty("ReadLHCAL" , m_LHCAL_r, "Handle of the LHCAL input collection" ); + declareProperty("ReadBCAL" , m_BCAL_r, "Handle of the BCAL input collection" ); + declareProperty("ReadKinkVertices" , m_KinkVertices_r, "Handle of the KinkVertices input collection" ); + declareProperty("ReadProngVertices" , m_ProngVertices_r, "Handle of the ProngVertices input collection" ); + declareProperty("ReadSplitVertices" , m_SplitVertices_r, "Handle of the SplitVertices input collection" ); + declareProperty("ReadV0Vertices" , m_V0Vertices_r, "Handle of the V0Vertices input collection" ); + declareProperty("ReadTracks" , m_MarlinTrkTracks_r, "Handle of the Tracks input collection" ); + declareProperty("MCRecoCaloAssociation" , m_MCRecoCaloAssociation_r, "Handle of the MCRecoCaloAssociation input collection" ); + declareProperty("MCRecoTrackerAssociation" , m_MCRecoTrackerAssociation_r, "Handle of the MCRecoTrackerAssociation input collection" ); + declareProperty("WriteClusterCollection" , m_ClusterCollection_w, "Handle of the ClusterCollection output collection" ); + declareProperty("WriteReconstructedParticleCollection", m_ReconstructedParticleCollection_w, "Handle of the ReconstructedParticleCollection output collection" ); + declareProperty("WriteVertexCollection" , m_VertexCollection_w, "Handle of the VertexCollection output collection" ); + +} + + +void PandoraPFAlg::FinaliseSteeringParameters(ISvcLocator* svcloc) +{ + // ATTN: This function seems to be necessary for operations that cannot easily be performed at construction of the processor, + // when the steering file is parsed e.g. the call to GEAR to get the inner bfield + + m_caloHitCreatorSettings.m_absorberRadLengthECal = m_geometryCreatorSettings.m_absorberRadLengthECal; + m_caloHitCreatorSettings.m_absorberIntLengthECal = m_geometryCreatorSettings.m_absorberIntLengthECal; + m_caloHitCreatorSettings.m_absorberRadLengthHCal = m_geometryCreatorSettings.m_absorberRadLengthHCal; + m_caloHitCreatorSettings.m_absorberIntLengthHCal = m_geometryCreatorSettings.m_absorberIntLengthHCal; + m_caloHitCreatorSettings.m_absorberRadLengthOther = m_geometryCreatorSettings.m_absorberRadLengthOther; + m_caloHitCreatorSettings.m_absorberIntLengthOther = m_geometryCreatorSettings.m_absorberIntLengthOther; + + m_caloHitCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder; + m_caloHitCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate; + + m_trackCreatorSettings.m_prongSplitVertexCollections = m_trackCreatorSettings.m_prongVertexCollections; + m_trackCreatorSettings.m_prongSplitVertexCollections.insert(m_trackCreatorSettings.m_prongSplitVertexCollections.end(), + m_trackCreatorSettings.m_splitVertexCollections.begin(), m_trackCreatorSettings.m_splitVertexCollections.end()); + + //m_settings.m_innerBField = marlin::Global::GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + gear::GearMgr* _GEAR = iSvc->getGearMgr(); + m_settings.m_innerBField = _GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + std::cout<<"m_innerBField="<<m_settings.m_innerBField<<std::endl; + m_mcParticleCreatorSettings.m_bField = m_settings.m_innerBField; +} + + + + +StatusCode PandoraPFAlg::initialize() +{ + + std::cout<<"hi init PandoraPFAlg"<<std::endl; + + std::string s_output =m_AnaOutput; + m_fout = new TFile(s_output.c_str(),"RECREATE"); + m_tree = new TTree("evt","tree"); + m_tree->Branch("m_pReco_PID" , &m_pReco_PID); + m_tree->Branch("m_pReco_mass" , &m_pReco_mass); + m_tree->Branch("m_pReco_energy", &m_pReco_energy); + m_tree->Branch("m_pReco_px" , &m_pReco_px); + m_tree->Branch("m_pReco_py" , &m_pReco_py); + m_tree->Branch("m_pReco_pz" , &m_pReco_pz); + m_tree->Branch("m_pReco_charge", &m_pReco_charge); + + m_tree->Branch("m_mc_p_size", &m_mc_p_size); + m_tree->Branch("m_mc_pid" , &m_mc_pid ); + m_tree->Branch("m_mc_mass" , &m_mc_mass ); + m_tree->Branch("m_mc_px" , &m_mc_px ); + m_tree->Branch("m_mc_py" , &m_mc_py ); + m_tree->Branch("m_mc_pz" , &m_mc_pz ); + m_tree->Branch("m_mc_charge", &m_mc_charge); + m_tree->Branch("m_hasConversion", &m_hasConversion); + + // XML file + m_settings.m_pandoraSettingsXmlFile = m_PandoraSettingsXmlFile ; + // Hadronic energy non-linearity correction + m_settings.m_inputEnergyCorrectionPoints = m_InputEnergyCorrectionPoints; + m_settings.m_outputEnergyCorrectionPoints = m_OutputEnergyCorrectionPoints; + // B-field parameters + m_settings.m_muonBarrelBField = m_MuonBarrelBField; + m_settings.m_muonEndCapBField = m_MuonEndCapBField; + + m_trackCreatorSettings.m_trackCollections = m_TrackCollections ; + m_trackCreatorSettings.m_kinkVertexCollections = m_KinkVertexCollections; + m_trackCreatorSettings.m_prongVertexCollections = m_ProngVertexCollections; + m_trackCreatorSettings.m_splitVertexCollections = m_SplitVertexCollections; + m_trackCreatorSettings.m_v0VertexCollections = m_V0VertexCollections; + + m_caloHitCreatorSettings.m_eCalCaloHitCollections = m_ECalCaloHitCollections; + m_caloHitCreatorSettings.m_hCalCaloHitCollections = m_HCalCaloHitCollections; + m_caloHitCreatorSettings.m_lCalCaloHitCollections = m_LCalCaloHitCollections; + m_caloHitCreatorSettings.m_lHCalCaloHitCollections = m_LHCalCaloHitCollections; + m_caloHitCreatorSettings.m_muonCaloHitCollections = m_MuonCaloHitCollections; + m_mcParticleCreatorSettings.m_mcParticleCollections = m_MCParticleCollections; + m_mcParticleCreatorSettings.m_CaloHitRelationCollections = m_RelCaloHitCollections; + m_mcParticleCreatorSettings.m_TrackRelationCollections = m_RelTrackCollections; + + + // Absorber properties + m_geometryCreatorSettings.m_absorberRadLengthECal = m_AbsorberRadLengthECal; + m_geometryCreatorSettings.m_absorberIntLengthECal = m_AbsorberIntLengthECal; + m_geometryCreatorSettings.m_absorberRadLengthHCal = m_AbsorberRadLengthHCal; + m_geometryCreatorSettings.m_absorberIntLengthHCal = m_AbsorberIntLengthHCal; + m_geometryCreatorSettings.m_absorberRadLengthOther = m_AbsorberRadLengthOther; + m_geometryCreatorSettings.m_absorberIntLengthOther = m_AbsorberIntLengthOther; + + // Name of PFO collection written by GaudiPandora + + m_pfoCreatorSettings.m_clusterCollectionName = m_ClusterCollectionName;// not used + m_pfoCreatorSettings.m_pfoCollectionName = m_PFOCollectionName;// + m_pfoCreatorSettings.m_startVertexCollectionName = m_StartVertexCollectionName; // + m_pfoCreatorSettings.m_startVertexAlgName = m_StartVertexAlgorithmName;// + + m_pfoCreatorSettings.m_emStochasticTerm = m_EMStochasticTerm; + m_pfoCreatorSettings.m_hadStochasticTerm = m_HadStochasticTerm; + m_pfoCreatorSettings.m_emConstantTerm = m_EMConstantTerm; + m_pfoCreatorSettings.m_hadConstantTerm = m_HadConstantTerm; + + // Calibration constants + m_caloHitCreatorSettings.m_eCalToMip = m_ECalToMipCalibration; + m_caloHitCreatorSettings.m_hCalToMip = m_HCalToMipCalibration; + m_caloHitCreatorSettings.m_eCalMipThreshold = m_ECalMipThreshold; + m_caloHitCreatorSettings.m_muonToMip = m_MuonToMipCalibration; + m_caloHitCreatorSettings.m_hCalMipThreshold = m_HCalMipThreshold; + m_caloHitCreatorSettings.m_eCalToEMGeV = m_ECalToEMGeVCalibration; + m_caloHitCreatorSettings.m_hCalToEMGeV = m_HCalToEMGeVCalibration; + m_caloHitCreatorSettings.m_eCalToHadGeVEndCap = m_ECalToHadGeVCalibrationEndCap; + m_caloHitCreatorSettings.m_eCalToHadGeVBarrel = m_ECalToHadGeVCalibrationBarrel; + m_caloHitCreatorSettings.m_hCalToHadGeV = m_HCalToHadGeVCalibration; + m_caloHitCreatorSettings.m_muonDigitalHits = m_DigitalMuonHits; + m_caloHitCreatorSettings.m_muonHitEnergy = m_MuonHitEnergy; + m_caloHitCreatorSettings.m_maxHCalHitHadronicEnergy = m_MaxHCalHitHadronicEnergy; + m_caloHitCreatorSettings.m_nOuterSamplingLayers = m_NOuterSamplingLayers; + m_caloHitCreatorSettings.m_layersFromEdgeMaxRearDistance = m_LayersFromEdgeMaxRearDistance; + + // Track relationship parameters + m_trackCreatorSettings.m_shouldFormTrackRelationships = m_ShouldFormTrackRelationships; + // Initial track hit specifications + m_trackCreatorSettings.m_minTrackHits = m_MinTrackHits; + m_trackCreatorSettings.m_minFtdTrackHits = m_MinFtdTrackHits; + m_trackCreatorSettings.m_maxTrackHits = m_MaxTrackHits; + ////m_trackCreatorSettings.m_useOldTrackStateCalculation = m_UseOldTrackStateCalculation; + // Track PFO usage parameters + m_trackCreatorSettings.m_d0TrackCut = m_D0TrackCut; + m_trackCreatorSettings.m_z0TrackCut = m_Z0TrackCut; + m_trackCreatorSettings.m_usingNonVertexTracks = m_UseNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedNonVertexTracks = m_UseUnmatchedNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedVertexTracks = m_UseUnmatchedVertexTracks; + m_trackCreatorSettings.m_unmatchedVertexTrackMaxEnergy = m_UnmatchedVertexTrackMaxEnergy; + m_trackCreatorSettings.m_d0UnmatchedVertexTrackCut = m_D0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_z0UnmatchedVertexTrackCut = m_Z0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_zCutForNonVertexTracks = m_ZCutForNonVertexTracks; + // Track "reaches ecal" parameters + m_trackCreatorSettings.m_reachesECalNTpcHits = m_ReachesECalNTpcHits; + m_trackCreatorSettings.m_reachesECalNFtdHits = m_ReachesECalNFtdHits; + m_trackCreatorSettings.m_reachesECalTpcOuterDistance = m_ReachesECalTpcOuterDistance; + m_trackCreatorSettings.m_reachesECalMinFtdLayer = m_ReachesECalMinFtdLayer; + m_trackCreatorSettings.m_reachesECalTpcZMaxDistance = m_ReachesECalTpcZMaxDistance; + m_trackCreatorSettings.m_reachesECalFtdZMaxDistance = m_ReachesECalFtdZMaxDistance; + m_trackCreatorSettings.m_curvatureToMomentumFactor = m_CurvatureToMomentumFactor; + m_trackCreatorSettings.m_minTrackECalDistanceFromIp = m_MinTrackECalDistanceFromIp; + // Final track quality parameters + m_trackCreatorSettings.m_maxTrackSigmaPOverP = m_MaxTrackSigmaPOverP; + m_trackCreatorSettings.m_minMomentumForTrackHitChecks = m_MinMomentumForTrackHitChecks; + m_trackCreatorSettings.m_tpcMembraneMaxZ = m_TpcMembraneMaxZ; + m_trackCreatorSettings.m_minTpcHitFractionOfExpected = m_MinTpcHitFractionOfExpected; + m_trackCreatorSettings.m_minFtdHitsForTpcHitFraction = m_MinFtdHitsForTpcHitFraction; + m_trackCreatorSettings.m_maxTpcInnerRDistance = m_MaxTpcInnerRDistance; + + + // Additional geometry parameters + m_geometryCreatorSettings.m_eCalEndCapInnerSymmetryOrder = m_ECalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapInnerPhiCoordinate = m_ECalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_eCalEndCapOuterSymmetryOrder = m_ECalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapOuterPhiCoordinate = m_ECalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_HCalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_HCalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapOuterSymmetryOrder = m_HCalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapOuterPhiCoordinate = m_HCalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingInnerSymmetryOrder = m_HCalRingInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingInnerPhiCoordinate = m_HCalRingInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingOuterSymmetryOrder = m_HCalRingOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingOuterPhiCoordinate = m_HCalRingOuterPhiCoordinate; + + // For Strip Splitting method and also for hybrid ECAL + m_caloHitCreatorSettings.m_stripSplittingOn = m_StripSplittingOn; + m_caloHitCreatorSettings.m_useEcalScLayers = m_UseEcalScLayers; + // Parameters for hybrid ECAL + // Energy to MIP for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToMip = m_ECalSiToMipCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToMip = m_ECalScToMipCalibration; + // MipThreshold for Si-layers and Sc-layers, respectively. + // Si + m_caloHitCreatorSettings.m_eCalSiMipThreshold = m_ECalSiMipThreshold; + //Sc + m_caloHitCreatorSettings.m_eCalScMipThreshold = m_ECalScMipThreshold; + // EcalToEM for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToEMGeV = m_ECalSiToEMGeVCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToEMGeV = m_ECalScToEMGeVCalibration; + // EcalToHad for Si-layers and Sc-layers of the endcaps, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVEndCap = m_ECalSiToHadGeVCalibrationEndCap; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVEndCap = m_ECalScToHadGeVCalibrationEndCap; + // EcalToHad for Si-layers and Sc-layers of the barrel, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVBarrel = m_ECalSiToHadGeVCalibrationBarrel; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVBarrel = m_ECalScToHadGeVCalibrationBarrel; + + try + { + ISvcLocator* svcloc = serviceLocator(); + this->FinaliseSteeringParameters(svcloc); + m_pPandora = new pandora::Pandora(); + m_pMCParticleCreator = new MCParticleCreator(m_mcParticleCreatorSettings, m_pPandora); + m_pGeometryCreator = new GeometryCreator(m_geometryCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pGeometryCreator->CreateGeometry(svcloc)); + m_pCaloHitCreator = new CaloHitCreator(m_caloHitCreatorSettings, m_pPandora, svcloc, 0); + m_pTrackCreator = new TrackCreator(m_trackCreatorSettings, m_pPandora, svcloc); + m_pPfoCreator = new PfoCreator(m_pfoCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->RegisterUserComponents()); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*m_pPandora, m_settings.m_pandoraSettingsXmlFile)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to initialize gaudi pandora: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Failed to initialize gaudi pandora: unrecognized exception" << std::endl; + throw; + } + + + return GaudiAlgorithm::initialize(); +} + +StatusCode PandoraPFAlg::execute() +{ + /* + if (_nEvt < m_settings.m_nEventsToSkip) + { + _nEvt++; + return StatusCode::SUCCESS; + } + */ + + try + { + std::cout<<"execute PandoraPFAlg"<<std::endl; + + updateMap(); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateMCParticles(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pCaloHitCreator->CreateCaloHits(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateCaloHitToMCParticleRelationships(*m_CollectionMaps, m_pCaloHitCreator->GetCalorimeterHitVector() )); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTrackAssociations(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTracks(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateTrackToMCParticleRelationships(*m_CollectionMaps, m_pTrackCreator->GetTrackVector() )); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pPandora)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pPfoCreator->CreateParticleFlowObjects(*m_CollectionMaps, m_ClusterCollection_w, m_ReconstructedParticleCollection_w, m_VertexCollection_w)); + + StatusCode sc0 = CreateMCRecoParticleAssociation(); + StatusCode sc = Ana(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pPandora)); + this->Reset(); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Gaudi pandora failed to process event: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Gaudi pandora failed to process event: unrecognized exception" << std::endl; + throw; + } + + info() << "PandoraPFAlg Processed " << _nEvt << " events " << endmsg; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode PandoraPFAlg::finalize() +{ + info() << "Finalized. Processed " << _nEvt << " events " <<",saved tree with entries="<<m_tree->GetEntries()<< endmsg; + m_fout->cd(); + m_tree->Write(); + m_fout->Close(); + delete m_pPandora; + delete m_pGeometryCreator; + delete m_pCaloHitCreator; + delete m_pTrackCreator; + delete m_pMCParticleCreator; + delete m_pPfoCreator; + return GaudiAlgorithm::finalize(); +} + + + + +pandora::StatusCode PandoraPFAlg::RegisterUserComponents() const +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterAlgorithms(*m_pPandora)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBasicPlugins(*m_pPandora)); + + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBFieldPlugin(*m_pPandora, + m_settings.m_innerBField, m_settings.m_muonBarrelBField, m_settings.m_muonEndCapBField)); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterNonLinearityEnergyCorrection(*m_pPandora, + "NonLinearity", pandora::HADRONIC, m_settings.m_inputEnergyCorrectionPoints, m_settings.m_outputEnergyCorrectionPoints)); + + + /* + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::RegisterAlgorithmFactory(*m_pPandora, + "ExternalClustering", new ExternalClusteringAlgorithm::Factory)); + */ + + return pandora::STATUS_CODE_SUCCESS; +} + + +void PandoraPFAlg::Reset() +{ + m_pCaloHitCreator->Reset(); + m_pTrackCreator->Reset(); + m_pMCParticleCreator->Reset(); + + std::vector<int>() .swap(m_pReco_PID ); + std::vector<float>().swap(m_pReco_mass); + std::vector<float>().swap(m_pReco_energy); + std::vector<float>().swap(m_pReco_px); + std::vector<float>().swap(m_pReco_py); + std::vector<float>().swap(m_pReco_pz); + std::vector<float>().swap(m_pReco_charge); + + std::vector<int>() .swap(m_mc_p_size); + std::vector<int>() .swap(m_mc_pid ); + std::vector<float>().swap(m_mc_mass ); + std::vector<float>().swap(m_mc_px ); + std::vector<float>().swap(m_mc_py ); + std::vector<float>().swap(m_mc_pz ); + std::vector<float>().swap(m_mc_charge); + m_hasConversion = 0; + + m_CollectionMaps->clear(); +} + +const pandora::Pandora *PandoraPFAlg::GetPandora() const +{ + if (NULL == m_pPandora) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return m_pPandora; +} +PandoraPFAlg::Settings::Settings() : + m_innerBField(3.5f), + m_muonBarrelBField(-1.5f), + m_muonEndCapBField(0.01f) +{ +} +CollectionMaps::CollectionMaps() +{ +} +void CollectionMaps::clear() +{ +CollectionMap_MC.clear(); +CollectionMap_CaloHit.clear(); +CollectionMap_Vertex.clear(); +CollectionMap_Track.clear(); +collectionMap_MC.clear(); +collectionMap_CaloHit.clear(); +collectionMap_Vertex.clear(); +collectionMap_Track.clear(); +collectionMap_CaloRel.clear(); +collectionMap_TrkRel.clear(); +} + +StatusCode PandoraPFAlg::updateMap() +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + m_CollectionMaps->CollectionMap_MC ["MCParticle"] = MCParticle ; + m_CollectionMaps->collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) m_CollectionMaps->collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALBarrel"] = ECALBarrel ; + m_CollectionMaps->collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALEndcap"] = ECALEndcap ; + m_CollectionMaps->collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALOther"] = ECALOther ; + m_CollectionMaps->collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALBarrel"] = HCALBarrel ; + m_CollectionMaps->collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALEndcap"] = HCALEndcap ; + m_CollectionMaps->collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALOther"] = HCALOther ; + m_CollectionMaps->collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["MUON"] = MUON ; + m_CollectionMaps->collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["LCAL"] = LCAL ; + m_CollectionMaps->collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["LHCAL"] = LHCAL ; + m_CollectionMaps->collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["BCAL"] = BCAL ; + m_CollectionMaps->collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["KinkVertices"] = KinkVertices ; + m_CollectionMaps->collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["ProngVertices"] = ProngVertices ; + m_CollectionMaps->collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["SplitVertices"] = SplitVertices ; + m_CollectionMaps->collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["V0Vertices"] = V0Vertices ; + m_CollectionMaps->collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + m_CollectionMaps->CollectionMap_Track["MarlinTrkTracks"] = MarlinTrkTracks ; + m_CollectionMaps->collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) m_CollectionMaps->collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel["RecoCaloAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) m_CollectionMaps->collectionMap_CaloRel ["RecoCaloAssociation"].push_back(mcRecoCaloAssociation->at(i)); + } + else + { + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + if(MCParticle->at(i).parents_size()==0) + { + std::cout<<"create recoCaloAssociation by hand now"<<std::endl; + for(std::map<std::string, std::vector<edm4hep::CalorimeterHit> >::iterator iter = m_CollectionMaps->collectionMap_CaloHit.begin(); iter != m_CollectionMaps->collectionMap_CaloHit.end(); iter++) + { + std::string prefix = "RecoCaloAssociation_"; + std::string key = prefix + iter->first; + std::cout<<"create for "<<key<<std::endl; + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel[key] = v_cal ; + for(std::vector<edm4hep::CalorimeterHit>::iterator it=iter->second.begin(); it != iter->second.end(); it ++) + { + edm4hep::SimCalorimeterHit sim_hit( it->getCellID(), it->getEnergy(), it->getPosition() ); + edm4hep::CaloHitContribution conb ( MCParticle->at(i).getPDG(), it->getEnergy(), 0, it->getPosition() ); + conb.setParticle( MCParticle->at(i) ); + sim_hit.addContribution(conb); + edm4hep::MCRecoCaloAssociation calo_association; + calo_association.setRec(*it); + calo_association.setSim(sim_hit); + m_CollectionMaps->collectionMap_CaloRel[key].push_back(calo_association); + } + } + break; + } + } + } + } + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + m_CollectionMaps->collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) m_CollectionMaps->collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + +StatusCode PandoraPFAlg::updateMap(CollectionMaps & tmp_map) +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation ); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + tmp_map.CollectionMap_MC ["MCParticle"] = MCParticle ; + tmp_map.collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) tmp_map.collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALBarrel"] = ECALBarrel ; + tmp_map.collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) tmp_map.collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALEndcap"] = ECALEndcap ; + tmp_map.collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) tmp_map.collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALOther"] = ECALOther ; + tmp_map.collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) tmp_map.collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALBarrel"] = HCALBarrel ; + tmp_map.collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) tmp_map.collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALEndcap"] = HCALEndcap ; + tmp_map.collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) tmp_map.collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALOther"] = HCALOther ; + tmp_map.collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) tmp_map.collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["MUON"] = MUON ; + tmp_map.collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) tmp_map.collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["LCAL"] = LCAL ; + tmp_map.collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) tmp_map.collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["LHCAL"] = LHCAL ; + tmp_map.collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) tmp_map.collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["BCAL"] = BCAL ; + tmp_map.collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) tmp_map.collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["KinkVertices"] = KinkVertices ; + tmp_map.collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) tmp_map.collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["ProngVertices"] = ProngVertices ; + tmp_map.collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) tmp_map.collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["SplitVertices"] = SplitVertices ; + tmp_map.collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) tmp_map.collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["V0Vertices"] = V0Vertices ; + tmp_map.collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) tmp_map.collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + tmp_map.CollectionMap_Track["MarlinTrkTracks"] = MarlinTrkTracks ; + tmp_map.collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) tmp_map.collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + tmp_map.collectionMap_CaloRel["RecoCaloAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) tmp_map.collectionMap_CaloRel ["RecoCaloAssociation"].push_back(mcRecoCaloAssociation->at(i)); + } + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + tmp_map.collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) tmp_map.collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + +StatusCode PandoraPFAlg::Ana() +{ + int n_current = m_tree->GetEntries()+1; + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + const edm4hep::MCRecoParticleAssociationCollection* reco_associa_col = m_MCRecoParticleAssociation_w.get(); + std::cout<<"reco_col size="<<reco_col->size()<<std::endl; + for(int i=0; i<reco_col->size();i++) + { + std::cout<<"reco="<<i<<std::endl; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + const float px = pReco.getMomentum()[0]; + const float py = pReco.getMomentum()[1]; + const float pz = pReco.getMomentum()[2]; + const float energy = pReco.getEnergy(); + const float mass = pReco.getMass(); + const float charge = pReco.getCharge(); + const int type = pReco.getType(); + //std::cout<<"MYDBUG evt="<<n_current<<",rec i="<<i<<",particleId="<<type<<",mass="<<mass<<",charge="<<charge<<",energy="<<energy<<",px="<<px<<",py="<<py<<",pz="<<pz<<std::endl; + m_pReco_PID.push_back(type); + m_pReco_mass.push_back(mass); + m_pReco_charge.push_back(charge); + m_pReco_energy.push_back(energy); + m_pReco_px.push_back(px); + m_pReco_py.push_back(py); + m_pReco_pz.push_back(pz); + for(int j=0; j < reco_associa_col->size(); j++) + { + if(reco_associa_col->at(j).getRec().id() != pReco.id() ) continue; + std::cout<<"MC pid ="<<reco_associa_col->at(j).getSim().getPDG()<<", px="<<reco_associa_col->at(j).getSim().getMomentum()[0]<<", py="<<reco_associa_col->at(j).getSim().getMomentum()[1]<<",pz="<<reco_associa_col->at(j).getSim().getMomentum()[2]<<std::endl; + } + } + const edm4hep::MCParticleCollection* MCParticle = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + m_mc_p_size.push_back(MCParticle->at(i).parents_size()); + m_mc_pid .push_back(MCParticle->at(i).getPDG()); + m_mc_mass .push_back(MCParticle->at(i).getMass()); + m_mc_px .push_back(MCParticle->at(i).getMomentum()[0]); + m_mc_py .push_back(MCParticle->at(i).getMomentum()[1]); + m_mc_pz .push_back(MCParticle->at(i).getMomentum()[2]); + m_mc_charge.push_back(MCParticle->at(i).getCharge()); + //for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) da_pids.push_back( MCParticle->at(i).getDaughters(j).getPDG()); + if(MCParticle->at(i).parents_size()==0) std::cout<<"MYDBUG evt="<<n_current<<", mc i="<<i<<",px="<<MCParticle->at(i).getMomentum()[0]<<",py="<<MCParticle->at(i).getMomentum()[1]<<",pz="<<MCParticle->at(i).getMomentum()[2]<<std::endl; + if (MCParticle->at(i).getPDG() != 22) continue; + int hasEm = 0; + int hasEp = 0; + for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) + { + if (MCParticle->at(i).getDaughters(j).getPDG() == 11 ) hasEm=1; + else if (MCParticle->at(i).getDaughters(j).getPDG() == -11 ) hasEp=1; + } + if(hasEm && hasEp) m_hasConversion=1; + } + } + m_tree->Fill(); + return StatusCode::SUCCESS; +} + +// create simple MCRecoParticleAssociation using calorimeter hit only +StatusCode PandoraPFAlg::CreateMCRecoParticleAssociation() +{ + edm4hep::MCRecoParticleAssociationCollection* pMCRecoParticleAssociationCollection = m_MCRecoParticleAssociation_w.createAndPut(); + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + std::cout<<"CreateMCRecoParticleAssociation, reco_col size="<<reco_col->size()<<std::endl; + for(int i=0; i<reco_col->size();i++) + { + std::map<int, edm4hep::ConstMCParticle> mc_map; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + for(int j=0; j < pReco.clusters_size(); j++) + { + edm4hep::ConstCluster cluster = pReco.getClusters(j); + for(int k=0; k < cluster.hits_size(); k++) + { + edm4hep::ConstCalorimeterHit hit = cluster.getHits(k); + for(std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> >::iterator iter = m_CollectionMaps->collectionMap_CaloRel.begin(); iter != m_CollectionMaps->collectionMap_CaloRel.end(); iter++) + { + for(std::vector<edm4hep::MCRecoCaloAssociation>::iterator it = iter->second.begin(); it != iter->second.end(); it ++) + { + if(it->getRec().id() != hit.id()) continue; + for(std::vector<edm4hep::ConstCaloHitContribution>::const_iterator itc = it->getSim().contributions_begin(); itc != it->getSim().contributions_end(); itc++) + { + if(mc_map.find(itc->getParticle().id()) == mc_map.end()) mc_map[itc->getParticle().id()] = itc->getParticle() ; + } + } + } + } + } + for(std::map<int, edm4hep::ConstMCParticle>::iterator it = mc_map.begin(); it != mc_map.end(); it ++) + { + edm4hep::MCRecoParticleAssociation association = pMCRecoParticleAssociationCollection->create(); + association.setRec(pReco); + association.setSim(it->second); + } + } + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp new file mode 100644 index 00000000..a3d35da1 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp @@ -0,0 +1,429 @@ +/** + * @file MarlinPandora/src/PfoCreator.cc + * + * @brief Implementation of the pfo creator class. + * + * $Log: $ + */ + +//#include "CalorimeterHitType.h" + +#include "Api/PandoraApi.h" + +#include "Objects/Cluster.h" +#include "Objects/ParticleFlowObject.h" +#include "Objects/Track.h" + +#include "Pandora/PdgTable.h" +#include "PfoCreator.h" +#include "PandoraPFAlg.h" + +#include <algorithm> +#include <cmath> + +PfoCreator::PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::~PfoCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection) +{ + m_collectionMaps = &collectionMaps; + edm4hep::ClusterCollection* pClusterCollection = _pClusterCollection.createAndPut(); + edm4hep::ReconstructedParticleCollection* pReconstructedParticleCollection = _pReconstructedParticleCollection.createAndPut(); + edm4hep::VertexCollection* pStartVertexCollection = _pStartVertexCollection.createAndPut(); + + const pandora::PfoList *pPandoraPfoList = NULL; + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pPandora, pPandoraPfoList)); + + + //IMPL::LCFlagImpl lcFlagImpl(pClusterCollection->getFlag()); + //lcFlagImpl.setBit(LCIO::CLBIT_HITS); + //pClusterCollection->setFlag(lcFlagImpl.getFlag()); + + pandora::StringVector subDetectorNames; + this->InitialiseSubDetectorNames(subDetectorNames); + //pClusterCollection->parameters().setValues("ClusterSubdetectorNames", subDetectorNames); + + // Create lcio "reconstructed particles" from the pandora "particle flow objects" + std::cout<<"pPandoraPfoList size="<<pPandoraPfoList->size()<<std::endl; + for (pandora::PfoList::const_iterator pIter = pPandoraPfoList->begin(), pIterEnd = pPandoraPfoList->end(); pIter != pIterEnd; ++pIter) + { + const pandora::ParticleFlowObject *const pPandoraPfo(*pIter); + //IMPL::ReconstructedParticleImpl *const pReconstructedParticle(new ReconstructedParticleImpl()); + edm4hep::ReconstructedParticle pReconstructedParticle0 = pReconstructedParticleCollection->create(); + edm4hep::ReconstructedParticle* pReconstructedParticle = &pReconstructedParticle0; + + const bool hasTrack(!pPandoraPfo->GetTrackList().empty()); + const pandora::ClusterList &clusterList(pPandoraPfo->GetClusterList()); + + //std::cout<<"ClusterList size="<<clusterList.size()<<std::endl; + float clustersTotalEnergy(0.f); + pandora::CartesianVector referencePoint(0.f, 0.f, 0.f), clustersWeightedPosition(0.f, 0.f, 0.f); + for (pandora::ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter) + { + const pandora::Cluster *const pPandoraCluster(*cIter); + pandora::CaloHitList pandoraCaloHitList; + pPandoraCluster->GetOrderedCaloHitList().FillCaloHitList(pandoraCaloHitList); + pandoraCaloHitList.insert(pandoraCaloHitList.end(), pPandoraCluster->GetIsolatedCaloHitList().begin(), pPandoraCluster->GetIsolatedCaloHitList().end()); + + pandora::FloatVector hitE, hitX, hitY, hitZ; + //IMPL::ClusterImpl *const p_Cluster(new ClusterImpl()); + edm4hep::Cluster p_Cluster0 = pClusterCollection->create(); + edm4hep::Cluster* p_Cluster = &p_Cluster0; + this->SetClusterSubDetectorEnergies(subDetectorNames, p_Cluster, pandoraCaloHitList, hitE, hitX, hitY, hitZ); + + float clusterCorrectEnergy(0.f); + this->SetClusterEnergyAndError(pPandoraPfo, pPandoraCluster, p_Cluster, clusterCorrectEnergy); + + pandora::CartesianVector clusterPosition(0.f, 0.f, 0.f); + const unsigned int nHitsInCluster(pandoraCaloHitList.size()); + this->SetClusterPositionAndError(nHitsInCluster, hitE, hitX, hitY, hitZ, p_Cluster, clusterPosition); + + if (!hasTrack) + { + clustersWeightedPosition += clusterPosition * clusterCorrectEnergy; + clustersTotalEnergy += clusterCorrectEnergy; + } + + //pClusterCollection->addElement(p_Cluster); + edm4hep::ConstCluster p_ClusterCon = *p_Cluster; + pReconstructedParticle->addCluster(p_ClusterCon); + } + + if (!hasTrack) + { + if (clustersTotalEnergy < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CreateParticleFlowObjects: invalid cluster energy " << clustersTotalEnergy << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = clustersWeightedPosition * (1.f / clustersTotalEnergy); + } + } + else + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CalculateTrackBasedReferencePoint(pPandoraPfo, referencePoint)); + } + + this->SetRecoParticleReferencePoint(referencePoint, pReconstructedParticle); + this->AddTracksToRecoParticle(pPandoraPfo, pReconstructedParticle); + this->SetRecoParticlePropertiesFromPFO(pPandoraPfo, pReconstructedParticle); + + edm4hep::Vertex pStartVertex0 = pStartVertexCollection->create(); + edm4hep::Vertex* pStartVertex = &pStartVertex0; + //pStartVertex->setAlgorithmType(m_settings.m_startVertexAlgName.c_str()); + pStartVertex->setAlgorithmType(0); + const float ref_value[3] = {referencePoint.GetX(),referencePoint.GetY(),referencePoint.GetZ()}; + pStartVertex->setPosition(edm4hep::Vector3f(ref_value)); + pStartVertex->setAssociatedParticle(*pReconstructedParticle); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const +{ + subDetectorNames.push_back("ecal"); + subDetectorNames.push_back("hcal"); + subDetectorNames.push_back("yoke"); + subDetectorNames.push_back("lcal"); + subDetectorNames.push_back("lhcal"); + subDetectorNames.push_back("bcal"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const p_Cluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const +{ + for (pandora::CaloHitList::const_iterator hIter = pandoraCaloHitList.begin(), hIterEnd = pandoraCaloHitList.end(); hIter != hIterEnd; ++hIter) + { + const pandora::CaloHit *const pPandoraCaloHit(*hIter); + edm4hep::CalorimeterHit *const pCalorimeterHit0 = (edm4hep::CalorimeterHit*)(pPandoraCaloHit->GetParentAddress()); + const edm4hep::CalorimeterHit pCalorimeterHit = *pCalorimeterHit0; + + p_Cluster->addHit(pCalorimeterHit); + + const float caloHitEnergy(pCalorimeterHit.getEnergy()); + hitE.push_back(caloHitEnergy); + hitX.push_back(pCalorimeterHit.getPosition()[0]); + hitY.push_back(pCalorimeterHit.getPosition()[1]); + hitZ.push_back(pCalorimeterHit.getPosition()[2]); + /* + std::vector<float> &subDetectorEnergies = p_Cluster->subdetectorEnergies(); + subDetectorEnergies.resize(subDetectorNames.size()); + + switch (CHT(pCalorimeterHit->getType()).caloID()) + { + case CHT::ecal: subDetectorEnergies[ECAL_INDEX ] += caloHitEnergy; break; + case CHT::hcal: subDetectorEnergies[HCAL_INDEX ] += caloHitEnergy; break; + case CHT::yoke: subDetectorEnergies[YOKE_INDEX ] += caloHitEnergy; break; + case CHT::lcal: subDetectorEnergies[LCAL_INDEX ] += caloHitEnergy; break; + case CHT::lhcal: subDetectorEnergies[LHCAL_INDEX] += caloHitEnergy; break; + case CHT::bcal: subDetectorEnergies[BCAL_INDEX ] += caloHitEnergy; break; + default: streamlog_out(WARNING) << "PfoCreator::SetClusterSubDetectorEnergies: no subdetector found for hit with type: " << pCalorimeterHit->getType() << std::endl; + } + */ + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const p_Cluster, float &clusterCorrectEnergy) const +{ + const bool isEmShower((pandora::PHOTON == pPandoraPfo->GetParticleId()) || (pandora::E_MINUS == std::abs(pPandoraPfo->GetParticleId()))); + clusterCorrectEnergy = (isEmShower ? pPandoraCluster->GetCorrectedElectromagneticEnergy(*m_pPandora) : pPandoraCluster->GetCorrectedHadronicEnergy(*m_pPandora)); + + if (clusterCorrectEnergy < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + + const float stochasticTerm(isEmShower ? m_settings.m_emStochasticTerm : m_settings.m_hadStochasticTerm); + const float constantTerm(isEmShower ? m_settings.m_emConstantTerm : m_settings.m_hadConstantTerm); + const float energyError(std::sqrt(stochasticTerm * stochasticTerm / clusterCorrectEnergy + constantTerm * constantTerm) * clusterCorrectEnergy); + + p_Cluster->setEnergy(clusterCorrectEnergy); + p_Cluster->setEnergyError(energyError); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const p_Cluster, pandora::CartesianVector &clusterPositionVec) const +{ + ClusterShapes *const pClusterShapes(new ClusterShapes(nHitsInCluster, hitE.data(), hitX.data(), hitY.data(), hitZ.data())); + + try + { + p_Cluster->setPhi(std::atan2(pClusterShapes->getEigenVecInertia()[1], pClusterShapes->getEigenVecInertia()[0])); + p_Cluster->setITheta(std::acos(pClusterShapes->getEigenVecInertia()[2])); + p_Cluster->setPosition(pClusterShapes->getCentreOfGravity()); + //ATTN these two lines below would only compile with ilcsoft HEAD V2015-10-13 and above + //p_Cluster->setPositionError(pClusterShapes->getCenterOfGravityErrors()); + //p_Cluster->setDirectionError(pClusterShapes->getEigenVecInertiaErrors()); + clusterPositionVec.SetValues(pClusterShapes->getCentreOfGravity()[0], pClusterShapes->getCentreOfGravity()[1], pClusterShapes->getCentreOfGravity()[2]); + } + catch (...) + { + std::cout<<"WARNING PfoCreator::SetClusterPositionAndError: unidentified exception caught." << std::endl; + } + + delete pClusterShapes; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + float totalTrackMomentumAtDca(0.f), totalTrackMomentumAtStart(0.f); + pandora::CartesianVector referencePointAtDCAWeighted(0.f, 0.f, 0.f), referencePointAtStartWeighted(0.f, 0.f, 0.f); + + bool hasSiblings(false); + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pPandoraTrack(*tIter); + + if (!this->IsValidParentTrack(pPandoraTrack, trackList)) + continue; + + if (this->HasValidSiblingTrack(pPandoraTrack, trackList)) + { + // Presence of sibling tracks typically represents a conversion + const pandora::CartesianVector &trackStartPoint((pPandoraTrack->GetTrackStateAtStart()).GetPosition()); + const float trackStartMomentum(((pPandoraTrack->GetTrackStateAtStart()).GetMomentum()).GetMagnitude()); + referencePointAtStartWeighted += trackStartPoint * trackStartMomentum; + totalTrackMomentumAtStart += trackStartMomentum; + hasSiblings = true; + } + else + { + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pPandoraTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + + const float z0(pPandoraTrack->GetZ0()); + pandora::CartesianVector intersectionPoint(0.f, 0.f, 0.f); + + //intersectionPoint.SetValues(pLcioTrack->getD0() * std::cos(pLcioTrack->getPhi()), pLcioTrack->getD0() * std::sin(pLcioTrack->getPhi()), z0); + if(pLcioTrack.trackStates_size()==0) throw "zero trackStates size find"; + intersectionPoint.SetValues(pLcioTrack.getTrackStates(0).D0 * std::cos(pLcioTrack.getTrackStates(0).phi), pLcioTrack.getTrackStates(0).D0 * std::sin(pLcioTrack.getTrackStates(0).phi), z0); + const float trackMomentumAtDca((pPandoraTrack->GetMomentumAtDca()).GetMagnitude()); + referencePointAtDCAWeighted += intersectionPoint * trackMomentumAtDca; + totalTrackMomentumAtDca += trackMomentumAtDca; + } + } + + if (hasSiblings) + { + if (totalTrackMomentumAtStart < std::numeric_limits<float>::epsilon()) + { + std::cout<<" WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtStart << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtStartWeighted * (1.f / totalTrackMomentumAtStart); + } + } + else + { + if (totalTrackMomentumAtDca < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtDca << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtDCAWeighted * (1.f / totalTrackMomentumAtDca); + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &parentTrackList(pPandoraTrack->GetParentList()); + + for (pandora::TrackList::const_iterator iter = parentTrackList.begin(), iterEnd = parentTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a parent not in the all track list; still use it if it is the closest to the ip + std::cout<<"WARNING PfoCreator::IsValidParentTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->IsClosestTrackToIP(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All parents are associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a sibling not in the all track list; still use it if it has a second sibling that is in the list + std::cout<<"WARNING PfoCreator::HasValidSiblingTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->AreAnyOtherSiblingsInList(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All siblings associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::Track *pClosestTrack(NULL); + float closestTrackDisplacement(std::numeric_limits<float>::max()); + + for (pandora::TrackList::const_iterator iter = allTrackList.begin(), iterEnd = allTrackList.end(); iter != iterEnd; ++iter) + { + const pandora::Track *const pTrack(*iter); + const float trialTrackDisplacement(pTrack->GetTrackStateAtStart().GetPosition().GetMagnitude()); + + if (trialTrackDisplacement < closestTrackDisplacement) + { + closestTrackDisplacement = trialTrackDisplacement; + pClosestTrack = pTrack; + } + } + + return (pPandoraTrack == pClosestTrack); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float referencePointArray[3] = {referencePoint.GetX(), referencePoint.GetY(), referencePoint.GetZ()}; + pReconstructedParticle->setReferencePoint(referencePointArray); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pTrack(*tIter); + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + pReconstructedParticle->addTrack(pLcioTrack); + + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float momentum[3] = {pPandoraPfo->GetMomentum().GetX(), pPandoraPfo->GetMomentum().GetY(), pPandoraPfo->GetMomentum().GetZ()}; + pReconstructedParticle->setMomentum(momentum); + pReconstructedParticle->setEnergy(pPandoraPfo->GetEnergy()); + pReconstructedParticle->setMass(pPandoraPfo->GetMass()); + pReconstructedParticle->setCharge(pPandoraPfo->GetCharge()); + pReconstructedParticle->setType(pPandoraPfo->GetParticleId()); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::Settings::Settings(): + m_emStochasticTerm(0.17f), + m_hadStochasticTerm(0.6f), + m_emConstantTerm(0.01f), + m_hadConstantTerm(0.03f) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp new file mode 100644 index 00000000..a57bd9b2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp @@ -0,0 +1,992 @@ +/** + * @file MarlinPandora/src/TrackCreator.cc + * + * @brief Implementation of the track creator class. + * + * $Log: $ + */ + +//#include "marlin/Global.h" +//#include "marlin/Processor.h" + +//#include "EVENT/LCCollection.h" +//#include "EVENT/ReconstructedParticle.h" +//#include "EVENT/Vertex.h" +#include "UTIL/ILDConf.h" + +#include "edm4hep/Vertex.h" +#include "edm4hep/ReconstructedParticle.h" + +#include "gear/BField.h" +#include "gear/CalorimeterParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/TPCParameters.h" +#include "gear/FTDParameters.h" +#include "gear/FTDLayerLayout.h" + +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" +#include "PandoraPFAlg.h" + +#include "TrackCreator.h" +#include "Pandora/PdgTable.h" + +#include <algorithm> +#include <cmath> +#include <limits> + +TrackCreator::TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc) : + m_settings(settings), + m_pPandora(pPandora) +{ + + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + m_bField = (_GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z()); + m_tpcInnerR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[0]); + m_tpcOuterR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[1]); + m_tpcMaxRow = (_GEAR->getTPCParameters().getPadLayout().getNRows()); + m_tpcZmax = (_GEAR->getTPCParameters().getMaxDriftLength()); + m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder()); + m_eCalBarrelInnerPhi0 = (_GEAR->getEcalBarrelParameters().getPhi0()); + m_eCalBarrelInnerR = (_GEAR->getEcalBarrelParameters().getExtent()[0]); + m_eCalEndCapInnerZ = (_GEAR->getEcalEndcapParameters().getExtent()[2]); + // fg: FTD description in GEAR has changed ... + try + { + m_ftdInnerRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDInnerRadius"); + m_ftdOuterRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDOuterRadius"); + m_ftdZPositions = _GEAR->getGearParameters("FTD").getDoubleVals("FTDZCoordinate"); + m_nFtdLayers = m_ftdZPositions.size(); + } + catch (gear::UnknownParameterException &) + { + const gear::FTDLayerLayout &ftdLayerLayout(_GEAR->getFTDParameters().getFTDLayerLayout()); + std::cout << " Filling FTD parameters from gear::FTDParameters - n layers: " << ftdLayerLayout.getNLayers() << std::endl; + + for(unsigned int i = 0, N = ftdLayerLayout.getNLayers(); i < N; ++i) + { + // Create a disk to represent even number petals front side + m_ftdInnerRadii.push_back(ftdLayerLayout.getSensitiveRinner(i)); + m_ftdOuterRadii.push_back(ftdLayerLayout.getMaxRadius(i)); + + // Take the mean z position of the staggered petals + const double zpos(ftdLayerLayout.getZposition(i)); + m_ftdZPositions.push_back(zpos); + std::cout << " layer " << i << " - mean z position = " << zpos << std::endl; + } + + m_nFtdLayers = m_ftdZPositions.size() ; + } + + // Check tpc parameters + if ((std::fabs(m_tpcZmax) < std::numeric_limits<float>::epsilon()) || (std::fabs(m_tpcInnerR) < std::numeric_limits<float>::epsilon()) + || (std::fabs(m_tpcOuterR - m_tpcInnerR) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + m_cosTpc = m_tpcZmax / std::sqrt(m_tpcZmax * m_tpcZmax + m_tpcInnerR * m_tpcInnerR); + + // Check ftd parameters + if ((0 == m_nFtdLayers) || (m_nFtdLayers != m_ftdInnerRadii.size()) || (m_nFtdLayers != m_ftdOuterRadii.size())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((std::fabs(m_ftdOuterRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon()) || + (std::fabs(m_ftdInnerRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + } + + m_tanLambdaFtd = m_ftdZPositions[0] / m_ftdOuterRadii[0]; + + // Calculate etd and set parameters + // fg: make SET and ETD optional - as they might not be in the model ... + try + { + const DoubleVector &etdZPositions(_GEAR->getGearParameters("ETD").getDoubleVals("ETDLayerZ")); + const DoubleVector &setInnerRadii(_GEAR->getGearParameters("SET").getDoubleVals("SETLayerRadius")); + + if (etdZPositions.empty() || setInnerRadii.empty()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + m_minEtdZPosition = *(std::min_element(etdZPositions.begin(), etdZPositions.end())); + m_minSetRadius = *(std::min_element(setInnerRadii.begin(), setInnerRadii.end())); + } + catch(gear::UnknownParameterException &) + { + std::cout << "Warnning, ETDLayerZ or SETLayerRadius parameters missing from GEAR parameters!" << std::endl + << " -> both will be set to " << std::numeric_limits<float>::quiet_NaN() << std::endl; + + //fg: Set them to NAN, so that they cannot be used to set trackParameters.m_reachesCalorimeter = true; + m_minEtdZPosition = std::numeric_limits<float>::quiet_NaN(); + m_minSetRadius = std::numeric_limits<float>::quiet_NaN(); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::~TrackCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTrackAssociations(const CollectionMaps& collectionMaps) +{ +// Don't use it now, because the Vertex.getAssociatedParticle() doesn't work for LCIO to plcio transfer +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractKinks(collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractProngsAndSplits(const CollectionMaps& collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractV0s(const CollectionMaps& collectionMaps)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractKinks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::ExtractKinks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_kinkVertexCollections.begin(), iterEnd = m_settings.m_kinkVertexCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.CollectionMap_Vertex.find(*iter) == collectionMaps.CollectionMap_Vertex.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const edm4hep::VertexCollection *pKinkCollection = (collectionMaps.CollectionMap_Vertex.find(*iter))->second; + + for (int i = 0, iMax = pKinkCollection->size(); i < iMax; ++i) + { + try + { + const edm4hep::Vertex pVertex0 = pKinkCollection->at(i); + const edm4hep::Vertex* pVertex = &(pVertex0); + + if (NULL == pVertex) throw ("Collection type mismatch"); + + std::cout<<"pVertex0 getChi2="<<pVertex0.getChi2()<<std::endl; + std::cout<<"pVertex getChi2="<<pVertex->getChi2()<<std::endl; + std::cout<<"Hi 0 "<<std::endl; + const plcio::ConstReconstructedParticle pReconstructedParticle0 = pVertex0.getAssociatedParticle(); + std::cout<<"Hi 1"<<std::endl; + //EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const plcio::ConstReconstructedParticle pReconstructedParticle = pVertex->getAssociatedParticle(); + std::cout<<"Hi 2:"<<&pReconstructedParticle<<std::endl; + //const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + //plcio::ConstTrack trackVec = pReconstructedParticle.getTracks(); + + std::cout<<"pReconstructedParticle0 en="<<pReconstructedParticle0.getEnergy()<<std::endl; + std::cout<<"pReconstructedParticle en="<<pReconstructedParticle.getEnergy()<<std::endl; + //if (this->IsConflictingRelationship(trackVec))continue; + if (this->IsConflictingRelationship(pReconstructedParticle))continue; + + //const int vertexPdgCode(pReconstructedParticle->getType()); + const int vertexPdgCode(pReconstructedParticle.getType()); + + // Extract the kink vertex information + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + for (unsigned int iTrack = 0, nTracks = pReconstructedParticle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + //plcio::ConstTrack pTrack = trackVec.getTracks(iTrack); + plcio::ConstTrack pTrack = pReconstructedParticle.getTracks(iTrack); + //(0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + (0 == iTrack) ? m_parentTrackList.insert(pTrack.id()) : m_daughterTrackList.insert(pTrack.id()); + //std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.getTrackerHits().size() << std::endl; + std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.trackerHits_size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + if (0 == iTrack) + { + trackPdgCode = vertexPdgCode; + } + else + { + switch (vertexPdgCode) + { + case pandora::PI_PLUS : + case pandora::K_PLUS : + trackPdgCode = pandora::MU_PLUS; + break; + case pandora::PI_MINUS : + case pandora::K_MINUS : + trackPdgCode = pandora::MU_MINUS; + break; + case pandora::HYPERON_MINUS_BAR : + case pandora::SIGMA_PLUS : + trackPdgCode = pandora::PI_PLUS; + break; + case pandora::SIGMA_MINUS : + case pandora::HYPERON_MINUS : + trackPdgCode = pandora::PI_PLUS; + break; + default : + //(pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + (pTrack.getTrackStates(0).omega > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) ) ); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) ) ); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) )); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) )); + } + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_prongSplitVertexCollections.begin(), iterEnd = m_settings.m_prongSplitVertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pProngOrSplitCollection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pProngOrSplitCollection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pProngOrSplitCollection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the prong/split vertex information + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + (0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + streamlog_out(DEBUG) << "Prong or Split Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract prong/split vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract prong/split vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::ExtractV0s(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_v0VertexCollections.begin(), iterEnd = m_settings.m_v0VertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pV0Collection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pV0Collection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pV0Collection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the v0 vertex information + const int vertexPdgCode(pReconstructedParticle->getType()); + + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + m_v0TrackList.insert(pTrack); + streamlog_out(DEBUG) << "V0Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + switch (vertexPdgCode) + { + case pandora::PHOTON : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::E_PLUS : trackPdgCode = pandora::E_MINUS; + break; + case pandora::LAMBDA : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PROTON : trackPdgCode = pandora::PI_MINUS; + break; + case pandora::LAMBDA_BAR : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PROTON_BAR; + break; + case pandora::K_SHORT : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + default : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track sibling relationships + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract v0 vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract v0 vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const +{ + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + std::cout<<"Particle en="<<Particle.getEnergy()<<std::endl; + for (unsigned int iTrack = 0, nTracks = Particle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + edm4hep::ConstTrack pTrack = Particle.getTracks(iTrack) ; + unsigned int pTrack_id = pTrack.id() ; + + //if (this->IsDaughter(pTrack) || this->IsParent(pTrack) || this->IsV0(pTrack)) + if (this->IsDaughter(pTrack_id) || this->IsParent(pTrack_id) || this->IsV0(pTrack_id)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTracks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::CreateTracks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_trackCollections.begin(), iterEnd = m_settings.m_trackCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_Track.find(*iter) == collectionMaps.collectionMap_Track.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::Track>& pTrackCollection = (collectionMaps.collectionMap_Track.find(*iter))->second; + std::cout<<(*iter)<<" size="<<pTrackCollection.size()<<std::endl; + + for (int i = 0, iMax = pTrackCollection.size(); i < iMax; ++i) + { + try + { + const edm4hep::Track& pTrack0 = pTrackCollection.at(i); + const edm4hep::Track* pTrack = (const edm4hep::Track*)(&pTrack0); + + if (NULL == pTrack) throw ("Collection type mismatch"); + + int minTrackHits = m_settings.m_minTrackHits; + //const float tanLambda(std::fabs(pTrack->getTanLambda())); + //std::cout<<"track states size="<<pTrack->trackStates_size()<<std::endl; + const float tanLambda(std::fabs(pTrack->getTrackStates(0).tanLambda)); + + if (tanLambda > m_tanLambdaFtd) + { + int expectedFtdHits(0); + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((tanLambda > m_ftdZPositions[iFtdLayer] / m_ftdOuterRadii[iFtdLayer]) && + (tanLambda < m_ftdZPositions[iFtdLayer] / m_ftdInnerRadii[iFtdLayer])) + { + expectedFtdHits++; + } + } + + minTrackHits = std::max(m_settings.m_minFtdTrackHits, expectedFtdHits); + } + + const int nTrackHits(static_cast<int>(pTrack->trackerHits_size())); + + if ((nTrackHits < minTrackHits) || (nTrackHits > m_settings.m_maxTrackHits)) + continue; + + // Proceed to create the pandora track + PandoraApi::Track::Parameters trackParameters; + //trackParameters.m_d0 = pTrack->getD0(); + trackParameters.m_d0 = pTrack->getTrackStates(0).D0; + //trackParameters.m_z0 = pTrack->getZ0(); + trackParameters.m_z0 = pTrack->getTrackStates(0).Z0; + trackParameters.m_pParentAddress = pTrack; + // By default, assume tracks are charged pions + const float signedCurvature(pTrack->getTrackStates(0).omega); + trackParameters.m_particleId = (signedCurvature > 0) ? pandora::PI_PLUS : pandora::PI_MINUS; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass(pandora::PI_PLUS); + + // Use particle id information from V0 and Kink finders + TrackToPidMap::const_iterator iter_t = m_trackToPidMap.find(*pTrack); + + if(iter_t != m_trackToPidMap.end()) + { + trackParameters.m_particleId = (*iter_t).second; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass((*iter_t).second); + } + + if (std::numeric_limits<float>::epsilon() < std::fabs(signedCurvature)) + trackParameters.m_charge = static_cast<int>(signedCurvature / std::fabs(signedCurvature)); + + this->GetTrackStates(pTrack, trackParameters); + this->TrackReachesECAL(pTrack, trackParameters); + this->DefineTrackPfoUsage(pTrack, trackParameters); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Track::Create(*m_pPandora, trackParameters)); + m_trackVector.push_back(pTrack); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract a track: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "WARNNING Failed to extract a track "<< std::endl; + } + } + } + catch (...) + { + std::cout<<"WARNING Failed to extract track collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + //const TrackState *pTrackState = pTrack->getTrackState(TrackState::AtIP); + edm4hep::TrackState pTrackState = pTrack->getTrackStates(1); // ref /cvmfs/cepcsw.ihep.ac.cn/prototype/LCIO/include/EVENT/TrackState.h + + //if (!pTrackState) throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + //const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState->getOmega())); + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + //trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState->getPhi()), std::sin(pTrackState->getPhi()), pTrackState->getTanLambda()) * pt; + trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState.phi), std::sin(pTrackState.phi), pTrackState.tanLambda) * pt; + //this->CopyTrackState(pTrack->getTrackState(TrackState::AtFirstHit), trackParameters.m_trackStateAtStart); + this->CopyTrackState(pTrack->getTrackStates(2), trackParameters.m_trackStateAtStart); + + //fg: curling TPC tracks have pointers to track segments stored -> need to get track states from last segment! + //const EVENT::Track *pEndTrack = (pTrack->getTracks().empty() ? pTrack : pTrack->getTracks().back()); + auto pEndTrack = (pTrack->tracks_size() ==0 ) ? *pTrack : pTrack->getTracks(pTrack->tracks_size()-1); + + //std::cout<<"GetTrackStates 1.6"<<", end track trackStates_size()="<<pEndTrack.trackStates_size()<<std::endl; + + //this->CopyTrackState(pEndTrack->getTrackState(TrackState::AtLastHit), trackParameters.m_trackStateAtEnd); + //this->CopyTrackState(pEndTrack->getTrackState(TrackState::AtCalorimeter), trackParameters.m_trackStateAtCalorimeter); + + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtEnd); + //this->CopyTrackState(pEndTrack.getTrackStates(4), trackParameters.m_trackStateAtCalorimeter); + //FIXME ? LCIO input only has 4 states, so 4 can't be used. + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtCalorimeter); + + + trackParameters.m_isProjectedToEndCap = ((std::fabs(trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetZ()) < m_eCalEndCapInnerZ) ? false : true); + + // Convert generic time (length from reference point to intersection, divided by momentum) into nanoseconds + const float minGenericTime(this->CalculateTrackTimeAtCalorimeter(pTrack)); + const float particleMass(trackParameters.m_mass.Get()); + const float particleEnergy(std::sqrt(particleMass * particleMass + trackParameters.m_momentumAtDca.Get().GetMagnitudeSquared())); + trackParameters.m_timeAtCalorimeter = minGenericTime * particleEnergy / 299.792f; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float TrackCreator::CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const +{ + //const pandora::Helix helix(pTrack->getPhi(), pTrack->getD0(), pTrack->getZ0(), pTrack->getOmega(), pTrack->getTanLambda(), m_bField); + const pandora::Helix helix(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const pandora::CartesianVector &referencePoint(helix.GetReferencePoint()); + + // First project to endcap + float minGenericTime(std::numeric_limits<float>::max()); + + pandora::CartesianVector bestECalProjection(0.f, 0.f, 0.f); + const int signPz((helix.GetMomentum().GetZ() > 0.f) ? 1 : -1); + (void) helix.GetPointInZ(static_cast<float>(signPz) * m_eCalEndCapInnerZ, referencePoint, bestECalProjection, minGenericTime); + + // Then project to barrel surface(s) + pandora::CartesianVector barrelProjection(0.f, 0.f, 0.f); + if (m_eCalBarrelInnerSymmetry > 0) + { + // Polygon + float twopi_n = 2. * M_PI / (static_cast<float>(m_eCalBarrelInnerSymmetry)); + + for (int i = 0; i < m_eCalBarrelInnerSymmetry; ++i) + { + float genericTime(std::numeric_limits<float>::max()); + const float phi(twopi_n * static_cast<float>(i) + m_eCalBarrelInnerPhi0); + + const pandora::StatusCode statusCode(helix.GetPointInXY(m_eCalBarrelInnerR * std::cos(phi), m_eCalBarrelInnerR * std::sin(phi), + std::cos(phi + 0.5 * M_PI), std::sin(phi + 0.5 * M_PI), referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + } + else + { + // Cylinder + float genericTime(std::numeric_limits<float>::max()); + const pandora::StatusCode statusCode(helix.GetPointOnCircle(m_eCalBarrelInnerR, referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + + if (bestECalProjection.GetMagnitudeSquared() < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return minGenericTime; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const +{ + //if (!pTrackState) throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + //const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState->getOmega())); + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + + //const double px(pt * std::cos(pTrackState->getPhi())); + const double px(pt * std::cos(pTrackState.phi)); + //const double py(pt * std::sin(pTrackState->getPhi())); + const double py(pt * std::sin(pTrackState.phi)); + //const double pz(pt * pTrackState->getTanLambda()); + const double pz(pt * pTrackState.tanLambda); + + const double xs(pTrackState.referencePoint[0]); + const double ys(pTrackState.referencePoint[1]); + const double zs(pTrackState.referencePoint[2]); + + inputTrackState = pandora::TrackState(xs, ys, zs, px, py, pz); +} + + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + + // Calculate hit position information + float hitZMin(std::numeric_limits<float>::max()); + float hitZMax(-std::numeric_limits<float>::max()); + float hitOuterR(-std::numeric_limits<float>::max()); + + int maxOccupiedFtdLayer=0; + + + const unsigned int nTrackHits(pTrack->trackerHits_size()); + for (unsigned int i = 0; i < nTrackHits; ++i) + { + + const edm4hep::ConstTrackerHit Hit ( pTrack->getTrackerHits(i) ); + const edm4hep::Vector3d pos = Hit.getPosition(); + + float x = float(pos[0]); + float y = float(pos[1]); + float z = float(pos[2]); + float r = std::sqrt(x * x + y * y); + + if (z > hitZMax) hitZMax = z; + + if (z < hitZMin) hitZMin = z; + + if (r > hitOuterR) hitOuterR = r; + + if ((r > m_tpcInnerR) && (r < m_tpcOuterR) && (std::fabs(z) <= m_tpcZmax)) continue; + + for (unsigned int j = 0; j < m_nFtdLayers; ++j) + { + if ((r > m_ftdInnerRadii[j]) && (r < m_ftdOuterRadii[j]) && + (std::fabs(z) - m_settings.m_reachesECalFtdZMaxDistance < m_ftdZPositions[j]) && + (std::fabs(z) + m_settings.m_reachesECalFtdZMaxDistance > m_ftdZPositions[j])) + { + //if (static_cast<int>(j) > maxOccupiedFtdLayer) maxOccupiedFtdLayer = static_cast<int>(j); + if ( j > maxOccupiedFtdLayer) maxOccupiedFtdLayer = j; + break; + } + } + } + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + // Look to see if there are hits in etd or set, implying track has reached edge of ecal + if ((hitOuterR > m_minSetRadius) || (hitZMax > m_minEtdZPosition)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + // Require sufficient hits in tpc or ftd, then compare extremal hit positions with tracker dimensions + if ((nTpcHits >= m_settings.m_reachesECalNTpcHits) || (nFtdHits >= m_settings.m_reachesECalNFtdHits)) + { + if ((hitOuterR - m_tpcOuterR > m_settings.m_reachesECalTpcOuterDistance) || + (std::fabs(hitZMax) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (std::fabs(hitZMin) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (maxOccupiedFtdLayer >= m_settings.m_reachesECalMinFtdLayer)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + } + + // If track is lowpt, it may curl up and end inside tpc inner radius + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float cosAngleAtDca(std::fabs(momentumAtDca.GetZ()) / momentumAtDca.GetMagnitude()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + if ((cosAngleAtDca > m_cosTpc) || (pT < m_settings.m_curvatureToMomentumFactor * m_bField * m_tpcOuterR)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + trackParameters.m_reachesCalorimeter = false; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + bool canFormPfo(false); + bool canFormClusterlessPfo(false); + + //if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack)) + if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack->id())) + { + //const float d0(std::fabs(pTrack->getD0())), z0(std::fabs(pTrack->getZ0())); + const float d0(std::fabs(pTrack->getTrackStates(0).D0)), z0(std::fabs(pTrack->getTrackStates(0).Z0)); + + //EVENT::TrackerHitVec trackerHitvec(pTrack->getTrackerHits()); + float rInner(std::numeric_limits<float>::max()), zMin(std::numeric_limits<float>::max()); + + //for (EVENT::TrackerHitVec::const_iterator iter = trackerHitvec.begin(), iterEnd = trackerHitvec.end(); iter != iterEnd; ++iter) + for (std::vector<edm4hep::ConstTrackerHit>::const_iterator iter = pTrack->trackerHits_begin(), iterEnd = pTrack->trackerHits_end(); iter != iterEnd; ++iter) + { + //const double *pPosition((*iter)->getPosition()); + const edm4hep::Vector3d pPosition = (*iter).getPosition(); + const float x(pPosition[0]), y(pPosition[1]), absoluteZ(std::fabs(pPosition[2])); + const float r(std::sqrt(x * x + y * y)); + + if (r < rInner) + rInner = r; + + if (absoluteZ < zMin) + zMin = absoluteZ; + } + + if (this->PassesQualityCuts(pTrack, trackParameters)) + { + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()), pZ(momentumAtDca.GetZ()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + const float zCutForNonVertexTracks(m_tpcInnerR * std::fabs(pZ / pT) + m_settings.m_zCutForNonVertexTracks); + const bool passRzQualityCuts((zMin < zCutForNonVertexTracks) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)); + + const bool isV0(this->IsV0(pTrack->id())); + const bool isDaughter(this->IsDaughter(pTrack->id())); + + // Decide whether track can be associated with a pandora cluster and used to form a charged PFO + if ((d0 < m_settings.m_d0TrackCut) && (z0 < m_settings.m_z0TrackCut) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks)) + { + canFormPfo = true; + } + else if (isV0 || isDaughter) + { + canFormPfo = true; + } + + // Decide whether track can be used to form a charged PFO, even if track fails to be associated with a pandora cluster + const float particleMass(trackParameters.m_mass.Get()); + const float trackEnergy(std::sqrt(momentumAtDca.GetMagnitudeSquared() + particleMass * particleMass)); + + if ((0 != m_settings.m_usingUnmatchedVertexTracks) && (trackEnergy < m_settings.m_unmatchedVertexTrackMaxEnergy)) + { + if ((d0 < m_settings.m_d0UnmatchedVertexTrackCut) && (z0 < m_settings.m_z0UnmatchedVertexTrackCut) && + (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormClusterlessPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks) && (0 != m_settings.m_usingUnmatchedNonVertexTracks)) + { + canFormClusterlessPfo = true; + } + else if (isV0 || isDaughter) + { + canFormClusterlessPfo = true; + } + } + } + else if (this->IsDaughter(pTrack->id()) || this->IsV0(pTrack->id())) + { + std::cout<<"WARNING Recovering daughter or v0 track " << trackParameters.m_momentumAtDca.Get().GetMagnitude() << std::endl; + canFormPfo = true; + } + } + + trackParameters.m_canFormPfo = canFormPfo; + trackParameters.m_canFormClusterlessPfo = canFormClusterlessPfo; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const +{ + // First simple sanity checks + if (trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetMagnitude() < m_settings.m_minTrackECalDistanceFromIp) + return false; + + //if (std::fabs(pTrack->getOmega()) < std::numeric_limits<float>::epsilon()) + if (std::fabs(pTrack->getTrackStates(0).omega) < std::numeric_limits<float>::epsilon()) + { + std::cout<<"ERROR Track has Omega = 0 " << std::endl; + return false; + } + + // Check momentum uncertainty is reasonable to use track + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + //const float sigmaPOverP(std::sqrt(pTrack->getCovMatrix()[5]) / std::fabs(pTrack->getOmega())); + const float sigmaPOverP(std::sqrt(pTrack->getTrackStates(0).covMatrix[5]) / std::fabs(pTrack->getTrackStates(0).omega)); + + if (sigmaPOverP > m_settings.m_maxTrackSigmaPOverP) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << "+-" << sigmaPOverP * (momentumAtDca.GetMagnitude()) + << " chi2 = " << pTrack->getChi2() << " " << pTrack->getNdf() + << " from " << pTrack->trackerHits_size() << std::endl; + return false; + } + + // Require reasonable number of TPC hits + if (momentumAtDca.GetMagnitude() > m_settings.m_minMomentumForTrackHitChecks) + { + const float pX(fabs(momentumAtDca.GetX())); + const float pY(fabs(momentumAtDca.GetY())); + const float pZ(fabs(momentumAtDca.GetZ())); + const float pT(std::sqrt(pX * pX + pY * pY)); + const float rInnermostHit(pTrack->getRadiusOfInnermostHit()); + + if ((std::numeric_limits<float>::epsilon() > std::fabs(pT)) || (std::numeric_limits<float>::epsilon() > std::fabs(pZ)) || (rInnermostHit == m_tpcOuterR)) + { + std::cout<<"ERROR Invalid track parameter, pT " << pT << ", pZ " << pZ << ", rInnermostHit " << rInnermostHit << std::endl; + return false; + } + + float nExpectedTpcHits(0.); + + if (pZ < m_tpcZmax / m_tpcOuterR * pT) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcOuterR - innerExpectedHitRadius) / (m_tpcOuterR - m_tpcInnerR)); + nExpectedTpcHits = m_tpcMaxRow * frac; + } + + if ((pZ <= m_tpcZmax / m_tpcInnerR * pT) && (pZ >= m_tpcZmax / m_tpcOuterR * pT)) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcZmax * pT / pZ - innerExpectedHitRadius) / (m_tpcOuterR - innerExpectedHitRadius)); + nExpectedTpcHits = frac * m_tpcMaxRow; + } + + // TODO Get TPC membrane information from GEAR when available + if (std::fabs(pZ) / momentumAtDca.GetMagnitude() < m_settings.m_tpcMembraneMaxZ / m_tpcInnerR) + nExpectedTpcHits = 0; + + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + const int minTpcHits = static_cast<int>(nExpectedTpcHits * m_settings.m_minTpcHitFractionOfExpected); + + if ((nTpcHits < minTpcHits) && (nFtdHits < m_settings.m_minFtdHitsForTpcHitFraction)) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << " Number of TPC hits = " << nTpcHits + << " < " << minTpcHits << " nftd = " << nFtdHits << std::endl; + return false; + } + } + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNTpcHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - 1 ]; + return pTrack->getSubDetectorHitNumbers(2 * lcio::ILDDetID::TPC - 1);// still use LCIO code now +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNFtdHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - 1 ]; + return pTrack->getSubDetectorHitNumbers( 2 * lcio::ILDDetID::FTD - 1 ); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::Settings::Settings() : + m_shouldFormTrackRelationships(1), + m_minTrackHits(5), + m_minFtdTrackHits(0), + m_maxTrackHits(5000.f), + m_d0TrackCut(50.f), + m_z0TrackCut(50.f), + m_usingNonVertexTracks(1), + m_usingUnmatchedNonVertexTracks(0), + m_usingUnmatchedVertexTracks(1), + m_unmatchedVertexTrackMaxEnergy(5.f), + m_d0UnmatchedVertexTrackCut(5.f), + m_z0UnmatchedVertexTrackCut(5.f), + m_zCutForNonVertexTracks(250.f), + m_reachesECalNTpcHits(11), + m_reachesECalNFtdHits(4), + m_reachesECalTpcOuterDistance(-100.f), + m_reachesECalMinFtdLayer(9), + m_reachesECalTpcZMaxDistance(-50.f), + m_reachesECalFtdZMaxDistance(1.f), + m_curvatureToMomentumFactor(0.3f / 2000.f), + m_minTrackECalDistanceFromIp(100.f), + m_maxTrackSigmaPOverP(0.15f), + m_minMomentumForTrackHitChecks(1.f), + m_tpcMembraneMaxZ(10.f), + m_maxTpcInnerRDistance(50.f), + m_minTpcHitFractionOfExpected(0.2f), + m_minFtdHitsForTpcHitFraction(2) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp new file mode 100644 index 00000000..819fa15d --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp @@ -0,0 +1,7 @@ +#include "Utility.h" + +std::string Convert (float number){ + std::ostringstream buff; + buff<<number; + return buff.str(); +} diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc new file mode 100644 index 00000000..e7e8d4fc --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc @@ -0,0 +1,2005 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +#include "ClusterShapes.h" + +#include <gsl/gsl_vector.h> +#include <gsl/gsl_matrix.h> +//#include <gsl/gsl_blas.h> +#include <gsl/gsl_linalg.h> +#include <gsl/gsl_eigen.h> +#include <gsl/gsl_multifit_nlin.h> +#include <gsl/gsl_sf_gamma.h> +#include <gsl/gsl_integration.h> +//#include <gsl/gsl_rng.h> +//#include <gsl/gsl_sf_pow_int.h> + + + +// ################################################# +// ##### ##### +// ##### Additional Structures and Functions ##### +// ##### ##### +// ################################################# +//============================================================================= + +struct data { + int n; + float* x; + float* y; + float* z; + float* ex; + float* ey; + float* ez; +}; + +//============================================================================= + +// Gammafunction +double G(double x) { + + return gsl_sf_gamma(x); + +} + +//============================================================================= + +// inverse Gammafunction +double invG(double x) { + + return gsl_sf_gammainv(x); + +} + +//============================================================================= + +// Integral needed for deriving the derivative of the Gammafunction +double Integral_G(double x, void* params) { + double a = *(double*)params; + double f = exp(-x) * pow(x,a-1) * log(x); + return f; +} + +//============================================================================= + +double DinvG(double x) { + + int workspace_size = 1000; + double abs_error = 0; + double rel_error = 1e-6; + double result = 0.0; + double error = 0.0; + int status = 0; + + gsl_integration_workspace* w = gsl_integration_workspace_alloc(workspace_size); + gsl_function F; + F.function = &Integral_G; + F.params = &x; + + status = gsl_integration_qagiu(&F,0,abs_error,rel_error,workspace_size,w, + &result,&error); + + // debug + /* + printf ("Numeric Integration : \n"); + printf ("parameter of integration = % .18f\n", x); + printf ("status of integration = %d \n" , status); + printf ("result = % .18f\n", result); + printf ("estimated error = % .18f\n", error); + printf ("intervals = %d\n\n", w->size); + */ + + double G2 = pow(gsl_sf_gamma(x),2); + double DG = result; + + gsl_integration_workspace_free(w); + + return -DG/G2; + +} + +//============================================================================= + +int ShapeFitFunct(const gsl_vector* par, void* d, gsl_vector* f) { + + // Used for shape fitting. Function to fit: + // + // a[i](t[i],s[i]) = + // + // E0 * b * 1/Gamma(a) * ( b * (t[i] - t0) )^(a-1) * exp(-b*(t[i] - t0)) * exp(-d*s[i]) + // + // Function to minimise: + // + // f0[i] = E0 * b * 1/Gamma(a) * + // ( b * (t[i] - t0) )^(a-1) * exp(-b*(t[i] - t0)) * exp(-d*s[i]) - a[i] + // + + + // float E0 = gsl_vector_get(par,0); + float A = gsl_vector_get(par,0); + float B = gsl_vector_get(par,1); + float D = gsl_vector_get(par,2); + float t0 = gsl_vector_get(par,3); + int n = ((struct data*)d)->n; + float* t = ((struct data*)d)->x; + float* s = ((struct data*)d)->y; + float* a = ((struct data*)d)->z; // amplitude stored in z[i] + float fi = 0.0; + + + for (int i(0); i < n; i++) { + fi = /*E0 * */ B * invG(A) * pow(B*(t[i]-t0),A-1) * exp(-B*(t[i]-t0)) * exp(-D*s[i]) + - a[i]; + gsl_vector_set(f,i,fi); + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int dShapeFitFunct(const gsl_vector* par, void* d, gsl_matrix* J) { + + // Used for shape fitting + //float E0 = gsl_vector_get(par,0); + float A = gsl_vector_get(par,0); + float B = gsl_vector_get(par,1); + float D = gsl_vector_get(par,2); + float t0 = gsl_vector_get(par,3); + int n = ((struct data*)d)->n; + float* t = ((struct data*)d)->x; + float* s = ((struct data*)d)->y; + + + // calculate Jacobi's matrix J[i][j] = dfi/dparj, but here only one dimension + + for (int i(0); i < n; i++) { + + /* + gsl_matrix_set(J,i,0,B * invG(A) * pow(B*(t[i]-t0),A-1) * exp(-B*(t[i]-t0)) + * exp(-D*s[i]) ); + */ + + gsl_matrix_set(J,i,0,( /* E0 * */ B * invG(A) * log(B*(t[i]-t0))*pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + DinvG(A) * /* E0 * */ B * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + ) * exp(-D*s[i])); + + gsl_matrix_set(J,i,1,( /* E0 * */ invG(A) * pow(B*(t[i]-t0),A-1) * exp(-B*(t[i]-t0)) + + /* E0 * */ invG(A) * (A-1) * B * (t[i]-t0) * pow(B*(t[i]-t0),A-2) * + exp(-B*(t[i]-t0)) - + /* E0 * */ B * invG(A) * (t[i]-t0) * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + ) * exp(-D*s[i])); + + gsl_matrix_set(J,i,2,-/* E0 * */ B * invG(A) * s[i] * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) * exp(-D*s[i])); + + gsl_matrix_set(J,i,3,(-/* E0 * */ pow(B,2) * invG(A) * (A-1) * pow(B*(t[i]-t0),A-2) * + exp(-B*(t[i]-t0)) + + /* E0 * */ pow(B,2) * invG(A) * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + ) * exp(-D*s[i])); + + + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int fdfShapeFitFunct(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + ShapeFitFunct(par, d, f); + dShapeFitFunct(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + +int signum(float x) { + + // computes the signum of x. Needed for the 3. parametrisation + + if ( x >= 0 ) return 1; // x == 0 is taken as positive + else return -1; + +} + +//============================================================================= + +int functParametrisation1(const gsl_vector* par, void* d, gsl_vector* f) { + + // For helix fitting + // calculate fit function f0[i] = + // ( (x0 + R*cos(b*z[i] + phi0)) - x[i] ) for i = 0 to n-1 + // and f1[i] = + // ( (y0 + R*sin(b*z[i] + phi0)) - y[i] ) for i = n to dim*n - 1 + // That means, minimise the two functions f0[i] and f1[i] + + float x0 = gsl_vector_get(par,0); + float y0 = gsl_vector_get(par,1); + float R = gsl_vector_get(par,2); + float b = gsl_vector_get(par,3); + float phi0 = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float* z = ((struct data*)d)->z; +//float* ex = ((struct data*)d)->ex; +//float* ey = ((struct data*)d)->ey; +//float* ez = ((struct data*)d)->ez; + float fi = 0.0; + + // first dimension + for (int i(0); i < n; i++) { + fi = (x0 + R*cos(b*z[i] + phi0)) - x[i]; + // float err = sqrt(ex[i]*ex[i]+R*b*R*b*sin(b*z[i] + phi0)*R*b*R*b*sin(b*z[i] + phi0)*ez[i]*ez[i]); + // fi = fi/err; + gsl_vector_set(f,i,fi); + } + // second dimension + for (int i(0); i < n; i++) { + fi = (y0 + R*sin(b*z[i] + phi0)) - y[i]; + // float err = sqrt(ey[i]*ey[i]+R*b*R*b*cos(b*z[i] + phi0)*R*b*R*b*cos(b*z[i] + phi0)*ez[i]*ez[i]); + // fi = fi/err; + gsl_vector_set(f,i+n,fi); + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int dfunctParametrisation1(const gsl_vector* par, void* d, gsl_matrix* J) { + + // For helix fitting + float R = gsl_vector_get(par,2); + float b = gsl_vector_get(par,3); + float phi0 = gsl_vector_get(par,4); + + int n = ((struct data*)d)->n; + float* z = ((struct data*)d)->z; +//float* ex = ((struct data*)d)->ex; +//float* ey = ((struct data*)d)->ey; +//float* ez = ((struct data*)d)->ez; + + + // calculate Jacobi's matrix J[i][j] = dfi/dparj + + // part of Jacobi's matrix corresponding to first dimension + for (int i(0); i < n; i++) { + // float err = sqrt(ex[i]*ex[i]+R*b*R*b*sin(b*z[i] + phi0)*R*b*R*b*sin(b*z[i] + phi0)*ez[i]*ez[i]); + gsl_matrix_set(J,i,0,1); + gsl_matrix_set(J,i,1,0); + gsl_matrix_set(J,i,2,cos(b*z[i]+phi0)); + gsl_matrix_set(J,i,3,-z[i]*R*sin(b*z[i]+phi0)); + gsl_matrix_set(J,i,4,-R*sin(b*z[i]+phi0)); + + } + + // part of Jacobi's matrix corresponding to second dimension + for (int i(0); i < n; i++) { + // float err = sqrt(ey[i]*ey[i]+R*b*R*b*cos(b*z[i] + phi0)*R*b*R*b*cos(b*z[i] + phi0)*ez[i]*ez[i]); + gsl_matrix_set(J,i+n,0,0); + gsl_matrix_set(J,i+n,1,1); + gsl_matrix_set(J,i+n,2,sin(b*z[i]+phi0)); + gsl_matrix_set(J,i+n,3,z[i]*R*cos(b*z[i]+phi0)); + gsl_matrix_set(J,i+n,4,R*cos(b*z[i]+phi0)); + + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int fdfParametrisation1(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + functParametrisation1(par, d, f); + dfunctParametrisation1(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + +int functParametrisation2(const gsl_vector* par, void* d, gsl_vector* f) { + + // For helix fitting + // calculate fit function f0[i] = + // ( (x0 + R*cos(phi)) - x[i] ) for i = 0 to n-1 + // f1[i] = + // ( (y0 + R*sin(phi)) - y[i] ) for i = n to dim*n - 1 + // and f2[i] = + // ( (z0 + b*phi ) - z[i] ) + // That means, minimise the three functions f0[i], f1[i] and f2[i] + + float x0 = gsl_vector_get(par,0); + float y0 = gsl_vector_get(par,1); + float z0 = gsl_vector_get(par,2); + float R = gsl_vector_get(par,3); + float b = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float* z = ((struct data*)d)->z; + float fi = 0.0; + float phii = 0.0; + + // first dimension + for (int i(0); i < n; i++) { + phii = atan2( y[i]-y0, x[i]-x0 ); + fi = (x0 + R*cos(phii)) - x[i]; + gsl_vector_set(f,i,fi); + } + // second dimension + for (int i(0); i < n; i++) { + phii = atan2( y[i]-y0, x[i]-x0 ); + fi = (y0 + R*sin(phii)) - y[i]; + gsl_vector_set(f,i+n,fi); + } + // third dimension + for (int i(0); i < n; i++) { + phii = atan2( y[i]-y0, x[i]-x0 ); + fi = (z0 + b*phii) - z[i]; + gsl_vector_set(f,i+2*n,fi); + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int dfunctParametrisation2(const gsl_vector* par, void* d, gsl_matrix* J) { + + // For helix fitting + float x0 = gsl_vector_get(par,0); + float y0 = gsl_vector_get(par,1); + float R = gsl_vector_get(par,3); + float b = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float phii = 0.0; + + // calculate Jacobi's matrix J[i][j] = dfi/dparj + + // part of Jacobi's matrix corresponding to first dimension + for (int i(0); i < n; i++) { + + phii = atan2( y[i]-y0, x[i]-x0 ); + + gsl_matrix_set(J,i,0,1 - R*sin(phii)* + ( (y[i]-y0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i,1,R*sin(phii)* + ( (x[i]-x0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i,2,0); + gsl_matrix_set(J,i,3,cos(phii)); + gsl_matrix_set(J,i,4,0); + + } + + // part of Jacobi's matrix corresponding to second dimension + for (int i(0); i < n; i++) { + + phii = atan2( y[i]-y0, x[i]-x0 ); + + gsl_matrix_set(J,i+n,0,R*cos(phii)* + ( (y[i]-y0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+n,1,1 + R*cos(phii)* + ( (x[i]-x0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+n,2,0); + gsl_matrix_set(J,i+n,3,sin(phii)); + gsl_matrix_set(J,i+n,4,0); + + } + + // part of Jacobi's matrix corresponding to third dimension + for (int i(0); i < n; i++) { + + phii = atan2( y[i]-y0, x[i]-x0 ); + + gsl_matrix_set(J,i+2*n,0,b* + ( (y[i]-y0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+2*n,1,b* + ( (x[i]-x0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+2*n,2,1); + gsl_matrix_set(J,i+2*n,3,0); + gsl_matrix_set(J,i+2*n,4,phii); + + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int fdfParametrisation2(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + functParametrisation2(par, d, f); + dfunctParametrisation2(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + +int functParametrisation3(const gsl_vector* par, void* d, gsl_vector* f) { + + // For helix fitting + // calculate fit function f0[i] = + // ( ( ( (1/omega) - d0 )*sin(Phi0) + ( 1/fabs(omega) )*cos( ( -omega/sqrt(1+tanL^2) )*s + Phi0 +( (omega*pi)/(2*fabs(omega)) ) ) ) - x[i] ) for i = 0 to n-1 + // f1[i] = + // ( ( (-1.0)*( (1/omega) - d0 )*cos(Phi0) + ( 1/fabs(omega) )*sin( ( -omega/sqrt(1+tanL^2) )*s + Phi0 +( (omega*pi)/(2*fabs(omega)) ) ) ) - y[i] ) for i = n to dim*n - 1 + // and f2[i] = + // ( ( z0 + (tanL/sqrt(1+tanL^2))*s ) - z[i] ) + // That means, minimise the three functions f0[i], f1[i] and f2[i] + + double z0 = gsl_vector_get(par,0); + double Phi0 = gsl_vector_get(par,1); + double omega = gsl_vector_get(par,2); + double d0 = gsl_vector_get(par,3); + double tanL = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float* z = ((struct data*)d)->z; + double phii = 0.0; + double fi = 0.0; + double si = 0.0; + + // first dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + fi = ( ( (1/omega) - d0 )*sin(Phi0) + ( 1/fabs(omega) )*cos(phii) ) - ((double)x[i]); + gsl_vector_set(f,i,fi); + } + // second dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + fi = ( (-1.0)*( (1/omega) - d0 )*cos(Phi0) + ( 1/fabs(omega) )*sin(phii) ) - ((double)y[i]); + gsl_vector_set(f,i+n,fi); + } + // third dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + fi = ( z0 + (tanL/sqrt(1+pow(tanL,2)))*si ) - ((double)z[i]); + gsl_vector_set(f,i+2*n,fi); + } + + return GSL_SUCCESS; + +} + +//============================================================================= + +int dfunctParametrisation3(const gsl_vector* par, void* d, gsl_matrix* J) { + + + // For helix fitting + // double z0 = gsl_vector_get(par,0); // not needed + double Phi0 = gsl_vector_get(par,1); + double omega = gsl_vector_get(par,2); + double d0 = gsl_vector_get(par,3); + double tanL = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + // float* z = ((struct data*)d)->z; // not needed + double phii = 0.0; + double si = 0.0; + + // calculate Jacobi's matrix J[i][j] = dfi/dparj + + // part of Jacobi's matrix corresponding to first dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 ) * cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + + gsl_matrix_set(J,i,0,0); + gsl_matrix_set(J,i,1,((1/omega) - d0) * cos(Phi0) - (1/fabs(omega)) * sin(phii) ); + gsl_matrix_set(J,i,2,((-1.0)*sin(Phi0))/pow(omega,2) - ( (signum(omega))/(pow(fabs(omega),2)) ) * cos(phii) - + (1/fabs(omega)) * sin(phii) * ( ( ((-1.0)/sqrt(1+pow(tanL,2)))*si) + (M_PI)/(2*fabs(omega)) - (signum(omega)*omega*M_PI)/(2*pow(fabs(omega),2)) ) ); + gsl_matrix_set(J,i,3,(-1.0)*sin(Phi0)); + gsl_matrix_set(J,i,4,((-1.0)/fabs(omega))*sin(phii) * ( (omega*tanL*si)/sqrt(pow(1+pow(tanL,2),3)) ) ); + + } + + // part of Jacobi's matrix corresponding to second dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + + gsl_matrix_set(J,i+n,0,0); + gsl_matrix_set(J,i+n,1,((1/omega) - d0)*sin(Phi0) + (1/fabs(omega)) * cos(phii) ); + gsl_matrix_set(J,i+n,2,cos(Phi0)/pow(omega,2) + ( (signum(omega))/(pow(fabs(omega),2)) ) * sin(phii) + + (1/fabs(omega))*cos(phii) * ( ( ((-1.0)/sqrt(1+pow(tanL,2)))*si) + (M_PI)/(2*fabs(omega)) - (signum(omega)*omega*M_PI)/(2*pow(fabs(omega),2)) ) ); + gsl_matrix_set(J,i+n,3,cos(Phi0)); + gsl_matrix_set(J,i+n,4,(1/fabs(omega))*cos(phii) * ( (omega*tanL*si)/sqrt(pow(1+pow(tanL,2),3)) ) ); + + } + + // part of Jacobi's matrix corresponding to third dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + + gsl_matrix_set(J,i+2*n,0,1.0); + gsl_matrix_set(J,i+2*n,1,0); + gsl_matrix_set(J,i+2*n,2,0); + gsl_matrix_set(J,i+2*n,3,0); + gsl_matrix_set(J,i+2*n,4,si/sqrt(1+pow(tanL,2)) - (pow(tanL,2)*si)/sqrt(pow(1+pow(tanL,2),3)) ); + + } + + return GSL_SUCCESS; + +} + +//============================================================================= + +int fdfParametrisation3(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + functParametrisation3(par, d, f); + dfunctParametrisation3(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + + + + +// ########################################## +// ##### ##### +// ##### Constructor and Destructor ##### +// ##### ##### +// ########################################## + +//============================================================================= + +ClusterShapes::ClusterShapes(int nhits, float* a, float* x, float* y, float* z){ + + _nHits = nhits; + _aHit = new float[_nHits]; + _xHit = new float[_nHits]; + _yHit = new float[_nHits]; + _zHit = new float[_nHits]; + _exHit = new float[_nHits]; + _eyHit = new float[_nHits]; + _ezHit = new float[_nHits]; + _types = new int[_nHits]; + + _xl = new float[_nHits]; + _xt = new float[_nHits]; + + _t = new float[_nHits]; + _s = new float[_nHits]; + + for (int i(0); i < nhits; ++i) { + _aHit[i] = a[i]; + _xHit[i] = x[i]; + _yHit[i] = y[i]; + _zHit[i] = z[i]; + _exHit[i] = 1.0; + _eyHit[i] = 1.0; + _ezHit[i] = 1.0; + _types[i] = 1; // all hits are assumed to be "cyllindrical" + } + + _ifNotGravity = 1; + _ifNotWidth = 1; + _ifNotInertia = 1; + _ifNotEigensystem = 1; + +} + + +//============================================================================= + +ClusterShapes::~ClusterShapes() { + + delete[] _aHit; + delete[] _xHit; + delete[] _yHit; + delete[] _zHit; + delete[] _exHit; + delete[] _eyHit; + delete[] _ezHit; + delete[] _types; + delete[] _xl; + delete[] _xt; + delete[] _t; + delete[] _s; +} + +//============================================================================= + +void ClusterShapes::setErrors(float *ex, float *ey, float *ez) { + + for (int i=0; i<_nHits; ++i) { + _exHit[i] = ex[i]; + _eyHit[i] = ey[i]; + _ezHit[i] = ez[i]; + } + +} + +void ClusterShapes::setHitTypes(int* typ) { + for (int i=0; i<_nHits; ++i) { + _types[i] = typ[i]; + + } + +} + + + +// ########################################## +// ##### ##### +// ##### public methods ##### +// ##### ##### +// ########################################## + +//============================================================================= + +int ClusterShapes::getNumberOfHits() { + return _nHits; +} + +//============================================================================= + +float ClusterShapes::getTotalAmplitude() { + if (_ifNotGravity == 1) findGravity(); + return _totAmpl; +} + +//============================================================================= + +float* ClusterShapes::getCentreOfGravity() { + if (_ifNotGravity == 1) findGravity() ; + return &_analogGravity[0] ; +} + +//============================================================================= + +float* ClusterShapes::getEigenValInertia() { + if (_ifNotInertia == 1) findInertia(); + return &_ValAnalogInertia[0] ; +} + +//============================================================================= + +float* ClusterShapes::getEigenVecInertia() { + if (_ifNotInertia == 1) findInertia(); + return &_VecAnalogInertia[0] ; +} + +//============================================================================= + +float ClusterShapes::getWidth() { + if (_ifNotWidth == 1) findWidth(); + return _analogWidth; +} + +//============================================================================= + +int ClusterShapes::getEigenSytemCoordinates(float* xlong, float* xtrans) { + + float xStart[3]; + int index_xStart; + + + // NOT SAVE, change to class variables !!!!! + float X0 = 7.0; + float Rm = 13.5; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + for (int i = 0; i < _nHits; ++i) { + xlong[i] = _xl[i]; + xtrans[i] = _xt[i]; + } + + return 0; // no error messages at the moment + +} + +//============================================================================= + +int ClusterShapes::getEigenSytemCoordinates(float* xlong, float* xtrans, float* a) { + + float xStart[3]; + int index_xStart; + + // NOT SAVE, change to class variables !!!!! + float X0 = 7.0; + float Rm = 13.5; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + for (int i = 0; i < _nHits; ++i) { + xlong[i] = _xl[i]; + xtrans[i] = _xt[i]; + a[i] = _aHit[i]; + } + + return 0; // no error messages at the moment + +} + +//============================================================================= + +int ClusterShapes::fit3DProfile(float& chi2, float& E0, float& A, float& B, float& D, + float& xl0, float* xStart, int& index_xStart, + float X0, float Rm) { + + const int npar = 4; + + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + float* E = new float[_nHits]; + + + double par_init[npar]; + for (int i = 0; i < npar; ++i) par_init[i] = 0.0; // initialise + + float E0_init = 0.0; + float A_init = 0.0; + float B_init = 0.5; // empirically + float D_init = 0.5; // empirically + float t0_init = -10.0/X0; // shift xl0_ini is assumed to be -10.0 without a reason ???? + + float E0_tmp = 0.0; + int i_max = 0; + float t_max = 0.0; + for (int i = 0; i < _nHits; ++i) { + if (E0_tmp < _aHit[i]) { + E0_tmp = _aHit[i]; + i_max = i; + } + E0_init += _aHit[i]; + } + + // first definition + //t_max = _xl[i_max]/X0; + //A_init = t_max*B_init + 1.0; + + // second definition + //t_max = (1.0/3.0) * (t[_nHits-1] - t[0]); + //A_init = t_max*B_init + 1.0; + + // third definition + float Ec = X0 * 0.021/Rm; + A_init = B_init * log(E0_init/Ec) + 0.5 * B_init + 1.0; // (+0.5 for Photons initiated showers) + + + + // par_init[0] = E0_init; + E0 = E0_init; + for (int i = 0; i < _nHits; ++i) E[i] = _aHit[i]/E0_init; + par_init[0] = A_init; // 2.0 + par_init[1] = B_init; + par_init[2] = D_init; + par_init[3] = t0_init; + + // debug + + std::cout << "E0_init : " << E0_init << "\t" << "A_init : " << A_init << "\t" + << "B_init : " << B_init << "\t" << "D_init : " << D_init << "\t" + << "xl0_init : " << t0_init*X0 << "\t" << "X0 : " << X0 + << "\t" << "t_max : " << t_max << std::endl << std::endl; + + + double t0 = xl0/X0; + double par[npar]; + par[0] = A; + par[1] = B; + par[2] = D; + par[3] = t0; + + fit3DProfileAdvanced(chi2,par_init,par,npar,_t,_s,E,E0); + + A = par[0]; + B = par[1]; + D = par[2]; + xl0 = par[3] * X0; + + delete[] E; + + int result = 0; // no error handling at the moment + return result; +} + +//============================================================================= + +float ClusterShapes::getChi2Fit3DProfileSimple(float a, float b, float c, float d, + float X0, float Rm) { + + float chi2 = 0.0; + + float xStart[3]; + int index_xStart; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + chi2 = calculateChi2Fit3DProfileSimple(a,b,c,d); + + return chi2; + +} + +//============================================================================= + +float ClusterShapes::getChi2Fit3DProfileAdvanced(float E0, float a, float b, float d, + float t0, float X0, float Rm) { + + float chi2 = 0.0; + + float xStart[3]; + int index_xStart; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + chi2 = calculateChi2Fit3DProfileAdvanced(E0,a,b,d,t0); + + return chi2; + +} + +//============================================================================= + +int ClusterShapes::FitHelix(int max_iter, int status_out, int parametrisation, + float* parameter, float* dparameter, float& chi2, + float& distmax, int direction) { + + + // Modified by Hengne Li @ LAL + + double parameterdb[5]; + double dparameterdb[5]; + double chi2db; + double distmaxdb; + for ( int i=0; i<5; i++ ){ + parameterdb[i] = double(parameter[i]); + dparameterdb[i] = double(dparameter[i]); + } + chi2db = double(chi2); + distmaxdb = double(distmax); + + int returnvalue = FitHelix(max_iter,status_out,parametrisation,parameterdb,dparameterdb,chi2db,distmaxdb,direction); + + for ( int i=0; i<5; i++ ){ + parameter[i] = float(parameterdb[i]); + dparameter[i] = float(dparameterdb[i]); + } + chi2 = float(chi2db); + distmax = float(distmaxdb); + + return returnvalue ; + +} + +//============================================================================= + +int ClusterShapes::FitHelix(int max_iter, int status_out, int parametrisation, + double* parameter, double* dparameter, double& chi2, + double& distmax, int direction) { + + // FIXME: version with double typed parameters needed 2006/06/10 OW + + if (_nHits < 3) { + std::cout << "ClusterShapes : helix fit impossible, two few points" ; + std::cout << std::endl; + for (int i = 0; i < 5; ++i) { + parameter[i] = 0.0; + dparameter[i] = 0.0; + } + return 1; + } + + // find initial parameters + + double Rmin = 1.0e+10; + double Rmax = -1.0; + int i1 = -1; + + // 1st loop + for (int i(0); i < _nHits; ++i) { + double Rz = sqrt(_xHit[i]*_xHit[i] + _yHit[i]*_yHit[i]); + if (Rz < Rmin) { + Rmin = Rz; + i1 = i; + } + if (Rz > Rmax) { + Rmax = Rz; + } + + } + + + + // debug + /* + for (int i(0); i < _nHits; ++i) std::cout << i << " " << _xHit[i] << " " << _yHit[i] << " " << _zHit[i] << std::endl; + std::cout << std::endl << Rmin << " " << Rmax << " " << i1 << std::endl; + */ + + + + + + // 2nd loop + double Upper = Rmin + 1.1*(Rmax-Rmin); + double Lower = Rmin + 0.9*(Rmax-Rmin); + double dZmin = 1.0e+20; + + int i3 = -1 ; + + for (int i(0); i < _nHits; ++i) { + double Rz = sqrt(_xHit[i]*_xHit[i] + _yHit[i]*_yHit[i]); + if ((Rz > Lower) && (Rz < Upper)) { + double dZ = fabs(_zHit[i]-_zHit[i1]); + if (dZ < dZmin) { + dZmin = dZ; + i3 = i; + } + } + } + + // debug + //std::cout << std::endl << Upper << " " << Lower << " " << dZmin << " " << i3 << std::endl; + + + + + double z1 = std::min(_zHit[i1],_zHit[i3]); + double z3 = std::max(_zHit[i1],_zHit[i3]); + + + int i2 = -1; + double dRmin = 1.0e+20; + double Rref = 0.5 * ( Rmax + Rmin ); + + // 3d loop + + for (int i(0); i < _nHits; ++i) { + if (_zHit[i] >= z1 && _zHit[i] <= z3) { + double Rz = sqrt(_xHit[i]*_xHit[i] + _yHit[i]*_yHit[i]); + double dRz = fabs(Rz - Rref); + if (dRz < dRmin) { + i2 = i; + dRmin = dRz; + } + } + } + + int problematic = 0; + + if (i2 < 0 || i2 == i1 || i2 == i3) { + problematic = 1; + // std::cout << "here we are " << std::endl; + for (int i(0); i < _nHits; ++i) { + if (i != i1 && i != i3) { + i2 = i; + if (_zHit[i2] < z1) { + int itemp = i1; + i1 = i2; + i2 = itemp; + } + else if (_zHit[i2] > z3) { + int itemp = i3; + i3 = i2; + i2 = itemp; + } + break; + } + } + // std::cout << i1 << " " << i2 << " " << i3 << std::endl; + } + + + double x0 = 0.5*(_xHit[i2]+_xHit[i1]); + double y0 = 0.5*(_yHit[i2]+_yHit[i1]); + double x0p = 0.5*(_xHit[i3]+_xHit[i2]); + double y0p = 0.5*(_yHit[i3]+_yHit[i2]); + double ax = _yHit[i2] - _yHit[i1]; + double ay = _xHit[i1] - _xHit[i2]; + double axp = _yHit[i3] - _yHit[i2]; + double ayp = _xHit[i2] - _xHit[i3]; + double det = ax * ayp - axp * ay; + double time; + + if (det == 0.) { + time = 500.; + } + else { + gsl_matrix* A = gsl_matrix_alloc(2,2); + gsl_vector* B = gsl_vector_alloc(2); + gsl_vector* T = gsl_vector_alloc(2); + gsl_matrix_set(A,0,0,ax); + gsl_matrix_set(A,0,1,-axp); + gsl_matrix_set(A,1,0,ay); + gsl_matrix_set(A,1,1,-ayp); + gsl_vector_set(B,0,x0p-x0); + gsl_vector_set(B,1,y0p-y0); + gsl_linalg_HH_solve(A,B,T); + time = gsl_vector_get(T,0); + gsl_matrix_free(A); + gsl_vector_free(B); + gsl_vector_free(T); + } + + double X0 = x0 + ax*time; + double Y0 = y0 + ay*time; + + double dX = _xHit[i1] - X0; + double dY = _yHit[i1] - Y0; + + double R0 = sqrt(dX*dX + dY*dY); + + /* + if (problematic == 1) { + std::cout << i1 << " " << i2 << " " << i3 << std::endl; + std::cout << _xHit[i1] << " " << _yHit[i1] << " " << _zHit[i1] << std::endl; + std::cout << _xHit[i2] << " " << _yHit[i2] << " " << _zHit[i2] << std::endl; + std::cout << _xHit[i3] << " " << _yHit[i3] << " " << _zHit[i3] << std::endl; + std::cout << "R0 = " << R0 << std::endl; + } + */ + + double phi1 = (double)atan2(_yHit[i1]-Y0,_xHit[i1]-X0); + double phi2 = (double)atan2(_yHit[i2]-Y0,_xHit[i2]-X0); + double phi3 = (double)atan2(_yHit[i3]-Y0,_xHit[i3]-X0); + +// testing bz > 0 hypothesis + + if ( phi1 > phi2 ) + phi2 = phi2 + 2.0*M_PI; + if ( phi1 > phi3 ) + phi3 = phi3 + 2.0*M_PI; + if ( phi2 > phi3 ) + phi3 = phi3 + 2.0*M_PI; + + double bz_plus = (phi3 - phi1) / (_zHit[i3]-_zHit[i1]); + double phi0_plus = phi1 - bz_plus * _zHit[i1]; + double dphi_plus = fabs( bz_plus * _zHit[i2] + phi0_plus - phi2 ); + +// testing bz < 0 hypothesis + + phi1 = (double)atan2(_yHit[i1]-Y0,_xHit[i1]-X0); + phi2 = (double)atan2(_yHit[i2]-Y0,_xHit[i2]-X0); + phi3 = (double)atan2(_yHit[i3]-Y0,_xHit[i3]-X0); + + if ( phi1 < phi2 ) + phi2 = phi2 - 2.0*M_PI; + if ( phi1 < phi3 ) + phi3 = phi3 - 2.0*M_PI; + if ( phi2 < phi3 ) + phi3 = phi3 - 2.0*M_PI; + + double bz_minus = (phi3 - phi1) / (_zHit[i3]-_zHit[i1]); + double phi0_minus = phi1 - bz_minus * _zHit[i1]; + double dphi_minus = fabs( bz_minus * _zHit[i2] + phi0_minus - phi2 ); + + double bz; + double phi0; + + if (dphi_plus < dphi_minus) { + bz = bz_plus; + phi0 = phi0_plus; + } + else { + bz = bz_minus; + phi0 = phi0_minus; + + } + + double par_init[5]; + + if (parametrisation == 1) { + par_init[0] = (double)X0; + par_init[1] = (double)Y0; + par_init[2] = (double)R0; + par_init[3] = (double)bz; + par_init[4] = (double)phi0; + } + else if (parametrisation == 2) { + par_init[0] = (double)X0; + par_init[1] = (double)Y0; + par_init[2] = (double)(-phi0/bz); + par_init[3] = (double)R0; + par_init[4] = (double)(1/bz); + } + + else if (parametrisation == 3) { // parameter vector: (z0,Phi0,omega,d0,tanL) + + // debug + // std::cout << std::setprecision(6) << "InitFit (X0,Y0,R0,bz,phi0) = " << "(" << X0 << "," << Y0 << "," << R0 << "," << bz << "," << phi0 << ")" << std::endl; + + + // debug + /* + X0 = -1205.28; + Y0 = 175.317; + R0 = 1217.97; + bz = 0.00326074; + phi0 = -0.144444; + */ + + + // debug + // std::cout << std::setprecision(6) << "InitUsed (X0,Y0,R0,bz,phi0) = " << "(" << X0 << "," << Y0 << "," << R0 << "," << bz << "," << phi0 << ")" << std::endl; + + double omega = 1/R0*direction; + double tanL = (-1.0)*omega/bz; + + double Phi0 = (-1.0)*atan2(X0,Y0); + + if (direction == 1) { + + if (tanL >= 0.0) Phi0 += M_PI; // add pi (see LC-DET-2006-004) // >= or > ? + else Phi0 -= M_PI; // < or <= ? + + } + + //double d0 = R0 - X0/sin(Phi0); + //double d0 = R0 + Y0/cos(Phi0); + + double d0 = 0.0; + if (true /*direction != 1*/) d0 = R0 - sqrt(X0*X0 + Y0*Y0); + // else d0 = R0 + sqrt(X0*X0 + Y0*Y0); + + + + // double d0 = R0 - ( (X0-Y0)/(sqrt(2.0)*cos(pi/4 - Phi0)) ); + // double d0 = R0 - ((X0-Y0)/(sin(Phi0)+cos(Phi0))); + + // double Phi0 = asin(X0/(R0-d0)); + + + double z0 = (1/bz)*((-1.0)*phi0+Phi0+(omega*M_PI)/(2.0*fabs(omega))); + + + // debug + /* + std::cout << std::setprecision(6) << "InitFitCalculated (d0,z0,phi0,omega,tanL) = " << "(" << d0 << "," << z0 << "," << Phi0 << "," << omega << "," << tanL << ")" + << " " << "sign(omega) = " << direction << std::endl; + */ + + // debug + /* + d0 = 0.00016512; + z0 = 0.000853511; + Phi0 = 1.11974; + omega = -4.22171e-05; + tanL = -0.33436; + */ + + + + + // debug + // std::cout << std::setprecision(6) << "InitFitUsed (d0,z0,phi0,omega,tanL) = " << "(" << d0 << "," << z0 << "," << Phi0 << "," << omega << "," << tanL << ")" << std::endl; + + par_init[0] = z0; + par_init[1] = Phi0; + par_init[2] = omega; + par_init[3] = d0; + par_init[4] = tanL; + } + else return 1; + + + // local variables + int status = 0; + int iter = 0; + + int npar = 5; // five parameters to fit + int ndim = 0; + if (parametrisation == 1) ndim = 2; // two dependent dimensions + else if (parametrisation == 2) ndim = 3; // three dependent dimensions + else if (parametrisation == 3) ndim = 3; // three dependent dimensions + + else return 1; + + + + double chi2_nofit = 0.0; + int iFirst = 1; + for (int ipoint(0); ipoint < _nHits; ipoint++) { + double distRPZ[2]; + double Dist = DistanceHelix(_xHit[ipoint],_yHit[ipoint],_zHit[ipoint], + X0,Y0,R0,bz,phi0,distRPZ); + double chi2rphi = distRPZ[0]/_exHit[ipoint]; + chi2rphi = chi2rphi*chi2rphi; + double chi2z = distRPZ[1]/_ezHit[ipoint]; + chi2z = chi2z*chi2z; + chi2_nofit = chi2_nofit + chi2rphi + chi2z; + if (Dist > distmax || iFirst == 1) { + distmax = Dist; + iFirst = 0; + } + } + chi2_nofit = chi2_nofit/double(_nHits); + + if ( status_out == 1 ) { + for (int i(0); i < 5; ++i) { + parameter[i] = (double)par_init[i]; + dparameter[i] = 0.0; + } + chi2 = chi2_nofit; + return 0; + } + + // converging criteria + const double abs_error = 1e-4; + const double rel_error = 1e-4; + + gsl_multifit_function_fdf fitfunct; + + const gsl_multifit_fdfsolver_type* T = gsl_multifit_fdfsolver_lmsder; + + gsl_multifit_fdfsolver* s = gsl_multifit_fdfsolver_alloc(T,ndim*_nHits,npar); + + gsl_matrix* covar = gsl_matrix_alloc(npar,npar); // covariance matrix + + data d; + d.n = _nHits; + d.x = &_xHit[0]; + d.y = &_yHit[0]; + d.z = &_zHit[0]; + d.ex = &_exHit[0]; + d.ey = &_eyHit[0]; + d.ez = &_ezHit[0]; + + + if (parametrisation == 1) { + fitfunct.f = &functParametrisation1; + fitfunct.df = &dfunctParametrisation1; + fitfunct.fdf = &fdfParametrisation1; + fitfunct.n = ndim*_nHits; + fitfunct.p = npar; + fitfunct.params = &d; + } + else if (parametrisation == 2) { + fitfunct.f = &functParametrisation2; + fitfunct.df = &dfunctParametrisation2; + fitfunct.fdf = &fdfParametrisation2; + fitfunct.n = ndim*_nHits; + fitfunct.p = npar; + fitfunct.params = &d; + } + else if (parametrisation == 3) { + fitfunct.f = &functParametrisation3; + fitfunct.df = &dfunctParametrisation3; + fitfunct.fdf = &fdfParametrisation3; + fitfunct.n = ndim*_nHits; + fitfunct.p = npar; + fitfunct.params = &d; + } + else return 1; + + gsl_vector_view pinit = gsl_vector_view_array(par_init,npar); + gsl_multifit_fdfsolver_set(s,&fitfunct,&pinit.vector); + + // perform fit + do { + iter++; + status = gsl_multifit_fdfsolver_iterate(s); + + if (status) break; + status = gsl_multifit_test_delta (s->dx, s->x,abs_error,rel_error); + + } while ( status==GSL_CONTINUE && iter < max_iter); + + gsl_multifit_covar (s->J, rel_error, covar); + + + + chi2 = 0.0; + + if (parametrisation == 1) { + X0 = (double)gsl_vector_get(s->x,0); + Y0 = (double)gsl_vector_get(s->x,1); + R0 = (double)gsl_vector_get(s->x,2); + bz = (double)gsl_vector_get(s->x,3); + phi0 = (double)gsl_vector_get(s->x,4); + } + else if (parametrisation == 2) { + X0 = (double)gsl_vector_get(s->x,0); + Y0 = (double)gsl_vector_get(s->x,1); + R0 = (double)gsl_vector_get(s->x,3); + bz = (double)(1/gsl_vector_get(s->x,4)); + phi0 = (double)(-gsl_vector_get(s->x,2)/gsl_vector_get(s->x,4)); + } + else if (parametrisation == 3) { // (parameter vector: (z0,phi0,omega,d0,tanL) + + double z0 = gsl_vector_get(s->x,0); + double Phi0 = gsl_vector_get(s->x,1); + double omega = gsl_vector_get(s->x,2); + double d0 = gsl_vector_get(s->x,3); + double tanL = gsl_vector_get(s->x,4); + + X0 = (double)( ( (1/omega) - d0 )*sin(Phi0) ); + Y0 = (double)( (-1)*( (1/omega) - d0 )*cos(Phi0) ); + R0 = (double)( 1/fabs(omega) ); + bz = (double)( (-1)*(omega/tanL) ); + phi0 = (double)( ( (z0*omega)/tanL ) + Phi0 + ( (omega*M_PI)/(2*fabs(omega)) ) ); + } + else return 1; + + iFirst = 1; + double ddmax = 0.0; + for (int ipoint(0); ipoint < _nHits; ipoint++) { + double distRPZ[2]; + double Dist = DistanceHelix(_xHit[ipoint],_yHit[ipoint],_zHit[ipoint], + X0,Y0,R0,bz,phi0,distRPZ); + double chi2rphi = distRPZ[0]/_exHit[ipoint]; + chi2rphi = chi2rphi*chi2rphi; + double chi2z = distRPZ[1]/_ezHit[ipoint]; + chi2z = chi2z*chi2z; + chi2 = chi2 + chi2rphi + chi2z; + if (Dist > ddmax || iFirst == 1) { + iFirst = 0; + ddmax = Dist; + } + } + + + chi2 = chi2/double(_nHits); + if (chi2 < chi2_nofit) { + for (int i = 0; i < npar; i++) { + parameter[i] = gsl_vector_get(s->x,i); + dparameter[i] = sqrt(gsl_matrix_get(covar,i,i)); + } + distmax = ddmax; + } + else { + chi2 = chi2_nofit; + for (int i = 0; i < npar; i++) { + parameter[i] = (double)par_init[i]; + dparameter[i] = 0.0; + } + } + + // if (problematic == 1) + // std::cout << "chi2 = " << chi2 << std::endl; + + gsl_multifit_fdfsolver_free(s); + gsl_matrix_free(covar); + return 0; + +} + + + +// ########################################## +// ##### ##### +// ##### private methods ##### +// ##### ##### +// ########################################## + +//============================================================================= + +void ClusterShapes::findElipsoid() { + + /** Elipsoid parameter calculations see cluster_proper.f */ + float cx,cy,cz ; + float dx,dy,dz ; + float r_hit_max, d_begn, d_last, r_max, proj; + if (_ifNotInertia == 1) findInertia() ; + // Normalize the eigen values of inertia tensor + float wr1 = sqrt(_ValAnalogInertia[0]/_totAmpl); + float wr2 = sqrt(_ValAnalogInertia[1]/_totAmpl); + float wr3 = sqrt(_ValAnalogInertia[2]/_totAmpl); + _r1 = sqrt(wr2*wr3); // spatial axis length -- the largest + _r2 = sqrt(wr1*wr3); // spatial axis length -- less + _r3 = sqrt(wr1*wr2); // spatial axis length -- even more less + _vol = 4.*M_PI*_r1*_r2*_r3/3.; // ellipsoid volume + _r_ave = pow(_vol,1/3); // average radius (quibc root) + _density = _totAmpl/_vol; // density + // _eccentricity = _r_ave/_r1; // Cluster Eccentricity + _eccentricity =_analogWidth/_r1; // Cluster Eccentricity + + // Find Minumal and Maximal Lenght for Principal axis + r_hit_max = -100000.; + d_begn = 100000.; + d_last = -100000.; + cx = _VecAnalogInertia[0] ; + cy = _VecAnalogInertia[1] ; + cz = _VecAnalogInertia[2] ; + for (int i(0); i < _nHits; ++i) { + dx = _xHit[i] - _xgr; + dy = _yHit[i] - _ygr; + dz = _zHit[i] - _zgr; + r_max = sqrt(dx*dx + dy*dy + dz*dz);; + if(r_max > r_hit_max) r_hit_max = r_max; + proj = dx*cx + dy*cy + dz*cz; + if(proj < d_begn) + d_begn = proj; + // lad_begn = ladc(L) + if(proj > d_last) + d_last = proj; + // lad_last = ladc(L) + } + // if (r_hit_max > 0.0) + // _r1 = 1.05*r_hit_max; // + 5% of length + _r1_forw = fabs(d_last); + _r1_back = fabs(d_begn); +} + +//============================================================================= + +void ClusterShapes::findGravity() { + + _totAmpl = 0. ; + for (int i(0); i < 3; ++i) { + _analogGravity[i] = 0.0 ; + } + for (int i(0); i < _nHits; ++i) { + _totAmpl+=_aHit[i] ; + _analogGravity[0]+=_aHit[i]*_xHit[i] ; + _analogGravity[1]+=_aHit[i]*_yHit[i] ; + _analogGravity[2]+=_aHit[i]*_zHit[i] ; + } + for (int i(0); i < 3; ++i) { + _analogGravity[i]/=_totAmpl ; + } + _xgr = _analogGravity[0]; + _ygr = _analogGravity[1]; + _zgr = _analogGravity[2]; + _ifNotGravity = 0; +} + +//============================================================================= + +void ClusterShapes::findInertia() { + + double aIne[3][3]; + // float radius1; + float radius2 = 0.0; + + findGravity(); + + for (int i(0); i < 3; ++i) { + for (int j(0); j < 3; ++j) { + aIne[i][j] = 0.0; + } + } + + for (int i(0); i < _nHits; ++i) { + float dX = _xHit[i] - _analogGravity[0]; + float dY = _yHit[i] - _analogGravity[1]; + float dZ = _zHit[i] - _analogGravity[2]; + aIne[0][0] += _aHit[i]*(dY*dY+dZ*dZ); + aIne[1][1] += _aHit[i]*(dX*dX+dZ*dZ); + aIne[2][2] += _aHit[i]*(dX*dX+dY*dY); + aIne[0][1] -= _aHit[i]*dX*dY; + aIne[0][2] -= _aHit[i]*dX*dZ; + aIne[1][2] -= _aHit[i]*dY*dZ; + } + + for (int i(0); i < 2; ++i) { + for (int j = i+1; j < 3; ++j) { + aIne[j][i] = aIne[i][j]; + } + } + //**************************************** + // analog Inertia + //**************************************** + + gsl_matrix_view aMatrix = gsl_matrix_view_array((double*)aIne,3,3); + gsl_vector* aVector = gsl_vector_alloc(3); + gsl_matrix* aEigenVec = gsl_matrix_alloc(3,3); + gsl_eigen_symmv_workspace* wa = gsl_eigen_symmv_alloc(3); + gsl_eigen_symmv(&aMatrix.matrix,aVector,aEigenVec,wa); + gsl_eigen_symmv_free(wa); + gsl_eigen_symmv_sort(aVector,aEigenVec,GSL_EIGEN_SORT_ABS_ASC); + + for (int i(0); i < 3; i++) { + _ValAnalogInertia[i] = gsl_vector_get(aVector,i); + for (int j(0); j < 3; j++) { + _VecAnalogInertia[i+3*j] = gsl_matrix_get(aEigenVec,i,j); + } + } + + // Main principal points away from IP + + _radius = 0.; + radius2 = 0.; + + for (int i(0); i < 3; ++i) { + _radius += _analogGravity[i]*_analogGravity[i]; + radius2 += (_analogGravity[i]+_VecAnalogInertia[i])*(_analogGravity[i]+_VecAnalogInertia[i]); + } + + if ( radius2 < _radius) { + for (int i(0); i < 3; ++i) + _VecAnalogInertia[i] = - _VecAnalogInertia[i]; + } + + _radius = sqrt(_radius); + _ifNotInertia = 0; + + // The final job + findWidth(); + findElipsoid(); + + gsl_vector_free(aVector); + gsl_matrix_free(aEigenVec); + +} + +//============================================================================= + +void ClusterShapes::findWidth() { + + float dist = 0.0; + if (_ifNotInertia == 1) findInertia() ; + _analogWidth = 0.0 ; + for (int i(0); i < _nHits; ++i) { + dist = findDistance(i) ; + _analogWidth+=_aHit[i]*dist*dist ; + } + _analogWidth = sqrt(_analogWidth / _totAmpl) ; + _ifNotWidth = 0 ; +} + +//============================================================================= + +float ClusterShapes::findDistance(int i) { + + float cx = 0.0; + float cy = 0.0; + float cz = 0.0; + float dx = 0.0; + float dy = 0.0; + float dz = 0.0; + cx = _VecAnalogInertia[0] ; + cy = _VecAnalogInertia[1] ; + cz = _VecAnalogInertia[2] ; + dx = _analogGravity[0] - _xHit[i] ; + dy = _analogGravity[1] - _yHit[i] ; + dz = _analogGravity[2] - _zHit[i] ; + float tx = cy*dz - cz*dy ; + float ty = cz*dx - cx*dz ; + float tz = cx*dy - cy*dx ; + float tt = sqrt(tx*tx+ty*ty+tz*tz) ; + float ti = sqrt(cx*cx+cy*cy+cz*cz) ; + float f = tt / ti ; + return f ; +} +/** + Function sdist(xp,yp,zp,cx,cy,cz,xv,yv,zv) +c---------------------------------------------------------------------- +c Distance from line to point +c xp, yp, zp -- point is at the line +c xv, yv, zv -- point is out of line +******************************************************************** +* Last update V.L.Morgunov 08-Apr-2002 * +******************************************************************** + real xp,yp,zp,cx,cy,cz,xv,yv,zv,t1,t2,t3,tt,sdist + + t1 = cy*(zp-zv)-cz*(yp-yv) + t2 = cz*(xp-xv)-cx*(zp-zv) + t3 = cx*(yp-yv)-cy*(xp-xv) + tt = sqrt(cx**2+cy**2+cz**2) + sdist = sqrt(t1**2+t2**2+t3**2)/tt + + return + end +*/ + +//============================================================================= + +float ClusterShapes::vecProduct(float * x1, float * x2) { + + float x1abs(0.); + float x2abs(0.); + float prod(0.); + + for (int i(0); i < 3; ++i) { + x1abs += x1[i]*x1[i]; + x2abs += x2[i]*x2[i]; + prod += x1[i]*x2[i]; + } + + + x1abs = sqrt(x1abs); + x2abs = sqrt(x2abs); + + if (x1abs > 0.0 && x2abs > 0.0) { + prod = prod/(x1abs*x2abs); + } + else { + prod = 0.; + } + + return prod; + +} + +//============================================================================= + +float ClusterShapes::vecProject(float * x, float * axis) { + float axisabs(0.); + float prod(0.); + for (int i(0); i < 3; ++i) { + axisabs += axis[i]*axis[i]; + prod += x[i]*axis[i]; + } + axisabs = sqrt(axisabs); + if (axisabs > 0.0 ) { + prod = prod/axisabs; + } + else { + prod = 0.; + } + return prod; +} + +//============================================================================= + +double ClusterShapes::DistanceHelix(double x, double y, double z, double X0, double Y0, + double R0, double bz, double phi0, double * distRPZ) { + + double phi = atan2(y-Y0,x-X0); + double R = sqrt( (y-Y0)*(y-Y0) + (x-X0)*(x-X0) ); + double dXY2 = (R-R0)*(R-R0); + double _const_2pi = 2.0*M_PI; + double xN = (bz*z + phi0 - phi)/_const_2pi; + + int n1 = 0; + int n2 = 0; + int nSpirals = 0; + + if (xN > 0) { + n1 = (int)xN; + n2 = n1 + 1; + } + else { + n1 = (int)xN - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xN) < fabs(n2-xN)) { + nSpirals = n1; + } + else { + nSpirals = n2; + } + + double dZ = (phi + _const_2pi*nSpirals - phi0)/bz - z; + double dZ2 = dZ*dZ; + + distRPZ[0] = sqrt(dXY2); + distRPZ[1] = sqrt(dZ2); + + return sqrt(dXY2 + dZ2); + +} + +//============================================================================= + +int ClusterShapes::transformToEigensystem(float* xStart, int& index_xStart, float X0, + float Rm) { + + if (_ifNotInertia == 1) findInertia(); + + float MainAxis[3]; + float MainCentre[3]; + + + MainAxis[0] = _VecAnalogInertia[0]; + MainAxis[1] = _VecAnalogInertia[1]; + MainAxis[2] = _VecAnalogInertia[2]; + MainCentre[0] = _analogGravity[0]; + MainCentre[1] = _analogGravity[1]; + MainCentre[2] = _analogGravity[2]; + + int ifirst = 0; + float xx[3]; + float prodmin = 0.0; + int index = 0; + + for (int i(0); i < _nHits; ++i) { + xx[0] = _xHit[i] - MainCentre[0]; + xx[1] = _yHit[i] - MainCentre[1]; + xx[2] = _zHit[i] - MainCentre[2]; + float prod = vecProject(xx,MainAxis); + if (ifirst == 0 || prod < prodmin) { + ifirst = 1; + prodmin = prod; + index = i; + } + } + xStart[0] = MainCentre[0] + prodmin*MainAxis[0]; + xStart[1] = MainCentre[1] + prodmin*MainAxis[1]; + xStart[2] = MainCentre[2] + prodmin*MainAxis[2]; + index_xStart = index; + + for (int i(0); i < _nHits; ++i) { + xx[0] = _xHit[i] - xStart[0]; + xx[1] = _yHit[i] - xStart[1]; + xx[2] = _zHit[i] - xStart[2]; + float xx2(0.); + for (int j(0); j < 3; ++j) xx2 += xx[j]*xx[j]; + + _xl[i] = 0.001 + vecProject(xx,MainAxis); + _xt[i] = sqrt(std::max(0.0,xx2 + 0.1 - _xl[i]*_xl[i])); + // std::cout << i << " " << _xl[i] << " " << _xt[i] << " " << _aHit[i] << " " + // << std::endl; + } + + for (int i = 0; i < _nHits; ++i) { + _t[i] = _xl[i]/X0; + _s[i] = _xt[i]/Rm; + } + + _ifNotEigensystem = 0; + + return 0; // no error messages at the moment + +} + +//============================================================================= + +float ClusterShapes::calculateChi2Fit3DProfileSimple(float a, float b, float c, + float d) { + + // ClusterShapes::transformToEigensystem needs to be executed before + + float chi2 = 0.0; + float Ampl = 0.0; + + for (int i(0); i < _nHits; ++i) { + // old definition of Ampl and chi2 + //Ampl = a*(float)pow(_xl[i],b)*exp(-c*_xl[i]-d*_xt[i]); + //chi2 += ((Ampl - _aHit[i])*(Ampl - _aHit[i]))/(_aHit[i]*_aHit[i]); + + Ampl = a*(float)pow(_xl[i],b)*exp(-c*_xl[i]-d*_xt[i]); + chi2 += (log(_aHit[i]) - log(Ampl))*(log(_aHit[i]) - log(Ampl)); + } + + chi2 = chi2/std::max((float)1.0,(float)(_nHits - 4)); + + return chi2; + +} + +//============================================================================= + +float ClusterShapes::calculateChi2Fit3DProfileAdvanced(float E0, float a, float b, + float d, float t0) { + + // ClusterShapes::transformToEigensystem needs to be executed before + + float chi2 = 0.0; + float Ampl = 0.0; + float shift = 0.0; + + for (int i(0); i < _nHits; ++i) { + + shift = _t[i]-t0; + + if (shift <= 0) Ampl = 0.0; + else { + Ampl = E0 * b * invG(a) * pow(b*(shift),a-1) + * exp(-b*(shift)) * exp(-d*_s[i]); + } + + // debug + /* + std::cout << "OUT : " << Ampl << " " << E0 << " " << a << " " << b << " " + << d << " " << t0 << " " << _t[i] << " " << invG(a) << " " + << pow(b*(_t[i]-t0),a-1) << " " << exp(-b*(_t[i]-t0)) << " " + << exp(-d*_s[i]) + << std::endl; + */ + + chi2 += ((Ampl - _aHit[i])*(Ampl - _aHit[i]))/(_aHit[i]*_aHit[i]); + //chi2 += (log(_aHit[i]) - log(Ampl))*(log(_aHit[i]) - log(Ampl)); + //chi2 += log((Ampl - _aHit[i])*(Ampl - _aHit[i]))/log(_aHit[i]*_aHit[i]); + + } + chi2 = chi2/std::max((float)1.0,(float)(_nHits - 4)); + + return chi2; + +} + +//============================================================================= + +int ClusterShapes::fit3DProfileSimple(float& chi2, float& a, float& b, float& c, + float& d) { + + // Fit function: _aHit[i] = a * pow(_xl[i],b) * exp(-c*_xl[i]) * exp(-d*_xt[i]) + + float Slnxl(0.); + float Sxl(0.); + float Sxt(0.); + float Sln2xl(0.); + float Sxllnxl(0.); + float Sxtlnxl(0.); + float Sxlxl(0.); + float Sxlxt(0.); + float Sxtxt(0.); + float SlnA(0.); + float SlnAlnxl(0.); + float SlnAxl(0.); + float SlnAxt(0.); + + // for a quadratic matrix + for (int i = 0; i < _nHits; i++) { + Slnxl += log(_xl[i]); + Sxl += _xl[i]; + Sxt += _xt[i]; + Sln2xl += log(_xl[i])*log(_xl[i]); + Sxllnxl += _xl[i]*log(_xl[i]); + Sxtlnxl += _xt[i]*log(_xl[i]); + Sxlxl += _xl[i]*_xl[i]; + Sxlxt += _xl[i]*_xt[i]; + Sxtxt += _xt[i]*_xt[i]; + SlnA += log(_aHit[i]); + SlnAlnxl += log(_aHit[i])*log(_xl[i]); + SlnAxl += log(_aHit[i])*_xl[i]; + SlnAxt += log(_aHit[i])*_xt[i]; + } + // create system of linear equations, written as Ae = z + + gsl_matrix* A = gsl_matrix_alloc(4,4); + gsl_vector* z = gsl_vector_alloc(4); + gsl_vector* e = gsl_vector_alloc(4); + + // initialise matrix and vectors + + gsl_matrix_set(A,0,0,_nHits); + gsl_matrix_set(A,0,1,Slnxl); + gsl_matrix_set(A,0,2,-Sxl); + gsl_matrix_set(A,0,3,-Sxt); + + gsl_matrix_set(A,1,0,Slnxl); + gsl_matrix_set(A,1,1,Sln2xl); + gsl_matrix_set(A,1,2,-Sxllnxl); + gsl_matrix_set(A,1,3,-Sxtlnxl); + + gsl_matrix_set(A,2,0,-Sxl); + gsl_matrix_set(A,2,1,-Sxllnxl); + gsl_matrix_set(A,2,2,Sxlxl); + gsl_matrix_set(A,2,3,Sxlxt); + + gsl_matrix_set(A,3,0,-Sxt); + gsl_matrix_set(A,3,1,-Sxtlnxl); + gsl_matrix_set(A,3,2,Sxlxt); + gsl_matrix_set(A,3,3,Sxtxt); + + gsl_vector_set(z,0,SlnA); + gsl_vector_set(z,1,SlnAlnxl); + gsl_vector_set(z,2,-SlnAxl); + gsl_vector_set(z,3,-SlnAxt); + + gsl_linalg_HH_solve(A,z,e); + + a = exp(gsl_vector_get(e,0)); + b = gsl_vector_get(e,1); + c = gsl_vector_get(e,2); + d = gsl_vector_get(e,3); + + chi2 = calculateChi2Fit3DProfileSimple(a,b,c,d); + + gsl_matrix_free(A); + gsl_vector_free(z); + gsl_vector_free(e); + + int result = 0; // no error handling at the moment + return result; + +} + +//============================================================================= + +int ClusterShapes::fit3DProfileAdvanced(float& chi2, double* par_init, double* par, + int npar, float* t, float* s, float* E, + float E0) { + + // local variables + int status = 0; + int iter = 0; + int max_iter = 1000; + + + // converging criteria + const double abs_error = 0.0; + const double rel_error = 1e-1; + + + + gsl_multifit_function_fdf fitfunct; + + const gsl_multifit_fdfsolver_type* T = gsl_multifit_fdfsolver_lmsder; + + gsl_multifit_fdfsolver* Solver = gsl_multifit_fdfsolver_alloc(T,_nHits,npar); + + gsl_matrix* covar = gsl_matrix_alloc(npar,npar); // covariance matrix + + data DataSet; + DataSet.n = _nHits; + DataSet.x = &t[0]; + DataSet.y = &s[0]; + DataSet.z = &E[0]; // _aHit[0]; // ???? normalise per volume ???? + + + fitfunct.f = &ShapeFitFunct; + fitfunct.df = &dShapeFitFunct; + fitfunct.fdf = &fdfShapeFitFunct; + fitfunct.n = _nHits; + fitfunct.p = npar; + fitfunct.params = &DataSet; + + gsl_vector_view pinit = gsl_vector_view_array(par_init,npar); + gsl_multifit_fdfsolver_set(Solver,&fitfunct,&pinit.vector); + + gsl_set_error_handler_off(); + + // perform fit + do { + iter++; + std::cout << "Multidimensional Fit Iteration started ... ... "; + status = gsl_multifit_fdfsolver_iterate(Solver); + std::cout << "--- DONE ---" << std::endl; + + if (status) break; + status = gsl_multifit_test_delta (Solver->dx,Solver->x,abs_error,rel_error); + + // debug + /* + // E0 = (float)gsl_vector_get(Solver->x,0); + par[0] = (float)gsl_vector_get(Solver->x,0); + par[1] = (float)gsl_vector_get(Solver->x,1); + par[2] = (float)gsl_vector_get(Solver->x,2); + par[3] = (float)gsl_vector_get(Solver->x,3); + + std::cout << "Status of multidimensional fit : " << status << " " + << "Iterations : " << iter << std::endl; + std::cout << "E0 : " << "FIXED" << "\t" << "A : " << par[0] << "\t" << "B : " + << par[1] << "\t" << "D : " << par[2] << "\t" << "t0 : " << par[3] + << std::endl << std::endl; + */ + + } while ( status==GSL_CONTINUE && iter < max_iter); + + gsl_multifit_covar (Solver->J,rel_error,covar); + + // E0 = (float)gsl_vector_get(Solver->x,0); + par[0] = (float)gsl_vector_get(Solver->x,0); // A + par[1] = (float)gsl_vector_get(Solver->x,1); // B + par[2] = (float)gsl_vector_get(Solver->x,2); // D + par[3] = (float)gsl_vector_get(Solver->x,3); // t0 + + gsl_multifit_fdfsolver_free(Solver); + gsl_matrix_free(covar); + + chi2 = calculateChi2Fit3DProfileAdvanced(E0,par[0],par[1],par[2],par[3]); + if (status) chi2 = -1.0; + + int result = 0; // no error handling at the moment + return result; + +} + +//============================================================================= + diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h new file mode 100644 index 00000000..2b97b685 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h @@ -0,0 +1,356 @@ +#ifndef ClusterShapes_h +#define ClusterShapes_h + + +#include <stdio.h> +#include <iostream> +#include <iomanip> +#include <string> +#include <sstream> +#include <cstdlib> +#include "HelixClass.h" +#include <math.h> + + +/** + * Utility class to derive properties of clusters, such as centre of gravity, + * axes of inertia, fits of the cluster shape and so on. All the details are + * explained in the documentation of the methods. Several classes of the GSL + * (GNU Scientific Library) are needed in this class. + * + * @authors V. Morgunov (ITEP/DESY), A. Raspereza (DESY), O. Wendt (DESY) + * @version $Id: ClusterShapes.h,v 1.14 2007-04-27 13:56:53 owendt Exp $ + * + */ +class ClusterShapes { + + public: + + /** + * Constructor + * @param nhits : number of hits in the cluster + * @param a : amplitudes of elements ('cells') of the cluster. Stored in + * an array, with one entry for each element ('cell'). Each entry + * is depending on coordinates x,y,z (Cartesian), which are stored + * in the arrays x,y,z. + * @param x,y,z : array of coordinates corresponding to the array of amplitudes a. + * + * + */ + ClusterShapes(int nhits, float* a, float* x, float* y, float* z); + + + /** + * Destructor + */ + ~ClusterShapes(); + + /** + * Defining errors for Helix Fit + */ + void setErrors(float *ex, float* ey, float *ez); + + /** + * Defining hit types for Helix Fit : + * type 1 - cyllindrical detector + * type 2 - Z disk detector + */ + void setHitTypes(int *ityp); + + + /** + * returns the number of elements of the cluster + */ + int getNumberOfHits(); + + /** + * returns the accumulated amplitude for the whole cluster (just the sum of the + * energy in all the entries of the cluster) + */ + float getTotalAmplitude(); + + /** + * returns an array, which represents a vector from the origin of the + * coordiante system, i.\ e.\ IP, to the centre of gravity of the cluster. The centre + * of gravity is calculated with the energy of the entries of the cluster. + */ + float* getCentreOfGravity(); + + /** US spelling of getCentreOfGravity */ + inline float* getCenterOfGravity() { return getCentreOfGravity() ; } + + /** + * array of the inertias of mass (i.\ e.\ energy) corresponding to the three main axes + * of inertia. The array is sorted in ascending order. + */ + float* getEigenValInertia(); + + /** + * array of the three main axes of inertia (9 entries) starting + * with the axis corresponding to the smallest inertia of mass + * (main principal axis). All axes are normalised to a length + * of 1. + */ + float* getEigenVecInertia(); + + /** + * 'mean' width of the cluster perpendicular to the main + * principal axis, defined as: + * width := sqrt( 1/TotalAmplitude * Sum(a[i]*d[i]*d[i]) ), + * where d[i] is the distance of the i-th point to the main + * principal axis. + */ + float getWidth(); + + /** + * returns the coordinates of the cluster transformed into + * the CoG-System. + * @param xlong : pointer to an array, where the calculated longitudinal coordiantes + * are stored in. + * @param xtrans : pointer to an array, where the calculated transversal coordiantes + * are stored in. + */ + int getEigenSytemCoordinates(float* xlong, float* xtrans); + + /** + * returns the coordinates and the amplitudes of the cluster + * transformed into the CoG-System. + * @param xlong : pointer to an array, where the calculated longitudinal coordiantes + * are stored in. + * @param xtrans : pointer to an array, where the calculated transversal coordiantes + * are stored in. + * @param a : pointer to an array, where the amplitudes corresponding to the + * longitudinal and transversal coordiantes are stored in. + */ + int getEigenSytemCoordinates(float* xlong, float* xtrans, float* a); + + /** + * performs a least square fit on the shape of an electro- + * magnetic-shower, which is defined as: + * A[i] = a * (xl[i]-xl0)^b * exp(-c*(xl[i]-xl0)) * exp(-d*xt[i]), + * where A[i] is the array of amplitudes, xl[i] is the + * coordinate of the actual point along the main principal + * axis and xt[i] the coordinate perpendicular to it. The return value + * of the method itself is not used at the moment (always returns 0). + * @param a,b,c,d,xl0 : references to the parameters, which are fitted. + * @param chi2 : reference to the chi2 of the fit + * @param xStart : pointer to the 'initial hit' of the cluster. It is defined + * as the point with the largest distance to the CoG measured + * in the direction towards the IP. + * @param index_xStart : index of the point in the cluster corresponding to xStart + * @param X0 : radiation length of the detector material. For a composite + * detector this is meant to be the 'mean' radiation length. + * @param Rm : Moliere radius of the the detector material. For a composite + * detector this is meant to be the 'mean' Moliere radius. + */ + int fit3DProfile(float& chi2, float& a, float& b, float& c, float& d, float& xl0, + float * xStart, int& index_xStart, float X0, float Rm); + + /** + * returns the chi2 of the fit in the method Fit3DProfile (if simple + * parametrisation is used)for a given set of parameters a,b,c,d + * @param a,b,c,d,xl0 : fitted parameters, which have been calculated before + * @param X0 : radiation length of the detector material. For a composite + * detector this is meant to be the 'mean' radiation length. + * @param Rm : Moliere radius of the the detector material. For a composite + * detector this is meant to be the 'mean' Moliere radius. + */ + float getChi2Fit3DProfileSimple(float a, float b, float c, float d, float X0, + float Rm); + + /** + * returns the chi2 of the fit in the method Fit3DProfile (if advanced + * parametrisation is used) for a given set of parameters E0,a,b,d,t0 + * @param E0,a,b,d,t0 : fitted parameters, which have been calculated before + * @param X0 : radiation length of the detector material. For a composite + * detector this is meant to be the 'mean' radiation length. + * @param Rm : Moliere radius of the the detector material. For a composite + * detector this is meant to be the 'mean' Moliere radius. + */ + float getChi2Fit3DProfileAdvanced(float E0, float a, float b, float d, float t0, + float X0, float Rm); + + /** + * performs a least square fit on a helix path in space, which + * which is defined as (Cartesian coordiantes): + * + * 1. parametrisation: + * x[i] = x0 + R*cos(b*z[i] + phi0) + * y[i] = y0 + R*sin(b*z[i] + phi0) + * z[i] = z[i], + * where x0,y0,R,b and phi0 are the parameters to be fitted and + * x[i],y[i],z[i] are the (Cartesian) coordiantes of the space + * points. + * + * 2. parametrisation: + * x[i] = x0 + R*cos(phi) + * y[i] = y0 + R*sin(phi) + * z[i] = z0 + b*phi + * and phi = atan2( y[i]-y0 , x[i]-x0 ), + * where x0,y0,z0,R and b are the parameters to be fitted and + * x[i],y[i],z[i] are the (Cartesian) coordiantes of the space + * points. + * + * The method returns 1 if an error occured and 0 if not. + * + * The following output/input parameters are returned/needed: + * + * OUTPUTS: + * @param parameter : array of parameters to be fitted. + * For parametrisation 1: parameter[5] = {x0,y0,R,b,phi0} + * For parametrisation 2: parameter[5] = {x0,y0,z0,R,b} + * @param dparameter : error on the parameters, that means: + * dparameter[i] = sqrt( CovarMatrix[i][i] ) + * @param chi2 : chi2 of the fit + * @param distmax : maximal distance between the points x[i],y[i] + * z[i] and the fitted function + * + * INPUTS: + * @param parametrisation : 1 for first and 2 for second parametrisation (see above) + * @param max_iter : maximal number of iterations, before fit cancels + * @param status_out : if set to 1, only the initial parameters of + * the fit are calculated and are stored in + * parameter. The entries of dparameter are + * set to 0.0 + */ + int FitHelix(int max_iter, int status_out, int parametrisation, + double* parameter, double* dparameter, double& chi2, double& distmax, int direction=1); + + + int FitHelix(int max_iter, int status_out, int parametrisation, + float* parameter, float* dparameter, float& chi2, float& distmax, int direction=1); + + /** + * distance to the centre of gravity measured from IP + * (absolut value of the vector to the centre of gravity) + */ + inline float radius() { return _radius; } + + /** + * largest spatial axis length of the ellipsoid derived + * by the inertia tensor (by their eigenvalues and eigen- + * vectors) + */ + inline float getElipsoid_r1() { return _r1; } + + /** + * medium spatial axis length of the ellipsoid derived + * by the inertia tensor (by their eigenvalues and eigen- + * vectors) + */ + inline float getElipsoid_r2() { return _r2; } + + /** + * smallest spatial axis length of the ellipsoid derived + * by the inertia tensor (by their eigenvalues and eigen- + * vectors) + */ + inline float getElipsoid_r3() { return _r3; } + + /** + * volume of the ellipsoid + */ + inline float getElipsoid_vol() { return _vol; } + + /** + * average radius of the ellipsoid (qubic root of volume) + */ + inline float getElipsoid_r_ave() { return _r_ave; } + + /** + * density of the ellipsoid defined by: totAmpl/vol + */ + inline float getElipsoid_density() { return _density; } + + /** + * eccentricity of the ellipsoid defined by: + * Width/r1 + */ + inline float getElipsoid_eccentricity() { return _eccentricity; } + + /** + * distance from centre of gravity to the point most far + * away from IP projected on the main principal axis + */ + inline float getElipsoid_r_forw() { return _r1_forw; } + + /** + * distance from centre of gravity to the point nearest + * to IP projected on the main principal axis + */ + inline float getElipsoid_r_back() { return _r1_back; } + + + + + + private: + + int _nHits; + + float* _aHit; + float* _xHit; + float* _yHit; + float* _zHit; + float* _exHit; + float* _eyHit; + float* _ezHit; + int* _types; + float* _xl; + float* _xt; + float* _t; + float* _s; + + int _ifNotGravity; + float _totAmpl; + float _radius; + float _xgr; + float _ygr; + float _zgr; + float _analogGravity[3]; + + int _ifNotWidth; + float _analogWidth; + + int _ifNotInertia; + float _ValAnalogInertia[3]; + float _VecAnalogInertia[9]; + + int _ifNotEigensystem; + + int _ifNotElipsoid; + float _r1 ; // Cluster spatial axis length -- the largest + float _r2 ; // Cluster spatial axis length -- less + float _r3 ; // Cluster spatial axis length -- less + float _vol ; // Cluster ellipsoid volume + float _r_ave ; // Cluster average radius (qubic root) + float _density ; // Cluster density + float _eccentricity ; // Cluster Eccentricity + float _r1_forw ; + float _r1_back ; + + void findElipsoid(); + void findGravity(); + void findInertia(); + void findWidth(); + float findDistance(int i); + float vecProduct(float * x1, float * x2); + float vecProject(float * x, float * axis); + double DistanceHelix(double x, double y, double z, double X0, double Y0, double R0, double bz, + double phi0, double * distRPhiZ); + int transformToEigensystem(float* xStart, int& index_xStart, float X0, float Xm); + float calculateChi2Fit3DProfileSimple(float a, float b, float c, float d); + float calculateChi2Fit3DProfileAdvanced(float E0, float a, float b, float d, float t0); + int fit3DProfileSimple(float& chi2, float& a, float& b, float& c, float& d); + int fit3DProfileAdvanced(float& chi2, double* par_init, double* par, int npar, + float* t, float* s, float* E, float E0); + + // private methods for non-linear, multidim. fitting (helix) + // static int functParametrisation1(const gsl_vector* par, void* data, gsl_vector* f); + // static int dfunctParametrisation1(const gsl_vector* par, void* d, gsl_matrix* J); + // static int fdfParametrisation1(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J); + + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc new file mode 100644 index 00000000..6582e17e --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc @@ -0,0 +1,768 @@ +#include "HelixClass.h" +#include <math.h> +#include <stdlib.h> +#include <iostream> +#include "ced_cli.h" + +HelixClass::HelixClass() { + _const_2pi = 2.0*M_PI; + _const_pi2 = 0.5*M_PI; + _FCT = 2.99792458E-4; +} + +HelixClass::~HelixClass() {} + +void HelixClass::Initialize_VP(float * pos, float * mom, float q, float B) { + _referencePoint[0] = pos[0]; + _referencePoint[1] = pos[1]; + _referencePoint[2] = pos[2]; + _momentum[0] = mom[0]; + _momentum[1] = mom[1]; + _momentum[2] = mom[2]; + _charge = q; + _bField = B; + _pxy = sqrt(mom[0]*mom[0]+mom[1]*mom[1]); + _radius = _pxy / (_FCT*B); + _omega = q/_radius; + _tanLambda = mom[2]/_pxy; + _phiMomRefPoint = atan2(mom[1],mom[0]); + _xCentre = pos[0] + _radius*cos(_phiMomRefPoint-_const_pi2*q); + _yCentre = pos[1] + _radius*sin(_phiMomRefPoint-_const_pi2*q); + _phiRefPoint = atan2(pos[1]-_yCentre,pos[0]-_xCentre); + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phi0 = -_const_pi2*q + _phiAtPCA; + while (_phi0<0) _phi0+=_const_2pi; + while (_phi0>=_const_2pi) _phi0-=_const_2pi; + _xAtPCA = _xCentre + _radius*cos(_phiAtPCA); + _yAtPCA = _yCentre + _radius*sin(_phiAtPCA); + // _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0); + double pxy = double(_pxy); + double radius = pxy/double(_FCT*B); + double xCentre = double(pos[0]) + radius*double(cos(_phiMomRefPoint-_const_pi2*q)); + double yCentre = double(pos[1]) + radius*double(sin(_phiMomRefPoint-_const_pi2*q)); + + double d0; + + if (q>0) { + d0 = double(q)*radius - double(sqrt(xCentre*xCentre+yCentre*yCentre)); + } + else { + d0 = double(q)*radius + double(sqrt(xCentre*xCentre+yCentre*yCentre)); + } + + _d0 = float(d0); + +// if (fabs(_d0)>0.001 ) { +// std::cout << "New helix : " << std::endl; +// std::cout << " Position : " << pos[0] +// << " " << pos[1] +// << " " << pos[2] << std::endl; +// std::cout << " Radius = " << _radius << std::endl; +// std::cout << " RC = " << sqrt(_xCentre*_xCentre+_yCentre*_yCentre) << std::endl; +// std::cout << " D0 = " << _d0 << std::endl; +// } + + _pxAtPCA = _pxy*cos(_phi0); + _pyAtPCA = _pxy*sin(_phi0); + float deltaPhi = _phiRefPoint - _phiAtPCA; + float xCircles = -pos[2]*q/(_radius*_tanLambda) - deltaPhi; + xCircles = xCircles/_const_2pi; + int nCircles; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + _z0 = pos[2] + _radius*_tanLambda*q*(deltaPhi + _const_2pi*nCircles); + +} + +void HelixClass::Initialize_Canonical(float phi0, float d0, float z0, + float omega, float tanLambda, float B) { + _omega = omega; + _d0 = d0; + _phi0 = phi0; + _z0 = z0; + _tanLambda = tanLambda; + _charge = omega/fabs(omega); + _radius = 1./fabs(omega); + _xAtPCA = -_d0*sin(_phi0); + _yAtPCA = _d0*cos(_phi0); + _referencePoint[0] = _xAtPCA; + _referencePoint[1] = _yAtPCA; + _referencePoint[2] = _z0; + _pxy = _FCT*B*_radius; + _momentum[0] = _pxy*cos(_phi0); + _momentum[1] = _pxy*sin(_phi0); + _momentum[2] = _tanLambda * _pxy; + _pxAtPCA = _momentum[0]; + _pyAtPCA = _momentum[1]; + _phiMomRefPoint = atan2(_momentum[1],_momentum[0]); + _xCentre = _referencePoint[0] + + _radius*cos(_phi0-_const_pi2*_charge); + _yCentre = _referencePoint[1] + + _radius*sin(_phi0-_const_pi2*_charge); + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phiRefPoint = _phiAtPCA ; + _bField = B; +} + + +void HelixClass::Initialize_BZ(float xCentre, float yCentre, float radius, + float bZ, float phi0, float B, float signPz, + float zBegin) { + + _radius = radius; + _pxy = _FCT*B*_radius; + _charge = -(bZ*signPz)/fabs(bZ*signPz); + _momentum[2] = -_charge*_pxy/(bZ*_radius); + _xCentre = xCentre; + _yCentre = yCentre; + _omega = _charge/radius; + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phi0 = -_const_pi2*_charge + _phiAtPCA; + while (_phi0<0) _phi0+=_const_2pi; + while (_phi0>=_const_2pi) _phi0-=_const_2pi; + _xAtPCA = _xCentre + _radius*cos(_phiAtPCA); + _yAtPCA = _yCentre + _radius*sin(_phiAtPCA); + _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0); + _pxAtPCA = _pxy*cos(_phi0); + _pyAtPCA = _pxy*sin(_phi0); + _referencePoint[2] = zBegin; + _referencePoint[0] = xCentre + radius*cos(bZ*zBegin+phi0); + _referencePoint[1] = yCentre + radius*sin(bZ*zBegin+phi0); + _phiRefPoint = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + _phiMomRefPoint = -_const_pi2*_charge + _phiRefPoint; + _tanLambda = _momentum[2]/_pxy; + _momentum[0] = _pxy*cos(_phiMomRefPoint); + _momentum[1] = _pxy*sin(_phiMomRefPoint); + + float deltaPhi = _phiRefPoint - _phiAtPCA; + float xCircles = bZ*_referencePoint[2] - deltaPhi; + xCircles = xCircles/_const_2pi; + int nCircles; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + _z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ; + _bField = B; + +} + +const float * HelixClass::getMomentum() { + return _momentum; +} +const float * HelixClass::getReferencePoint() { + return _referencePoint; +} +float HelixClass::getPhi0() { + if (_phi0<0.0) + _phi0 += 2*M_PI; + return _phi0; +} +float HelixClass::getD0() { + return _d0; +} +float HelixClass::getZ0() { + return _z0; +} +float HelixClass::getOmega() { + return _omega; +} +float HelixClass::getTanLambda() { + return _tanLambda; +} +float HelixClass::getPXY() { + return _pxy; +} +float HelixClass::getXC() { + return _xCentre; +} + +float HelixClass::getYC() { + return _yCentre; +} + +float HelixClass::getRadius() { + return _radius; +} + +float HelixClass::getBz() { + return _bZ; +} + +float HelixClass::getPhiZ() { + return _phiZ; +} + +float HelixClass::getCharge() { + return _charge; +} + +float HelixClass::getPointInXY(float x0, float y0, float ax, float ay, + float * ref , float * point) { + + float time; + + float AA = sqrt(ax*ax+ay*ay); + + + if (AA <= 0) { + time = -1.0e+20; + return time; + } + + + float BB = ax*(x0-_xCentre) + ay*(y0-_yCentre); + BB = BB / AA; + + float CC = (x0-_xCentre)*(x0-_xCentre) + + (y0-_yCentre)*(y0-_yCentre) - _radius*_radius; + + CC = CC / AA; + + float DET = BB*BB - CC; + float tt1 = 0.; + float tt2 = 0.; + float xx1,xx2,yy1,yy2; + + + if (DET < 0 ) { + time = 1.0e+10; + point[0]=0.0; + point[1]=0.0; + point[2]=0.0; + return time; + } + + + tt1 = - BB + sqrt(DET); + tt2 = - BB - sqrt(DET); + + xx1 = x0 + tt1*ax; + yy1 = y0 + tt1*ay; + xx2 = x0 + tt2*ax; + yy2 = y0 + tt2*ay; + + float phi1 = atan2(yy1-_yCentre,xx1-_xCentre); + float phi2 = atan2(yy2-_yCentre,xx2-_xCentre); + float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre); + + float dphi1 = phi1 - phi0; + float dphi2 = phi2 - phi0; + + if (dphi1 < 0 && _charge < 0) { + dphi1 = dphi1 + _const_2pi; + } + else if (dphi1 > 0 && _charge > 0) { + dphi1 = dphi1 - _const_2pi; + } + + if (dphi2 < 0 && _charge < 0) { + dphi2 = dphi2 + _const_2pi; + } + else if (dphi2 > 0 && _charge > 0) { + dphi2 = dphi2 - _const_2pi; + } + + // Times + tt1 = -_charge*dphi1*_radius/_pxy; + tt2 = -_charge*dphi2*_radius/_pxy; + + if (tt1 < 0. ) + std::cout << "WARNING " << tt1 << std::endl; + if (tt2 < 0. ) + std::cout << "WARNING " << tt2 << std::endl; + + + if (tt1 < tt2) { + point[0] = xx1; + point[1] = yy1; + time = tt1; + } + else { + point[0] = xx2; + point[1] = yy2; + time = tt2; + } + + point[2] = ref[2]+time*_momentum[2]; + + + + return time; + +} + + +float HelixClass::getPointOnCircle(float Radius, float * ref, float * point) { + + float distCenterToIP = sqrt(_xCentre*_xCentre + _yCentre*_yCentre); + + point[0] = 0.0; + point[1] = 0.0; + point[2] = 0.0; + + if ((distCenterToIP+_radius)<Radius) { + float xx = -1.0e+20; + return xx; + } + + if ((_radius+Radius)<distCenterToIP) { + float xx = -1.0e+20; + return xx; + } + + float phiCentre = atan2(_yCentre,_xCentre); + float phiStar = Radius*Radius + distCenterToIP*distCenterToIP + - _radius*_radius; + + phiStar = 0.5*phiStar/fmax(1.0e-20,Radius*distCenterToIP); + + if (phiStar > 1.0) + phiStar = 0.9999999; + + if (phiStar < -1.0) + phiStar = -0.9999999; + + phiStar = acos(phiStar); + + float tt1,tt2,time; + + float xx1 = Radius*cos(phiCentre+phiStar); + float yy1 = Radius*sin(phiCentre+phiStar); + + float xx2 = Radius*cos(phiCentre-phiStar); + float yy2 = Radius*sin(phiCentre-phiStar); + + + float phi1 = atan2(yy1-_yCentre,xx1-_xCentre); + float phi2 = atan2(yy2-_yCentre,xx2-_xCentre); + float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre); + + float dphi1 = phi1 - phi0; + float dphi2 = phi2 - phi0; + + if (dphi1 < 0 && _charge < 0) { + dphi1 = dphi1 + _const_2pi; + } + else if (dphi1 > 0 && _charge > 0) { + dphi1 = dphi1 - _const_2pi; + } + + if (dphi2 < 0 && _charge < 0) { + dphi2 = dphi2 + _const_2pi; + } + else if (dphi2 > 0 && _charge > 0) { + dphi2 = dphi2 - _const_2pi; + } + + // Times + tt1 = -_charge*dphi1*_radius/_pxy; + tt2 = -_charge*dphi2*_radius/_pxy; + + if (tt1 < 0. ) + std::cout << "WARNING " << tt1 << std::endl; + if (tt2 < 0. ) + std::cout << "WARNING " << tt2 << std::endl; + + + float time2; + if (tt1 < tt2) { + point[0] = xx1; + point[1] = yy1; + point[3] = xx2; + point[4] = yy2; + time = tt1; + time2 = tt2; + } + else { + point[0] = xx2; + point[1] = yy2; + point[3] = xx1; + point[4] = yy1; + time = tt2; + time2 = tt1; + } + + point[2] = ref[2]+time*_momentum[2]; + point[5] = ref[2]+time2*_momentum[2]; + + + return time; + +} + + +float HelixClass::getPointInZ(float zLine, float * ref, float * point) { + + float time = zLine - ref[2]; + + if (_momentum[2] == 0.) { + time = -1.0e+20; + point[0] = 0.; + point[1] = 0.; + point[2] = 0.; + return time; + } + + time = time/_momentum[2]; + + float phi0 = atan2(ref[1] - _yCentre , ref[0] - _xCentre); + float phi = phi0 - _charge*_pxy*time/_radius; + float xx = _xCentre + _radius*cos(phi); + float yy = _yCentre + _radius*sin(phi); + + point[0] = xx; + point[1] = yy; + point[2] = zLine; + + return time; + + +} + +float HelixClass::getDistanceToPoint(float * xPoint, float * Distance) { + + float zOnHelix; + float phi = atan2(xPoint[1]-_yCentre,xPoint[0]-_xCentre); + float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY + float DistXY = (_xCentre-xPoint[0])*(_xCentre-xPoint[0]) + (_yCentre-xPoint[1])*(_yCentre-xPoint[1]); + DistXY = sqrt(DistXY); + DistXY = fabs(DistXY - _radius); + + int nCircles = 0; + + if (fabs(_tanLambda*_radius)>1.0e-20) { + float xCircles = phi0 - phi -_charge*(xPoint[2]-_referencePoint[2])/(_tanLambda*_radius); + xCircles = xCircles/_const_2pi; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + + } + + float DPhi = _const_2pi*((float)nCircles) + phi - phi0; + + zOnHelix = _referencePoint[2] - _charge*_radius*_tanLambda*DPhi; + + float DistZ = fabs(zOnHelix - xPoint[2]); + float Time; + + if (fabs(_momentum[2]) > 1.0e-20) { + Time = (zOnHelix - _referencePoint[2])/_momentum[2]; + } + else { + Time = _charge*_radius*DPhi/_pxy; + } + + Distance[0] = DistXY; + Distance[1] = DistZ; + Distance[2] = sqrt(DistXY*DistXY+DistZ*DistZ); + + return Time; + + +} + +//When we are not interested in the exact distance, we can check if we are +//already far enough away in XY, before we start calculating in Z as the +//distance will only increase +float HelixClass::getDistanceToPoint(const std::vector<float>& xPoint, float distCut) { + //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY + float tempx = xPoint[0]-_xCentre; + float tempy = xPoint[1]-_yCentre; + float tempsq = sqrt(tempx*tempx + tempy*tempy); + float tempdf = tempsq - _radius; + float DistXY = fabs( tempdf ); + //If this is bigger than distCut, we dont have to know how much bigger this is + if( DistXY > distCut) { + return DistXY; + } + + int nCircles = 0; + float phi = atan2(tempy,tempx); + float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + float phidiff = phi0-phi; + float tempz = xPoint[2] - _referencePoint[2];//Yes referencePoint + float tanradius = _tanLambda*_radius; + if (fabs(tanradius)>1.0e-20) { + float xCircles = (phidiff -_charge*tempz/tanradius)/_const_2pi; + int n1,n2; + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + } + float DistZ = - tempz - _charge*tanradius*(_const_2pi*((float)nCircles) - phidiff); + return sqrt(DistXY*DistXY+DistZ*DistZ); +}//getDistanceToPoint(vector,float) + +float HelixClass::getDistanceToPoint(const float* xPoint, float distCut) { + std::vector<float> xPosition(xPoint, xPoint + 3 );//We are expecting three coordinates, must be +3, last element is excluded! + return getDistanceToPoint(xPosition, distCut); +}//getDistanceToPoint(float*,float) + + + +void HelixClass::setHelixEdges(float * xStart, float * xEnd) { + for (int i=0; i<3; ++i) { + _xStart[i] = xStart[i]; + _xEnd[i] = xEnd[i]; + } + +} + +float HelixClass::getDistanceToHelix(HelixClass * helix, float * pos, float * mom) { + + float x01 = getXC(); + float y01 = getYC(); + + float x02 = helix->getXC(); + float y02 = helix->getYC(); + + float rad1 = getRadius(); + float rad2 = helix->getRadius(); + + float distance = sqrt((x01-x02)*(x01-x02)+(y01-y02)*(y01-y02)); + + bool singlePoint = true; + + float phi1 = 0; + float phi2 = 0; + + if (rad1+rad2<distance) { + phi1 = atan2(y02-y01,x02-x01); + phi2 = atan2(y01-y02,x01-x02); + } + else if (distance+rad2<rad1) { + phi1 = atan2(y02-y01,x02-x01); + phi2 = phi1; + } + else if (distance+rad1<rad2) { + phi1 = atan2(y01-y02,x01-x02); + phi2 = phi1; + } + else { + singlePoint = false; + float cosAlpha = 0.5*(distance*distance+rad2*rad2-rad1*rad1)/(distance*rad2); + float alpha = acos(cosAlpha); + float phi0 = atan2(y01-y02,x01-x02); + phi1 = phi0 + alpha; + phi2 = phi0 - alpha; + } + + + float ref1[3]; + float ref2[3]; + for (int i=0;i<3;++i) { + ref1[i]=_referencePoint[i]; + ref2[i]=helix->getReferencePoint()[i]; + } + + float pos1[3]; + float pos2[3]; + float mom1[3]; + float mom2[3]; + + + if (singlePoint ) { + + float xSect1 = x01 + rad1*cos(phi1); + float ySect1 = y01 + rad1*sin(phi1); + float xSect2 = x02 + rad2*cos(phi2); + float ySect2 = y02 + rad2*sin(phi2); + float R1 = sqrt(xSect1*xSect1+ySect1*ySect1); + float R2 = sqrt(xSect2*xSect2+ySect2*ySect2); + + getPointOnCircle(R1,ref1,pos1); + helix->getPointOnCircle(R2,ref2,pos2); + + } + else { + + float xSect1 = x02 + rad2*cos(phi1); + float ySect1 = y02 + rad2*sin(phi1); + float xSect2 = x02 + rad2*cos(phi2); + float ySect2 = y02 + rad2*sin(phi2); + +// std::cout << "(xSect1,ySect1)=(" << xSect1 << "," << ySect1 << ")" << std::endl; +// std::cout << "(xSect2,ySect2)=(" << xSect2 << "," << ySect2 << ")" << std::endl; + + float temp21[3]; + float temp22[3]; + + float phiI2 = atan2(ref2[1]-y02,ref2[0]-x02); + float phiF21 = atan2(ySect1-y02,xSect1-x02); + float phiF22 = atan2(ySect2-y02,xSect2-x02); + float deltaPhi21 = phiF21 - phiI2; + float deltaPhi22 = phiF22 - phiI2; + float charge2 = helix->getCharge(); + float pxy2 = helix->getPXY(); + float pz2 = helix->getMomentum()[2]; + if (deltaPhi21 < 0 && charge2 < 0) { + deltaPhi21 += _const_2pi; + } + else if (deltaPhi21 > 0 && charge2 > 0) { + deltaPhi21 -= _const_2pi; + } + + if (deltaPhi22 < 0 && charge2 < 0) { + deltaPhi22 += _const_2pi; + } + else if (deltaPhi22 > 0 && charge2 > 0) { + deltaPhi22 -= _const_2pi; + } + + float time21 = -charge2*deltaPhi21*rad2/pxy2; + float time22 = -charge2*deltaPhi22*rad2/pxy2; + + float Z21 = ref2[2] + time21*pz2; + float Z22 = ref2[2] + time22*pz2; + + temp21[0] = xSect1; temp21[1] = ySect1; temp21[2] = Z21; + temp22[0] = xSect2; temp22[1] = ySect2; temp22[2] = Z22; + + +// std::cout << "temp21 = " << temp21[0] << " " << temp21[1] << " " << temp21[2] << std::endl; +// std::cout << "temp22 = " << temp22[0] << " " << temp22[1] << " " << temp22[2] << std::endl; + + + float temp11[3]; + float temp12[3]; + + float phiI1 = atan2(ref1[1]-y01,ref1[0]-x01); + float phiF11 = atan2(ySect1-y01,xSect1-x01); + float phiF12 = atan2(ySect2-y01,xSect2-x01); + float deltaPhi11 = phiF11 - phiI1; + float deltaPhi12 = phiF12 - phiI1; + float charge1 = _charge; + float pxy1 = _pxy; + float pz1 = _momentum[2]; + if (deltaPhi11 < 0 && charge1 < 0) { + deltaPhi11 += _const_2pi; + } + else if (deltaPhi11 > 0 && charge1 > 0) { + deltaPhi11 -= _const_2pi; + } + + if (deltaPhi12 < 0 && charge1 < 0) { + deltaPhi12 += _const_2pi; + } + else if (deltaPhi12 > 0 && charge1 > 0) { + deltaPhi12 -= _const_2pi; + } + + float time11 = -charge1*deltaPhi11*rad1/pxy1; + float time12 = -charge1*deltaPhi12*rad1/pxy1; + + float Z11 = ref1[2] + time11*pz1; + float Z12 = ref1[2] + time12*pz1; + + temp11[0] = xSect1; temp11[1] = ySect1; temp11[2] = Z11; + temp12[0] = xSect2; temp12[1] = ySect2; temp12[2] = Z12; + +// std::cout << "temp11 = " << temp11[0] << " " << temp11[1] << " " << temp11[2] << std::endl; +// std::cout << "temp12 = " << temp12[0] << " " << temp12[1] << " " << temp12[2] << std::endl; + + float Dist1 = 0; + float Dist2 = 0; + + for (int j=0;j<3;++j) { + Dist1 += (temp11[j]-temp21[j])*(temp11[j]-temp21[j]); + Dist2 += (temp12[j]-temp22[j])*(temp12[j]-temp22[j]); + } + + if (Dist1<Dist2) { + for (int l=0;l<3;++l) { + pos1[l] = temp11[l]; + pos2[l] = temp21[l]; + } + } + else { + for (int l=0;l<3;++l) { + pos1[l] = temp12[l]; + pos2[l] = temp22[l]; + } + } + + } + + getExtrapolatedMomentum(pos1,mom1); + helix->getExtrapolatedMomentum(pos2,mom2); + + float helixDistance = 0; + + for (int i=0;i<3;++i) { + helixDistance += (pos1[i] - pos2[i])*(pos1[i] - pos2[i]); + pos[i] = 0.5*(pos1[i]+pos2[i]); + mom[i] = mom1[i]+mom2[i]; + } + helixDistance = sqrt(helixDistance); + + return helixDistance; + +} + +void HelixClass::getExtrapolatedMomentum(float * pos, float * momentum) { + + float phi = atan2(pos[1]-_yCentre,pos[0]-_xCentre); + if (phi <0.) phi += _const_2pi; + phi = phi - _phiAtPCA + _phi0; + momentum[0] = _pxy*cos(phi); + momentum[1] = _pxy*sin(phi); + momentum[2] = _momentum[2]; + + +} diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h new file mode 100644 index 00000000..794f8158 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h @@ -0,0 +1,302 @@ +#ifndef HELIXAR_H +#define HELIXAR_H 1 +#include <vector> +/** + * Utility class to manipulate with different parameterisations <br> + * of helix. Helix can be initialized in a three different <br> + * ways using the following public methods : <br> + * 1) Initialize_VP(float * pos, float * mom, float q, float B) : <br> + * initialization of helix is done using <br> + * - position of the reference point : pos[3]; <br> + * - momentum vector at the reference point : mom[3];<br> + * - particle charge : q;<br> + * - magnetic field (in Tesla) : B;<br> + * 2) Initialize_BZ(float xCentre, float yCentre, float radius, <br> + * float bZ, float phi0, float B, float signPz,<br> + * float zBegin):<br> + * initialization of helix is done according to the following<br> + * parameterization<br> + * x = xCentre + radius*cos(bZ*z + phi0)<br> + * y = yCentre + radius*sin(bZ*z + phi0)<br> + * where (x,y,z) - position of point on the helix<br> + * - (xCentre,yCentre) is the centre of circumference in R-Phi plane<br> + * - radius is the radius of circumference<br> + * - bZ is the helix slope parameter<br> + * - phi0 is the initial phase of circumference<br> + * - B is the magnetic field (in Tesla)<br> + * - signPz is the sign of the z component of momentum vector<br> + * - zBegin is the z coordinate of the reference point;<br> + * 3) void Initialize_Canonical(float phi0, float d0, float z0, float omega,<br> + * float tanlambda, float B) :<br> + * canonical (LEP-wise) parameterisation with the following parameters<br> + * - phi0 - Phi angle of momentum vector at the point of<br> + * closest approach to IP in R-Phi plane; + * - d0 - signed distance of closest approach to IP in R-Phi plane;<br> + * - z0 - z coordinate of the point of closest approach in R-Phi plane;<br> + * - omega - signed curvature;<br> + * - tanlambda - tangent of dip angle;<br> + * - B - magnetic field (in Tesla);<br> + * A set of public methods (getters) provide access to <br> + * various parameters associated with helix. Helix Class contains<br> + * also several utility methods, allowing for calculation of helix<br> + * intersection points with planes parallel and perpendicular to <br> + * z (beam) axis and determination of the distance of closest approach<br> + * from arbitrary 3D point to the helix. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: HelixClass.h,v 1.16 2008-06-05 13:47:18 rasp Exp $<br> + * + */ + +#include "LineClass.h" +class HelixClass; + +class HelixClass { + public: + +/** + * Constructor. Initializations of constants which are used + * to calculate various parameters associated with helix. + */ + HelixClass(); +/** + * Destructor. + */ + ~HelixClass(); +/** + * Initialization of helix using <br> + * - position of the reference point : pos[3]; <br> + * - momentum vector at the reference point : mom[3];<br> + * - particle charge : q;<br> + * - magnetic field (in Tesla) : B<br> + */ + void Initialize_VP(float * pos, float * mom, float q, float B); + +/** + * Initialization of helix according to the following<br> + * parameterization<br> + * x = xCentre + radius*cos(bZ*z + phi0)<br> + * y = yCentre + radius*sin(bZ*z + phi0)<br> + * where (x,y,z) - position of point on the helix<br> + * - (xCentre,yCentre) is the centre of circumference in R-Phi plane<br> + * - radius is the radius of circumference<br> + * - bZ is the helix slope parameter<br> + * - phi0 is the initial phase of circumference<br> + * - B is the magnetic field (in Tesla)<br> + * - signPz is the sign of the z component of momentum vector<br> + * - zBegin is the z coordinate of the reference point<br> + */ + void Initialize_BZ(float xCentre, float yCentre, float radius, + float bZ, float phi0, float B, float signPz, + float zBegin); +/** + * Canonical (LEP-wise) parameterisation with the following parameters<br> + * - phi0 - Phi angle of momentum vector at the point of<br> + * closest approach to IP in R-Phi plane; + * - d0 - signed distance of closest approach in R-Phi plane;<br> + * - z0 - z coordinate of the point of closest approach to IP + * in R-Phi plane;<br> + * - omega - signed curvature;<br> + * - tanlambda - tangent of dip angle;<br> + * - B - magnetic field (in Tesla)<br> + */ + void Initialize_Canonical(float phi0, float d0, float z0, float omega, + float tanlambda, float B); + /** + * Returns momentum of particle at the point of closest approach <br> + * to IP <br> + */ + const float * getMomentum(); + + /** + * Returns reference point of track <br> + */ + const float * getReferencePoint(); + + /** + * Returns Phi angle of the momentum vector <br> + * at the point of closest approach to IP <br> + */ + float getPhi0(); + + /** + * Returns signed distance of closest approach <br> + * to IP in the R-Phi plane <br> + */ + float getD0(); + + /** + * Returns z coordinate of the point of closest + * approach to IP in the R-Phi plane <br> + */ + float getZ0(); + + /** + * Returns signed curvature of the track <br> + */ + float getOmega(); + + /** + * Returns tangent of dip angle of the track <br> + */ + float getTanLambda(); + + /** + * Returns transverse momentum of the track <br> + */ + float getPXY(); + + + /** + * Returns x coordinate of circumference + */ + float getXC(); + + /** + * Returns y coordinate of circumference + */ + float getYC(); + + + /** + * Returns radius of circumference + */ + float getRadius(); + + + /** + * Returns helix intersection point with the plane <br> + * parallel to z axis. Plane is defined by two coordinates <br> + * of the point belonging to the plane (x0,y0) and normal <br> + * vector (ax,ay). ref[3] is the reference point of the helix. <br> + * point[3] - returned vector holding the coordinates of <br> + * intersection point <br> + */ + float getPointInXY(float x0, float y0, float ax, float ay, + float * ref , float * point); + + /** + * Returns helix intersection point with the plane <br> + * perpendicular to z axis. Plane is defined by z coordinate <br> + * of the plane. ref[3] is the reference point of the helix. <br> + * point[3] - returned vector holding the coordinates of <br> + * intersection point <br> + */ + float getPointInZ(float zLine, float * ref, float * point); + + /** + * Return distance of the closest approach of the helix to <br> + * arbitrary 3D point in space. xPoint[3] - coordinates of <br> + * space point. Distance[3] - vector of distances of helix to <br> + * a given point in various projections : <br> + * Distance[0] - distance in R-Phi plane <br> + * Distance[1] - distance along Z axis <br> + * Distance[2] - 3D distance <br> + */ + float getDistanceToPoint(float * xPoint, float * Distance); + + /** + * Return distance of the closest approach of the helix to <br> + * arbitrary 3D point in space. xPoint[3] - coordinates of <br> + * space point. distCut - limit on the distance between helix <br> + * and the point to reduce calculation time <br> + * If R-Phi is found to be greater than distCut, rPhi distance is returned <br> + * If the R-Phi distance is not too big, than the exact 3D distance is returned <br> + * This function can be used, if the exact distance is not always needed <br> + */ + float getDistanceToPoint(const float* xPoint, float distCut); + float getDistanceToPoint(const std::vector<float>& xPoint, float distCut); + + /** + * This method calculates coordinates of both intersection <br> + * of the helix with a cylinder. <br> + * Rotational symmetry with respect to z axis is assumed, <br> + * meaning that cylinder axis corresponds to the z axis <br> + * of reference frame. <br> + * Inputs : <br> + * Radius - radius of cylinder. <br> + * ref[3] - point of closest approach to the origin of the helix. <br> + * Output : <br> + * point[6] - coordinates of intersection point. <br> + * Method returns also generic time, defined as the <br> + * ratio of helix length from reference point to the intersection <br> + * point to the particle momentum <br> + */ + float getPointOnCircle(float Radius, float * ref, float * point); + + /** Returns distance between two helixes <br> + * Output : <br> + * pos[3] - position of the point of closest approach <br> + * mom[3] - momentum of V0 <br> + */ + float getDistanceToHelix(HelixClass * helix, float * pos, float * mom); + + /** + * Set Edges of helix + */ + void setHelixEdges(float * xStart, float * xEnd); + + /** + * Returns starting point of helix + */ + float * getStartingPoint() {return _xStart;} + + /** + * Returns endpoint of helix + */ + float * getEndPoint() {return _xEnd;} + + /** + * Returns BZ for the second parameterization + */ + float getBz(); + + /** + * Returns Phi for the second parameterization + */ + float getPhiZ(); + + /** + * Returns extrapolated momentum + */ + void getExtrapolatedMomentum(float * pos, float * momentum); + + /** + * Returns charge + */ + float getCharge(); + + private: + float _momentum[3]; // momentum @ ref point + float _referencePoint[3]; // coordinates @ ref point + float _phi0; // phi0 in canonical parameterization + float _d0; // d0 in canonical parameterisation + float _z0; // z0 in canonical parameterisation + float _omega; // signed curvuture in canonical parameterisation + float _tanLambda; // TanLambda + float _pxy; // Transverse momentum + float _charge; // Particle Charge + float _bField; // Magnetic field (assumed to point to Z>0) + float _radius; // radius of circle in XY plane + float _xCentre; // X of circle centre + float _yCentre; // Y of circle centre + float _phiRefPoint; // Phi w.r.t. (X0,Y0) of circle @ ref point + float _phiAtPCA; // Phi w.r.t. (X0,Y0) of circle @ PCA + float _xAtPCA; // X @ PCA + float _yAtPCA; // Y @ PCA + float _pxAtPCA; // PX @ PCA + float _pyAtPCA; // PY @ PCA + float _phiMomRefPoint; // Phi of Momentum vector @ ref point + float _const_pi; // PI + float _const_2pi; // 2*PI + float _const_pi2; // PI/2 + float _FCT; // 2.99792458E-4 + float _xStart[3]; // Starting point of track segment + float _xEnd[3]; // Ending point of track segment + + float _bZ; + float _phiZ; + +}; + + +#endif diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc new file mode 100644 index 00000000..e23db1fa --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc @@ -0,0 +1,73 @@ +#include "LineClass.h" +#include <math.h> + +/* + * Constructor + */ + +LineClass::LineClass(float x0, + float y0, + float z0, + float ax, + float ay, + float az) { + _x0[0] = x0; + _x0[1] = y0; + _x0[2] = z0; + _ax[0] = ax; + _ax[1] = ay; + _ax[2] = az; +} + +LineClass::LineClass(float *x0, + float *ax) { + + for (int i=0; i<3; ++i) { + _x0[i] = x0[i]; + _ax[i] = ax[i]; + } +} + +float * LineClass::getReferencePoint() { + return _x0; +} + +float * LineClass::getDirectionalVector() { + return _ax; +} + +void LineClass::setReferencePoint(float *x0) { + for (int i=0; i<3; ++i) + _x0[i] = x0[i]; +} + +void LineClass::setDirectionalVector(float *ax) { + for (int i=0; i<3; ++i) + _ax[i] = ax[i]; + +} + +float LineClass::getDistanceToPoint(float * xpoint, float * pos) { + + float dif[3]; + float prod = 0; + float den = 0; + for (int i=0; i<3; ++i) { + dif[i] = xpoint[i] - _x0[i]; + prod += _ax[i]*dif[i]; + den += _ax[i]*_ax[i]; + } + float time = prod/fmax(1e-10,den); + + float dist = 0.0; + for (int i=0; i<3; ++i) { + pos[i] = _x0[i] + _ax[i]*time; + dist += (xpoint[i]-pos[i])*(xpoint[i]-pos[i]); + } + dist = sqrt(dist); + + return dist; + + + +} diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h new file mode 100644 index 00000000..98970a26 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h @@ -0,0 +1,32 @@ +#ifndef LINECLASS_H +#define LINECLASS_H +class LineClass { + + public: + LineClass(float x0, + float y0, + float z0, + float ax, + float ay, + float az); + + LineClass(float *x0, + float *ax); + + ~LineClass(); + + float * getReferencePoint(); + void setReferencePoint(float *x0); + float * getDirectionalVector(); + void setDirectionalVector(float *ax); + float getDistanceToPoint(float * xpoint, float * pos); + + private: + + float _x0[3]; + float _ax[3]; + + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt b/Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt new file mode 100644 index 00000000..99429ca5 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt @@ -0,0 +1,57 @@ +gaudi_subdir(MatrixPandora v0r0) + +find_package(DD4hep COMPONENTS DDG4 REQUIRED) +find_package(CLHEP REQUIRED) +find_package(GSL REQUIRED )##don't use this, use CEPC LCIO version one , due to the ClusterShape.cc file which is from LCIO +message("GSL: ${GSL_LIBRARIES} ") +set (gsl_include "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/include") +set (gsl_lib1 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgsl.so") +set (gsl_lib2 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgslcblas.so") +find_package(LCIO REQUIRED ) +find_package(GEAR REQUIRED) +#message("ENV GEAR: $ENV{GEAR}") +find_package(EDM4HEP REQUIRED ) +#message("EDM4HEP_INCLUDE_DIRS: ${EDM4HEP_INCLUDE_DIR}") +#message("EDM4HEP_LIB: ${EDM4HEP_LIBRARIES}") +include_directories(${EDM4HEP_INCLUDE_DIR}) +link_libraries("/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/externals/97.0.0/EDM4hep/lib64/libedm4hep.so") +find_package(PandoraSDK REQUIRED ) +#message("PandoraSDK_INCLUDE_DIRS: ${PandoraSDK_INCLUDE_DIRS}") +#message("PandoraSDK_LIB: ${PandoraSDK_LIBRARIES}") +find_package(LCContent REQUIRED ) +#message("LCContent_INCLUDE_DIRS: ${LCContent_INCLUDE_DIRS}") +#message("LCContent_LIB: ${LCContent_LIBRARIES}") +include_directories(${PandoraSDK_INCLUDE_DIRS}) +link_libraries(${PandoraSDK_LIBRARIES}) +include_directories(${LCContent_INCLUDE_DIRS}) +link_libraries(${LCContent_LIBRARIES}) + + +list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") +find_package(ROOT 5.26.00 REQUIRED COMPONENTS Eve Geom RGL EG) + +include_directories("../CED/CED/") +include_directories("../MarlinUtil/01-08/source/") + +gaudi_depends_on_subdirs( + Service/EventSeeder + Service/GearSvc + Detector/DetInterface +) + +set(dir_srcs + src/PandoraMatrixAlg.cpp + src/MCParticleCreator.cpp + src/GeometryCreator.cpp + src/CaloHitCreator.cpp + src/TrackCreator.cpp + src/PfoCreator.cpp + ../CED/CED/*.cc + ../MarlinUtil/01-08/source/*.cc +) +set(dir_include include) +# Modules +gaudi_add_module(MatrixPandora ${dir_srcs} + INCLUDE_DIRS ${gsl_include} ${dir_include} GaudiKernel FWCore CLHEP ${LCIO_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} gear DD4hep + LINK_LIBRARIES ${gsl_lib1} ${gsl_lib2} GaudiKernel FWCore CLHEP ROOT ${LCIO_LIBRARIES} $ENV{GEAR}/lib/libgear.so $ENV{GEAR}/lib/libgearxml.so DD4hep ${DD4hep_COMPONENT_LIBRARIES} DDRec +) diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h new file mode 100644 index 00000000..c7714205 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h @@ -0,0 +1,298 @@ +/** + * @file MarlinPandora/include/CaloHitCreator.h + * + * @brief Header file for the calo hit creator class. + * + * $Log: $ + */ + +#ifndef CALO_HIT_CREATOR_H +#define CALO_HIT_CREATOR_H 1 + +#include "GaudiKernel/ISvcLocator.h" +#include "edm4hep/CalorimeterHit.h" + +#include "gear/LayerLayout.h" + +#include "Api/PandoraApi.h" + +#include "DetInterface/IGeoSvc.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/Detector.h" +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include "DD4hep/BitFieldCoder.h" + + +#include <string> + +typedef std::vector<edm4hep::CalorimeterHit *> CalorimeterHitVector; + +namespace gear { class GearMgr; } + +class CollectionMaps; +/** + * @brief CaloHitCreator class + */ +class CaloHitCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_eCalCaloHitCollections; ///< The ecal calorimeter hit collections + StringVector m_hCalCaloHitCollections; ///< The hcal calorimeter hit collections + StringVector m_lCalCaloHitCollections; ///< The lcal calorimeter hit collections + StringVector m_lHCalCaloHitCollections; ///< The lhcal calorimeter hit collections + StringVector m_muonCaloHitCollections; ///< The muon calorimeter hit collections + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + float m_eCalToMip; ///< The calibration from deposited ECal energy to mip + float m_hCalToMip; ///< The calibration from deposited HCal energy to mip + float m_muonToMip; ///< The calibration from deposited Muon energy to mip + float m_eCalMipThreshold; ///< Threshold for creating calo hits in the ECal, units mip + float m_hCalMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + float m_muonMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + + float m_eCalToEMGeV; ///< The calibration from deposited ECal energy to EM energy + float m_eCalToHadGeVBarrel; ///< The calibration from deposited ECal barrel energy to hadronic energy + float m_eCalToHadGeVEndCap; ///< The calibration from deposited ECal endcap energy to hadronic energy + float m_hCalToEMGeV; ///< The calibration from deposited HCal energy to EM energy + float m_hCalToHadGeV; ///< The calibration from deposited HCal energy to hadronic energy + int m_muonDigitalHits; ///< Muon hits are treated as digital (energy from hit count) + float m_muonHitEnergy; ///< The energy for a digital muon calorimeter hit, units GeV + + float m_maxHCalHitHadronicEnergy; ///< The maximum hadronic energy allowed for a single hcal hit + int m_nOuterSamplingLayers; ///< Number of layers from edge for hit to be flagged as an outer layer hit + float m_layersFromEdgeMaxRearDistance; ///< Maximum number of layers from candidate outer layer hit to rear of detector + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD00 gear file) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD00 gear file) + + // For Strip Splitting method and hybrid ECAL. + int m_stripSplittingOn; ///< To use SSA, this should be true (default is false) + int m_useEcalScLayers; ///< To use scintillator layers ~ hybrid ECAL, this should be true (default is false) + float m_eCalSiToMip; ///< The calibration from deposited Si-layer energy to mip + float m_eCalScToMip; ///< The calibration from deposited Sc-layer energy to mip + float m_eCalSiMipThreshold; ///< Threshold for creating calo hits in the Si-layers of ECAL, units mip + float m_eCalScMipThreshold; ///< Threshold for creating calo hits in the Sc-layers of ECAL, units mip + float m_eCalSiToEMGeV; ///< The calibration from deposited Si-layer energy to EM energy + float m_eCalScToEMGeV; ///< The calibration from deposited Sc-layer energy to EM energy + float m_eCalSiToHadGeVBarrel; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVBarrel; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + float m_eCalSiToHadGeVEndCap; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVEndCap; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style); + + /** + * @brief Destructor + */ + ~CaloHitCreator(); + + /** + * @brief Create calo hits + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateCaloHits(const LCEvent *const pLCEvent); + pandora::StatusCode CreateCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get the calorimeter hit vector + * + * @return The calorimeter hit vector + */ + const CalorimeterHitVector &GetCalorimeterHitVector() const; + + /** + * @brief Reset the calo hit creator + */ + void Reset(); + +private: + /** + * @brief Create ecal calo hits + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateECalCaloHits(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode CreateECalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create hcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create muon calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateMuonCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateLCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lhcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateLHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get common calo hit properties: position, parent address, input energy and time + * + * @param pCaloHit the lcio calorimeter hit + * @param caloHitParameters the calo hit parameters to populate + */ + void GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const; + + /** + * @brief Get end cap specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + * @param pCaloHit the lcio calorimeter hit + * @param layerLayout the gear end cap layer layout + * @param caloHitParameters the calo hit parameters to populate + * @param absorberCorrection to receive the absorber thickness correction for the mip equivalent energy + */ + void GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const; + + /** + * @brief Get barrel specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + * @param pCaloHit the lcio calorimeter hit + * @param layerLayout the gear barrel layer layout + * @param barrelSymmetryOrder the barrel order of symmetry + * @param barrelPhi0 the barrel orientation + * @param staveNumber the stave number + * @param caloHitParameters the calo hit parameters to populate + * @param absorberCorrection to receive the absorber thickness correction for the mip equivalent energy + */ + void GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const; + + void GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const; + /** + * @brief Get number of active layers from position of a calo hit to the edge of the detector + * + * @param pCaloHit the lcio calorimeter hit + */ + int GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const; + + /** + * @brief Get the maximum radius of a calo hit in a polygonal detector structure + * + * @param pCaloHit the lcio calorimeter hit + * @param symmetryOrder the symmetry order + * @param phi0 the angular orientation + * + * @return the maximum radius + */ + float GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const; + + void GetCoding(const edm4hep::CalorimeterHit* pCaloHit, long& sys, long& x, long& y, long& z) const ; + int GetBarrelLayer(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout) const; + /** + * @brief Get the layer coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the layer coding string + */ + std::string GetLayerCoding(const std::string &encodingString) const; + + /** + * @brief Get the stave coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the stave coding string + */ + std::string GetStaveCoding(const std::string &encodingString) const; + + const Settings m_settings; ///< The calo hit creator settings + + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create calo hits + + float m_eCalBarrelOuterZ; ///< ECal barrel outer z coordinate + float m_hCalBarrelOuterZ; ///< HCal barrel outer z coordinate + float m_muonBarrelOuterZ; ///< Muon barrel outer z coordinate + float m_coilOuterR; ///< Coil outer r coordinate + + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi0 coordinate + unsigned int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_hCalBarrelInnerPhi0; ///< HCal barrel inner phi0 coordinate + unsigned int m_hCalBarrelInnerSymmetry; ///< HCal barrel inner symmetry order + float m_muonBarrelInnerPhi0; ///< Muon barrel inner phi0 coordinate + unsigned int m_muonBarrelInnerSymmetry; ///< Muon barrel inner symmetry order + + float m_hCalEndCapOuterR; ///< HCal endcap outer r coordinate + float m_hCalEndCapOuterZ; ///< HCal endcap outer z coordinate + float m_hCalBarrelOuterR; ///< HCal barrel outer r coordinate + float m_hCalBarrelOuterPhi0; ///< HCal barrel outer phi0 coordinate + unsigned int m_hCalBarrelOuterSymmetry; ///< HCal barrel outer symmetry order + + float m_hCalBarrelLayerThickness; ///< HCal barrel layer thickness + float m_hCalEndCapLayerThickness; ///< HCal endcap layer thickness + + CalorimeterHitVector m_calorimeterHitVector; ///< The calorimeter hit vector + std::string m_encoder_str; + std::string m_encoder_str_MUON ; + std::string m_encoder_str_LCal ; + std::string m_encoder_str_LHCal; + gear::GearMgr* _GEAR; + dd4hep::Detector* m_dd4hep; + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + std::string m_compact ; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const CalorimeterHitVector &CaloHitCreator::GetCalorimeterHitVector() const +{ + return m_calorimeterHitVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void CaloHitCreator::Reset() +{ + m_calorimeterHitVector.clear(); +} + +#endif // #ifndef CALO_HIT_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h new file mode 100644 index 00000000..0a0c1ae2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h @@ -0,0 +1,166 @@ +/** + * @file MarlinPandora/include/GeometryCreator.h + * + * @brief Header file for the geometry creator class. + * + * $Log: $ + */ + +#ifndef GEOMETRY_CREATOR_H +#define GEOMETRY_CREATOR_H 1 + +#include "Api/PandoraApi.h" + +#include "GaudiKernel/ISvcLocator.h" + +#include "DetInterface/IGeoSvc.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/Detector.h" + +namespace gear { class CalorimeterParameters; class GearMgr; } + +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief GeometryCreator class + */ +class GeometryCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + int m_eCalEndCapInnerSymmetryOrder; ///< ECal end cap inner symmetry order (missing from ILD gear files) + float m_eCalEndCapInnerPhiCoordinate; ///< ECal end cap inner phi coordinate (missing from ILD gear files) + int m_eCalEndCapOuterSymmetryOrder; ///< ECal end cap outer symmetry order (missing from ILD gear files) + float m_eCalEndCapOuterPhiCoordinate; ///< ECal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD gear files) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD gear files) + int m_hCalEndCapOuterSymmetryOrder; ///< HCal end cap outer symmetry order (missing from ILD gear files) + float m_hCalEndCapOuterPhiCoordinate; ///< HCal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalRingInnerSymmetryOrder; ///< HCal ring inner symmetry order (missing from ILD gear files) + float m_hCalRingInnerPhiCoordinate; ///< HCal ring inner phi coordinate (missing from ILD gear files) + int m_hCalRingOuterSymmetryOrder; ///< HCal ring outer symmetry order (missing from ILD gear files) + float m_hCalRingOuterPhiCoordinate; ///< HCal ring outer phi coordinate (missing from ILD gear files) + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~GeometryCreator(); + + /** + * @brief Create geometry + */ + //pandora::StatusCode CreateGeometry() const; + pandora::StatusCode CreateGeometry(ISvcLocator* svcloc); + +private: + typedef std::map<pandora::SubDetectorType, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorTypeMap; + typedef std::map<std::string, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorNameMap; + + /** + * @brief Set mandatory sub detector parameters + * + * @param subDetectorTypeMap the sub detector type map + */ + void SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Set additional sub detector parameters + * + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + void SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Set sub detector parameters to their gear default values + * + * @param inputParameters input parameters, from gear + * @param subDetectorName the sub detector name + * @param subDetectorType the sub detector type + * @param parameters the sub detector parameters + */ + void SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const; + + void SetDefaultSubDetectorParameters(const dd4hep::Detector* theDetector, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const; + + /** + * @brief Set positions of gaps in ILD detector and add information missing from GEAR parameters file + * + * @param subDetectorTypeMap the sub detector type map + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + pandora::StatusCode SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Add information missing from GEAR parameters file for ILD SDHCAL detector + * + * @param subDetectorTypeMap the sub detector type map + */ + pandora::StatusCode SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Specify positions of hcal barrel box gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelBoxGaps() const; + + /** + * @brief Specify positions of hcal end cap box gaps - ILD specific + */ + pandora::StatusCode CreateHCalEndCapBoxGaps() const; + + /** + * @brief Specify positions of hcal barrel concentric polygon gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelConcentricGaps() const; + + /** + * @brief Create box gaps at regular positions on polygonal prism, oriented along main z axis - ILD specific + * + * @param symmetryOrder the pandora geometry parameters + * @param phi0 the phi coordinate + * @param innerRadius the inner r coordinate + * @param outerRadius the outer r coordinate + * @param minZ the minimum z coordinate + * @param maxZ the maximum z coordinate + * @param gapWidth the gap width + * @param vertexOffset position offset for vertex that doesn't point back to origin of xy plane + */ + pandora::StatusCode CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, float minZ, + float maxZ, float gapWidth, pandora::CartesianVector vertexOffset = pandora::CartesianVector(0, 0, 0)) const; + + const Settings m_settings; ///< The geometry creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the geometry + gear::GearMgr* _GEAR; + dd4hep::Detector* m_dd4hep; +}; + +#endif // #ifndef GEOMETRY_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h new file mode 100644 index 00000000..4ad9f275 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h @@ -0,0 +1,98 @@ +/** + * @file MarlinPandora/include/MCParticleCreator.h + * + * @brief Header file for the mc particle creator class. + * + * $Log: $ + */ + +#ifndef MC_PARTICLE_CREATOR_H +#define MC_PARTICLE_CREATOR_H 1 + +#include "edm4hep/MCParticle.h" +#include "Api/PandoraApi.h" + +#include "CaloHitCreator.h" +#include "TrackCreator.h" +/** + * @brief MCParticleCreator class + */ + +class CollectionMaps; + +class MCParticleCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_mcParticleCollections; ///< The mc particle collections + StringVector m_CaloHitRelationCollections; ///< The SimCaloHit to CaloHit particle relations + StringVector m_TrackRelationCollections; ///< The SimTrackerHit to TrackerHit particle relations + float m_bField; ///< m_bField + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~MCParticleCreator(); + + /** + * @brief Create MCParticles + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateMCParticles(const EVENT::LCEvent *const pLCEvent) const; + //pandora::StatusCode CreateMCParticles(const std::map<std::string, const podio::CollectionBase*>& collectionMap ) const; + pandora::StatusCode CreateMCParticles(const CollectionMaps& collectionMaps ) const; + + /** + * @brief Create Track to mc particle relationships + * + * @param pLCEvent the lcio event + * @param trackVector the vector containing all tracks successfully passed to pandora + */ + // pandora::StatusCode CreateTrackToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const TrackVector &trackVector) const; + pandora::StatusCode CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const; + + void Reset(); + /** + * @brief Create calo hit to mc particle relationships + * + * @param pLCEvent the lcio event + * @param calorimeterHitVector the vector containing all calorimeter hits successfully passed to pandora + */ +// pandora::StatusCode CreateCaloHitToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const CalorimeterHitVector &calorimeterHitVector) const; + pandora::StatusCode CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const; + +private: + const Settings m_settings; ///< The mc particle creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the mc particles + const float m_bField; ///< The bfield + std::map<unsigned int, const edm4hep::MCParticle*>* m_id_pMC_map; +}; + +inline void MCParticleCreator::Reset() +{ + m_id_pMC_map->clear(); +} + +#endif // #ifndef MC_PARTICLE_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h new file mode 100644 index 00000000..96a6938b --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h @@ -0,0 +1,324 @@ +#ifndef PandoraMatrixAlg_H +#define PandoraMatrixAlg_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include <gsl/gsl_rng.h> +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" +#include "edm4hep/MCRecoCaloAssociationCollection.h" +#include "edm4hep/MCRecoParticleAssociation.h" +#include "edm4hep/MCRecoParticleAssociationCollection.h" + +#include "Api/PandoraApi.h" + +#ifdef MONITORING +#include "TApplication.h" +#endif + +#include <iostream> +#include <random> +#include <string> +#include <unistd.h> + + +#include "CaloHitCreator.h" +#include "GeometryCreator.h" +#include "MCParticleCreator.h" +#include "PfoCreator.h" +#include "TrackCreator.h" + +#include "TROOT.h" +#include "TTree.h" +#include "TFile.h" + + +/* PandoraMatrixAlg ========== <br> + * + */ +namespace pandora {class Pandora;} + +class IEventSeeder; + +class CollectionMaps +{ +public: + /** + * @brief Default constructor + */ + CollectionMaps(); + void clear(); + std::map<std::string, const edm4hep::MCParticleCollection*> CollectionMap_MC; + std::map<std::string, const edm4hep::CalorimeterHitCollection*> CollectionMap_CaloHit; + std::map<std::string, const edm4hep::VertexCollection*> CollectionMap_Vertex; + std::map<std::string, const edm4hep::TrackCollection*> CollectionMap_Track; + + std::map<std::string, std::vector<edm4hep::MCParticle> > collectionMap_MC; + std::map<std::string, std::vector<edm4hep::CalorimeterHit> > collectionMap_CaloHit; + std::map<std::string, std::vector<edm4hep::Vertex> > collectionMap_Vertex; + std::map<std::string, std::vector<edm4hep::Track> > collectionMap_Track; + std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> > collectionMap_CaloRel; + std::map<std::string, std::vector<edm4hep::MCRecoTrackerAssociation> > collectionMap_TrkRel; +}; + + + +class PandoraMatrixAlg : public GaudiAlgorithm +{ + //friend class AlgFactory<PandoraMatrixAlg>;//gives error in 97 version + +public: + + PandoraMatrixAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + /** Called for every event - the working horse. + */ + virtual StatusCode execute() ; + + /** Called after data processing for clean up. + */ + virtual StatusCode finalize() ; + + //void FinaliseSteeringParameters(); + void FinaliseSteeringParameters(ISvcLocator* svcloc); + pandora::StatusCode RegisterUserComponents() const; + void Reset(); + typedef std::vector<float> FloatVector; + typedef std::vector<std::string> StringVector; + + + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_pandoraSettingsXmlFile; ///< The pandora settings xml file + + float m_innerBField; ///< The bfield in the main tracker, ecal and hcal, units Tesla + float m_muonBarrelBField; ///< The bfield in the muon barrel, units Tesla + float m_muonEndCapBField; ///< The bfield in the muon endcap, units Tesla + + FloatVector m_inputEnergyCorrectionPoints; ///< The input energy points for non-linearity energy correction + FloatVector m_outputEnergyCorrectionPoints; ///< The output energy points for non-linearity energy correction + }; + + + /** + * @brief Get address of the pandora instance + * + * @return address of the pandora instance + */ + const pandora::Pandora *GetPandora() const; + StatusCode updateMap(); + StatusCode updateMap(CollectionMaps & tmp_map); + StatusCode Ana(); + StatusCode CreateMCRecoParticleAssociation(); + //StatusCode Create_MC(); +protected: + + typedef std::vector<float> FloatVec; + + int _nEvt ; + + IEventSeeder * _SEEDER; + + + Gaudi::Property< std::string > m_PandoraSettingsXmlFile { this, "PandoraSettingsDefault_xml", "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" }; + Gaudi::Property<int> m_NEventsToSkip { this, "NEventsToSkip", 0 }; + + Gaudi::Property< std::vector<std::string> > m_TrackCollections{ this, "TrackCollections", {"MarlinTrkTracks"} }; + Gaudi::Property< std::vector<std::string> > m_ECalCaloHitCollections{ this, "ECalCaloHitCollections", {"ECALBarrel","ECALEndcap","ECALOther"} }; + Gaudi::Property< std::vector<std::string> > m_HCalCaloHitCollections{ this, "HCalCaloHitCollections", {"HCALBarrel","HCALEndcap","HCALOther"} }; + Gaudi::Property< std::vector<std::string> > m_LCalCaloHitCollections{ this, "LCalCaloHitCollections", {"LCAL"} }; + Gaudi::Property< std::vector<std::string> > m_LHCalCaloHitCollections{ this, "LHCalCaloHitCollections", {"LHCAL"} }; + Gaudi::Property< std::vector<std::string> > m_MuonCaloHitCollections{ this, "MuonCaloHitCollections", {"MUON"} }; + Gaudi::Property< std::vector<std::string> > m_MCParticleCollections{ this, "MCParticleCollections", {"MCParticle"} }; + Gaudi::Property< std::vector<std::string> > m_RelCaloHitCollections{ this, "RelCaloHitCollections", {"RelationCaloHit","RelationMuonHit"} }; + Gaudi::Property< std::vector<std::string> > m_RelTrackCollections{ this, "RelTrackCollections", {"MarlinTrkTracksMCTruthLink"} }; + Gaudi::Property< std::vector<std::string> > m_KinkVertexCollections{ this, "KinkVertexCollections", {"KinkVertices"} }; + Gaudi::Property< std::vector<std::string> > m_ProngVertexCollections{ this, "ProngVertexCollections", {"ProngVertices"} }; + Gaudi::Property< std::vector<std::string> > m_SplitVertexCollections{ this, "SplitVertexCollections", {"SplitVertices"} }; + Gaudi::Property< std::vector<std::string> > m_V0VertexCollections{ this, "V0VertexCollections", {"V0Vertices"} }; + Gaudi::Property< std::string > m_ClusterCollectionName { this, "ClusterCollectionName", "PandoraClusters" }; + Gaudi::Property< std::string > m_PFOCollectionName { this, "PFOCollectionName", "PandoraPFOs" }; + Gaudi::Property<float> m_ECalToMipCalibration{ this, "ECalToMipCalibration", 160.0 }; + Gaudi::Property<float> m_HCalToMipCalibration{ this, "HCalToMipCalibration", 34.8 }; + Gaudi::Property<float> m_ECalMipThreshold{ this, "ECalMipThreshold", 0.5 }; + Gaudi::Property<float> m_HCalMipThreshold{ this, "HCalMipThreshold", 0.3 }; + Gaudi::Property<float> m_ECalToEMGeVCalibration{ this, "ECalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_HCalToEMGeVCalibration{ this, "HCalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationBarrel{ this, "ECalToHadGeVCalibrationBarrel", 1.12 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationEndCap{ this, "ECalToHadGeVCalibrationEndCap", 1.12 }; + Gaudi::Property<float> m_HCalToHadGeVCalibration{ this, "HCalToHadGeVCalibration", 1.07 }; + Gaudi::Property<float> m_MuonToMipCalibration{ this, "MuonToMipCalibration", 10.0 }; + Gaudi::Property<int> m_DigitalMuonHits{ this, "DigitalMuonHits", 0 }; + Gaudi::Property<float> m_MaxHCalHitHadronicEnergy{ this, "MaxHCalHitHadronicEnergy", 1.0 }; + Gaudi::Property<int> m_UseOldTrackStateCalculation{ this, "UseOldTrackStateCalculation", 0 }; + + + Gaudi::Property<float> m_AbsorberRadLengthECal{ this, "AbsorberRadLengthECal", 0.2854 }; + Gaudi::Property<float> m_AbsorberIntLengthECal{ this, "AbsorberIntLengthECal", 0.0101 }; + Gaudi::Property<float> m_AbsorberRadLengthHCal{ this, "AbsorberRadLengthHCal", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthHCal{ this, "AbsorberIntLengthHCal", 0.006 }; + Gaudi::Property<float> m_AbsorberRadLengthOther{ this, "AbsorberRadLengthOther", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthOther{ this, "AbsorberIntLengthOther", 0.006 }; + Gaudi::Property< std::string > m_StartVertexCollectionName { this, "StartVertexCollectionName", "PandoraPFANewStartVertices" }; + Gaudi::Property< std::string > m_StartVertexAlgorithmName { this, "StartVertexAlgorithmName", "PandoraPFANew" }; + Gaudi::Property<float> m_EMStochasticTerm{ this, "EMStochasticTerm", 0.17 }; + Gaudi::Property<float> m_HadStochasticTerm{ this, "HadStochasticTerm", 0.6 }; + Gaudi::Property<float> m_EMConstantTerm{ this, "EMConstantTerm", 0.01 }; + Gaudi::Property<float> m_HadConstantTerm{ this, "HadConstantTerm", 0.03 }; + Gaudi::Property<float> m_MuonHitEnergy{ this, "MuonHitEnergy", 0.5 }; + Gaudi::Property<int> m_NOuterSamplingLayers{ this, "NOuterSamplingLayers", 3 }; + Gaudi::Property<float> m_LayersFromEdgeMaxRearDistance{ this, "LayersFromEdgeMaxRearDistance", 250.f }; + Gaudi::Property<float> m_MuonBarrelBField{ this, "MuonBarrelBField", -1.5f }; + Gaudi::Property<float> m_MuonEndCapBField{ this, "MuonEndCapBField", 0.01f }; + Gaudi::Property<int> m_ShouldFormTrackRelationships{ this, "ShouldFormTrackRelationships", 1 }; + Gaudi::Property<int> m_MinTrackHits{ this, "MinTrackHits", 5 }; + Gaudi::Property<int> m_MinFtdTrackHits{ this, "MinFtdTrackHits", 0 }; + Gaudi::Property<int> m_MaxTrackHits{ this, "MaxTrackHits", 5000 }; + Gaudi::Property<float> m_D0TrackCut{ this, "D0TrackCut", 50. }; + Gaudi::Property<float> m_Z0TrackCut{ this, "Z0TrackCut", 50. }; + Gaudi::Property<int> m_UseNonVertexTracks{ this, "UseNonVertexTracks", 1 }; + Gaudi::Property<int> m_UseUnmatchedNonVertexTracks{ this, "UseUnmatchedNonVertexTracks", 0 }; + Gaudi::Property<int> m_UseUnmatchedVertexTracks{ this, "UseUnmatchedVertexTracks", 1 }; + Gaudi::Property<float> m_UnmatchedVertexTrackMaxEnergy{ this, "UnmatchedVertexTrackMaxEnergy", 5. }; + Gaudi::Property<float> m_D0UnmatchedVertexTrackCut{ this, "D0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_Z0UnmatchedVertexTrackCut{ this, "Z0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_ZCutForNonVertexTracks{ this, "ZCutForNonVertexTracks", 250. }; + Gaudi::Property<int> m_ReachesECalNTpcHits{ this, "ReachesECalNTpcHits", 11 }; + Gaudi::Property<int> m_ReachesECalNFtdHits{ this, "ReachesECalNFtdHits", 4 }; + Gaudi::Property<float> m_ReachesECalTpcOuterDistance{ this, "ReachesECalTpcOuterDistance", -100. }; + Gaudi::Property<int> m_ReachesECalMinFtdLayer{ this, "ReachesECalMinFtdLayer", 9 }; + Gaudi::Property<float> m_ReachesECalTpcZMaxDistance{ this, "ReachesECalTpcZMaxDistance", -50. }; + Gaudi::Property<float> m_ReachesECalFtdZMaxDistance{ this, "ReachesECalFtdZMaxDistance", -1. }; + Gaudi::Property<float> m_CurvatureToMomentumFactor{ this, "CurvatureToMomentumFactor", 0.3 / 2000. }; + Gaudi::Property<float> m_MinTrackECalDistanceFromIp{ this, "MinTrackECalDistanceFromIp", 100. }; + + Gaudi::Property<float> m_MaxTrackSigmaPOverP { this, "MaxTrackSigmaPOverP", 0.15 }; + Gaudi::Property<float> m_MinMomentumForTrackHitChecks { this, "MinMomentumForTrackHitChecks", 1. }; + Gaudi::Property<float> m_TpcMembraneMaxZ { this, "TpcMembraneMaxZ", 10. }; + Gaudi::Property<float> m_MinTpcHitFractionOfExpected { this, "MinTpcHitFractionOfExpected", 0.20 }; + Gaudi::Property<int> m_MinFtdHitsForTpcHitFraction { this, "MinFtdHitsForTpcHitFraction", 2 }; + Gaudi::Property<float> m_MaxTpcInnerRDistance { this, "MaxTpcInnerRDistance", 50.0 }; + Gaudi::Property<int> m_ECalEndCapInnerSymmetryOrder { this, "ECalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_ECalEndCapInnerPhiCoordinate { this, "ECalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_ECalEndCapOuterSymmetryOrder { this, "ECalEndCapOuterSymmetryOrder", 8 }; + Gaudi::Property<float> m_ECalEndCapOuterPhiCoordinate { this, "ECalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapInnerSymmetryOrder { this, "HCalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_HCalEndCapInnerPhiCoordinate { this, "HCalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapOuterSymmetryOrder { this, "HCalEndCapOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalEndCapOuterPhiCoordinate { this, "HCalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingInnerSymmetryOrder { this, "HCalRingInnerSymmetryOrder", 8 }; + Gaudi::Property<float> m_HCalRingInnerPhiCoordinate { this, "HCalRingInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingOuterSymmetryOrder { this, "HCalRingOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalRingOuterPhiCoordinate { this, "HCalRingOuterPhiCoordinate", 0. }; + Gaudi::Property<bool> m_StripSplittingOn { this, "StripSplittingOn", false }; + Gaudi::Property<bool> m_UseEcalScLayers { this, "UseEcalScLayers", false }; + Gaudi::Property<float> m_ECalSiToMipCalibration { this, "ECalSiToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalScToMipCalibration { this, "ECalScToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalSiMipThreshold { this, "ECalSiMipThreshold", 0. }; + Gaudi::Property<float> m_ECalScMipThreshold { this, "ECalScMipThreshold", 0. }; + Gaudi::Property<float> m_ECalSiToEMGeVCalibration { this, "ECalSiToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalScToEMGeVCalibration { this, "ECalScToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationEndCap { this, "ECalSiToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationEndCap { this, "ECalScToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationBarrel { this, "ECalSiToHadGeVCalibrationBarrel", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationBarrel { this, "ECalScToHadGeVCalibrationBarrel", 1. }; + + Gaudi::Property<FloatVector> m_InputEnergyCorrectionPoints { this, "InputEnergyCorrectionPoints", {} }; + Gaudi::Property<FloatVector> m_OutputEnergyCorrectionPoints { this, "OutputEnergyCorrectionPoints", {} }; + + + static pandora::Pandora *m_pPandora; + GeometryCreator *m_pGeometryCreator; ///< The geometry creator + CaloHitCreator *m_pCaloHitCreator; ///< The calo hit creator + TrackCreator *m_pTrackCreator; ///< The track creator + MCParticleCreator *m_pMCParticleCreator; ///< The mc particle creator + PfoCreator *m_pPfoCreator; ///< The pfo creator + + Settings m_settings; ///< The settings for the pandora pfa new algo + CollectionMaps *m_CollectionMaps; ///< The settings for the pandora pfa new algo + GeometryCreator::Settings m_geometryCreatorSettings; ///< The geometry creator settings + TrackCreator::Settings m_trackCreatorSettings; ///< The track creator settings + CaloHitCreator::Settings m_caloHitCreatorSettings; ///< The calo hit creator settings + MCParticleCreator::Settings m_mcParticleCreatorSettings; ///< The mc particle creator settings + PfoCreator::Settings m_pfoCreatorSettings; ///< The pfo creator settings + + std::string m_detectorName; ///< The detector name + unsigned int m_nRun; ///< The run number + unsigned int m_nEvent; ///< The event number + //### For Ana ################# + TFile* m_fout; + TTree* m_tree; + std::vector<int > m_pReco_PID; + std::vector<float> m_pReco_mass; + std::vector<float> m_pReco_energy; + std::vector<float> m_pReco_px; + std::vector<float> m_pReco_py; + std::vector<float> m_pReco_pz; + std::vector<float> m_pReco_charge; + + std::vector<int> m_mc_p_size; + std::vector<int> m_mc_pid ; + std::vector<float> m_mc_mass ; + std::vector<float> m_mc_px ; + std::vector<float> m_mc_py ; + std::vector<float> m_mc_pz ; + std::vector<float> m_mc_charge; + int m_hasConversion; + std::vector<float> m_hits_x ; + std::vector<float> m_hits_y ; + std::vector<float> m_hits_z ; + std::vector<float> m_hits_E ; + + Gaudi::Property< std::string > m_AnaOutput{ this, "AnaOutput", "/junofs/users/wxfang/MyGit/CEPCSW/Reconstruction/PFA/Pandora/GaudiPandora/Ana.root" }; + //###################### + + DataHandle<edm4hep::MCParticleCollection> m_mcParCol_r {"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALBarrel_r{"ECALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALEndcap_r{"ECALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALOther_r {"ECALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALBarrel_r{"HCALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALEndcap_r{"HCALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALOther_r {"HCALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_MUON_r {"MUON", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LCAL_r {"LCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LHCAL_r {"LHCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_BCAL_r {"BCAL", Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::VertexCollection> m_KinkVertices_r {"KinkVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_ProngVertices_r {"ProngVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_SplitVertices_r {"SplitVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_V0Vertices_r {"V0Vertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackCollection> m_MarlinTrkTracks_r {"MarlinTrkTracks",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoCaloAssociationCollection> m_MCRecoCaloAssociation_r {"MCRecoCaloAssociation",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> m_MCRecoTrackerAssociation_r {"MCRecoTrackerAssociation",Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::ClusterCollection> m_ClusterCollection_w {"PandoraClusters",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::ReconstructedParticleCollection> m_ReconstructedParticleCollection_w {"PandoraPFOs" ,Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::VertexCollection> m_VertexCollection_w {"PandoraPFANewStartVertices",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoParticleAssociationCollection> m_MCRecoParticleAssociation_w {"pfoMCRecoParticleAssociation",Gaudi::DataHandle::Writer, this}; + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h new file mode 100644 index 00000000..83c6e149 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h @@ -0,0 +1,219 @@ +/** + * @file MarlinPandora/include/PfoCreator.h + * + * @brief Header file for the pfo creator class. + * + * $Log: $ + */ + +#ifndef PFO_CREATOR_H +#define PFO_CREATOR_H 1 + +#include "FWCore/DataHandle.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/Cluster.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/ReconstructedParticle.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/Vertex.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/Track.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/CalorimeterHit.h" + +#include "ClusterShapes.h" +#include "Api/PandoraApi.h" + +class CollectionMaps; +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief PfoCreator class + */ +class PfoCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_clusterCollectionName; ///< The name of the cluster output collection + std::string m_pfoCollectionName; ///< The name of the pfo output collection + std::string m_startVertexCollectionName; ///< The name of the start vertex output collection + std::string m_startVertexAlgName; ///< The name of the algorithm to fill the start vertex output collection + float m_emStochasticTerm; ///< The stochastic term for EM shower energy resolution + float m_hadStochasticTerm; ///< The stochastic term for Hadronic shower energy resolution + float m_emConstantTerm; ///< The constant term for EM shower energy resolution + float m_hadConstantTerm; ///< The constant term for Hadronic shower energy resolution + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~PfoCreator(); + + /** + * @brief Create particle flow objects + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateParticleFlowObjects(EVENT::LCEvent *pLCEvent); + //pandora::StatusCode CreateParticleFlowObjects(const CollectionMaps& collectionMaps); + pandora::StatusCode CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection); + + CollectionMaps* m_collectionMaps; + +private: + /** + * @brief index for the subdetector + */ + enum Index + { + ECAL_INDEX = 0, + HCAL_INDEX = 1, + YOKE_INDEX = 2, + LCAL_INDEX = 3, + LHCAL_INDEX = 4, + BCAL_INDEX = 5 + }; + + /** + * @brief initialise sub detector name strings + * + * @param subDetectorNames to receive the list of sub detector names + */ + void InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const; + + /** + * @brief Set sub detector energies for a cluster + * + * @param subDetectorNames the list of sub detector names + * @param pLcioCluster the address of the lcio cluster to be set sub detector energies + * @param pandoraCaloHitList the pandora calorimeter hit list + * @param hitE the vector to receive the energy of hits + * @param hitX the vector to receive the x position of hits + * @param hitY the vector to receive the y position of hits + * @param hitZ the vector to receive the z position of hits + */ + void SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const pLcioCluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const; + + /** + * @brief Set cluster energies and errors + * + * @param pPandoraPfo the address of the pandora pfo + * @param pPandoraCluster the address of the pandora cluster + * @param pLcioCluster the address of the lcio cluster to be set energies and erros + * @param clusterCorrectEnergy a number to receive the cluster correct energy + */ + void SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const pLcioCluster, float &clusterCorrectEnergy) const; + + /** + * @brief Set cluster position, errors and other shape info, by calculating culster shape first + * + * @param nHitsInCluster number of hits in cluster + * @param hitE the vector of the energy of hits + * @param hitX the vector of the x position of hits + * @param hitY the vector of the y position of hits + * @param hitZ the vector of the z position of hits + * @param pLcioCluster the lcio cluster to be set positions and errors + * @param clusterPosition a CartesianVector to receive the cluster position + */ + void SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const pLcioCluster, pandora::CartesianVector &clusterPositionVec) const; + + /** + * @brief Calculate reference point for pfo with tracks + * + * @param pPandoraPfo the address of the pandora pfo + * @param referencePoint a CartesianVector to receive the reference point + */ + pandora::StatusCode CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const; + + /** + * @brief Set reference point of the reconstructed particle + * + * @param referencePoint a CartesianVector of the reference point + * @param pReconstructedParticle the address of the reconstructed particle to be reference point + */ + void SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Add tracks to reconstructed particle + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be added tracks + */ + void AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Set properties of reconstructed particle from pandora pfo + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be set properties + */ + void SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Whether parent and daughter tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether sibling tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether the track is the closest (of those associated with the same pfo) to the interaction point + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether at least one track sibling track is associated to the reconstructed particle + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + const Settings m_settings; ///< The pfo creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object from which to extract the pfos +}; + +#endif // #ifndef PFO_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h new file mode 100644 index 00000000..1e1588c2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h @@ -0,0 +1,373 @@ +/** + * @file MarlinPandora/include/TrackCreator.h + * + * @brief Header file for the track creator class. + * + * $Log: $ + */ + +#ifndef TRACK_CREATOR_H +#define TRACK_CREATOR_H 1 + + + + +#include "GaudiKernel/ISvcLocator.h" + +#include "edm4hep/Track.h" +#include "edm4hep/TrackConst.h" +#include "edm4hep/TrackState.h" +#include "edm4hep/ReconstructedParticleConst.h" + +#include "Api/PandoraApi.h" +#include "Objects/Helix.h" + +namespace gear { class GearMgr; } + +class CollectionMaps; + +typedef std::vector<const edm4hep::Track *> TrackVector; +//typedef std::set<const edm4hep::Track *> TrackList; +typedef std::set<unsigned int> TrackList; +//typedef std::map<edm4hep::Track *, int> TrackToPidMap; +typedef std::map<edm4hep::ConstTrack, int> TrackToPidMap; +/* +inline LCCollectionVec *newTrkCol(const std::string &name, LCEvent *evt , bool isSubset) +{ + LCCollectionVec* col = new LCCollectionVec( LCIO::TRACK ) ; + + LCFlagImpl hitFlag(0) ; + hitFlag.setBit( LCIO::TRBIT_HITS ) ; + col->setFlag( hitFlag.getFlag() ) ; + evt->addCollection( col , name ) ; + col->setSubset( isSubset ) ; + + return col ; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief TrackCreator class + */ +class TrackCreator +{ +public: + typedef std::vector<double> DoubleVector; + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_trackCollections; ///< The reconstructed track collections + StringVector m_kinkVertexCollections; ///< The kink vertex collections + StringVector m_prongVertexCollections; ///< The prong vertex collections + StringVector m_splitVertexCollections; ///< The split vertex collections + StringVector m_v0VertexCollections; ///< The v0 vertex collections + + StringVector m_prongSplitVertexCollections; ///< Concatenated list of prong and split vertex collections + int m_shouldFormTrackRelationships; ///< Whether to form pandora track relationships using v0 and kink info + + int m_minTrackHits; ///< Track quality cut: the minimum number of track hits + int m_minFtdTrackHits; ///< Track quality cut: the minimum number of FTD track hits for FTD only tracks + int m_maxTrackHits; ///< Track quality cut: the maximum number of track hits + + float m_d0TrackCut; ///< Track d0 cut used to determine whether track can be used to form pfo + float m_z0TrackCut; ///< Track z0 cut used to determine whether track can be used to form pfo + + int m_usingNonVertexTracks; ///< Whether can form pfos from tracks that don't start at vertex + int m_usingUnmatchedNonVertexTracks; ///< Whether can form pfos from unmatched tracks that don't start at vertex + int m_usingUnmatchedVertexTracks; ///< Whether can form pfos from unmatched tracks that start at vertex + float m_unmatchedVertexTrackMaxEnergy; ///< Maximum energy for unmatched vertex track + + float m_d0UnmatchedVertexTrackCut; ///< d0 cut used to determine whether unmatched vertex track can form pfo + float m_z0UnmatchedVertexTrackCut; ///< z0 cut used to determine whether unmatched vertex track can form pfo + float m_zCutForNonVertexTracks; ///< Non vtx track z cut to determine whether track can be used to form pfo + + int m_reachesECalNTpcHits; ///< Minimum number of tpc hits to consider track as reaching ecal + int m_reachesECalNFtdHits; ///< Minimum number of ftd hits to consider track as reaching ecal + float m_reachesECalTpcOuterDistance; ///< Max distance from track to tpc r max to id whether track reaches ecal + int m_reachesECalMinFtdLayer; ///< Min layer in Ftd for tracks to be considered to have reached decal + float m_reachesECalTpcZMaxDistance; ///< Max distance from track to tpc z max to id whether track reaches ecal + float m_reachesECalFtdZMaxDistance; ///< Max distance from track hit to ftd z position to identify ftd hits + float m_curvatureToMomentumFactor; ///< Constant relating track curvature in b field to momentum + + float m_minTrackECalDistanceFromIp; ///< Sanity check on separation between ip and track projected ecal position + float m_maxTrackSigmaPOverP; ///< Track fraction momentum error cut + float m_minMomentumForTrackHitChecks; ///< Min track momentum required to perform final quality checks on number of hits + + float m_tpcMembraneMaxZ; ///< Tpc membrane max z coordinate + float m_maxTpcInnerRDistance; ///< Track cut on distance from tpc inner r to id whether track can form pfo + float m_minTpcHitFractionOfExpected; ///< Minimum fraction of TPC hits compared to expected + int m_minFtdHitsForTpcHitFraction; ///< Minimum number of FTD hits to ignore TPC hit fraction + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + //TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora); + TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc); + + /** + * @brief Destructor + */ + ~TrackCreator(); + + /** + * @brief Create associations between tracks, V0s, kinks, etc + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateTrackAssociations(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode CreateTrackAssociations(const CollectionMaps& collectionMaps); + + /** + * @brief Create tracks, insert user code here + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateTracks(EVENT::LCEvent *pLCEvent); + pandora::StatusCode CreateTracks(const CollectionMaps& collectionMaps); + + /** + * @brief Get the track vector + * + * @return The track vector + */ + const TrackVector &GetTrackVector() const; + + /** + * @brief Reset the track creator + */ + void Reset(); + +private: + /** + * @brief Extract kink information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractKinks(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode ExtractKinks(const CollectionMaps& collectionMaps); + + /** + * @brief Extract prong and split information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Extract v0 information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractV0s(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Whether the track vertex conflicts with previously provided relationship information + * + * @param trackVec the vector of tracks associated with the vertex + */ + //bool IsConflictingRelationship(const EVENT::TrackVec &trackVec) const; + //bool IsConflictingRelationship(edm4hep::ConstTrack &trackVec) const; + bool IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const; + + /** + * @brief Whether a track is a v0 track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsV0(const EVENT::Track *const pTrack) const; + bool IsV0(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a parent track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsParent(const EVENT::Track *const pTrack) const; + bool IsParent(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a daughter track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsDaughter(const EVENT::Track *const pTrack) const; + bool IsDaughter(unsigned int pTrack_id) const; + + /** + * @brief Copy track states stored in lcio tracks to pandora track parameters + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void GetTrackStates(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Copy track state from lcio track state instance to pandora input track state + * + * @param pTrackState the lcio track state instance + * @param inputTrackState the pandora input track state + */ + //void CopyTrackState(const TrackState *const pTrackState, pandora::InputTrackState &inputTrackState) const; + void CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const; + + /** + * @brief Obtain track time when it reaches ECAL + * + * @param pTrack the lcio track + */ + //float CalculateTrackTimeAtCalorimeter(const EVENT::Track *const pTrack) const; + float CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const; + + /** + * @brief Decide whether track reaches the ecal surface + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void TrackReachesECAL(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + //void TrackReachesECAL(const edm4hep::Track& pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Determine whether a track can be used to form a pfo under the following conditions: + * 1) if the track proves to be associated with a cluster, OR + * 2) if the track proves to have no cluster associations + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void DefineTrackPfoUsage(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Whether track passes the quality cuts required in order to be used to form a pfo + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + * + * @return boolean + */ + //bool PassesQualityCuts(const EVENT::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + bool PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Get number of hits in TPC of a track + * + * @param pTrack the lcio track + * + * @return number of hits in TPC of a track + */ + //int GetNTpcHits(const EVENT::Track *const pTrack) const; + int GetNTpcHits(const edm4hep::Track *const pTrack) const; + + /** + * @brief Get number of hits in FTD of a track + * + * @param pTrack the lcio track + * + * @return number of hits in FTDof a track + */ + //int GetNFtdHits(const EVENT::Track *const pTrack) const; + int GetNFtdHits(const edm4hep::Track *const pTrack) const; + + const Settings m_settings; ///< The track creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create tracks and track relationships + + float m_bField; ///< The bfield + + float m_tpcInnerR; ///< The tpc inner radius + float m_tpcOuterR; ///< The tpc outer radius + unsigned int m_tpcMaxRow; ///< The tpc maximum row number + float m_tpcZmax; ///< The tpc maximum z coordinate + float m_cosTpc; ///< Cos(theta) value at end of tpc + + DoubleVector m_ftdInnerRadii; ///< List of ftd inner radii + DoubleVector m_ftdOuterRadii; ///< List of ftd outer radii + DoubleVector m_ftdZPositions; ///< List of ftd z positions + unsigned int m_nFtdLayers; ///< Number of ftd layers + float m_tanLambdaFtd; ///< Tan lambda for first ftd layer + + int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi 0 + float m_eCalBarrelInnerR; ///< ECal barrel inner radius + float m_eCalEndCapInnerZ; ///< ECal endcap inner z + + float m_minEtdZPosition; ///< Min etd z position + float m_minSetRadius; ///< Min set radius + + TrackVector m_trackVector; ///< The track vector + TrackList m_v0TrackList; ///< The list of v0 tracks + TrackList m_parentTrackList; ///< The list of parent tracks + TrackList m_daughterTrackList; ///< The list of daughter tracks + TrackToPidMap m_trackToPidMap; ///< The map from track addresses to particle ids, where set by kinks/V0s + gear::GearMgr* _GEAR; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const TrackVector &TrackCreator::GetTrackVector() const +{ + return m_trackVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void TrackCreator::Reset() +{ + m_trackVector.clear(); + m_v0TrackList.clear(); + m_parentTrackList.clear(); + m_daughterTrackList.clear(); + m_trackToPidMap.clear(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsV0(const Track *const pTrack) const +inline bool TrackCreator::IsV0(unsigned int pTrack_id) const // should check here, if id is correct one to do this +{ + //return (m_v0TrackList.end() != m_v0TrackList.find(pTrack)); + return (m_v0TrackList.end() != m_v0TrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsParent(const Track *const pTrack) const +inline bool TrackCreator::IsParent(unsigned int pTrack_id) const +{ + //return (m_parentTrackList.end() != m_parentTrackList.find(pTrack)); + return (m_parentTrackList.end() != m_parentTrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsDaughter(const Track *const pTrack) const +inline bool TrackCreator::IsDaughter(unsigned int pTrack_id) const +{ + //return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack)); + return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack_id)); +} + +#endif // #ifndef TRACK_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h new file mode 100644 index 00000000..0bd75b5d --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h @@ -0,0 +1,6 @@ +#ifndef MYUTILITY +#define MYUTILITY 1 + +#include <sstream> +std::string Convert (float number); +#endif diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h new file mode 100644 index 00000000..f1515996 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h @@ -0,0 +1,127 @@ +#ifndef cellIDDecoder_h +#define cellIDDecoder_h 1 + +//#include <vector> +//#include "EVENT/LCObject.h" +#include "EVENT/LCCollection.h" +//#include "EVENT/SimTrackerHit.h" +#include "UTIL/BitField64.h" +#include "lcio.h" +#include <string> + +// fixes problem in gcc 4.0.3 +#include "EVENT/LCParameters.h" + +//#include <sstream> +//#include <typeinfo> + +//##################### changed for EMD4HEP ######## +//need check !! + +namespace ID_UTIL{ + + + /** Convenient class for decoding cellIDs from collection parameter LCIO::CellIDEncoding. + * See UTIL::BitField64 for a description of the encoding string. + * + * @see BitField64 + * @version $Id: CellIDDecoder.h,v 1.9.16.1 2011-03-04 14:09:07 engels Exp $ + */ + template <class T> + class CellIDDecoder { + + public: + + CellIDDecoder() = default ; + CellIDDecoder(const CellIDDecoder& ) = delete ; + CellIDDecoder& operator=(const CellIDDecoder& ) = delete ; + + + /** Constructor takes encoding string as argument. + */ + CellIDDecoder( const std::string& encoder_str ) : _oldHit(0) { + + if( encoder_str.length() == 0 ){ + throw( lcio::Exception( "CellIDDecoder : string of length zero provided as encoder string" ) ) ; + } + _b = new UTIL::BitField64( encoder_str ) ; + + } + + /** Constructor reads encoding string from collection parameter LCIO::CellIDEncoding. + */ + CellIDDecoder( const EVENT::LCCollection* col ) : _oldHit(0) { + + std::string initString("") ; + + if( col !=0 ) + initString = col->getParameters().getStringVal( lcio::LCIO::CellIDEncoding ) ; + + if( initString.size() == 0 ) { + + initString = _defaultEncoding ; + + std::cout << " ----------------------------------------- " << std::endl + << " WARNING: CellIDDecoder - no CellIDEncoding parameter in collection ! " + << std::endl + << " -> using default : \"" << initString << "\"" + << std::endl + << " ------------------------------------------ " + << std::endl ; + } + + _b = new UTIL::BitField64( initString ) ; + } + + ~CellIDDecoder(){ + + delete _b ; + } + + + /** Provides access to the bit fields, e.g. <br> + * int layer = myCellIDEncoding( hit )[ "layer" ] ; + * + */ + inline const UTIL::BitField64 & operator()( const T* hit ){ + + if( hit != _oldHit && hit ) { + auto id = hit->getCellID(); + unsigned int id0 = id&0xFFFFFFFF; + unsigned int id1 = id>>32; + //lcio::long64 val = lcio::long64( hit->getCellID0() & 0xffffffff ) | ( lcio::long64( hit->getCellID1() ) << 32 ) ; + lcio::long64 val = lcio::long64( id0 & 0xffffffff ) | ( lcio::long64( id1 ) << 32 ) ; + + _b->setValue( val ) ; + + _oldHit = hit ; + } + + return *_b ; + } + + + /** This can be used to set the default encoding that is used if no + * CellIDEncoding parameter is set in the collection, e.g. in older lcio files. + */ + static void setDefaultEncoding(const std::string& defaultEncoding ) { + + _defaultEncoding = std::string( defaultEncoding ) ; + } + + protected: + UTIL::BitField64* _b{} ; + const T* _oldHit{NULL} ; + + static std::string _defaultEncoding; + } ; + + template <class T> + std::string CellIDDecoder<T>::_defaultEncoding + = std::string("byte0:8,byte1:8,byte2:8,byte3:8,byte4:8,byte5:8,byte6:8,byte7:8") ; + + +} // namespace +#endif + + diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp new file mode 100644 index 00000000..3196cde2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp @@ -0,0 +1,959 @@ +/** + * @file MarlinPandora/src/CaloHitCreator.cc + * + * @brief Implementation of the calo hit creator class. + * + * $Log: $ + */ + + +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/GearDistanceProperties.h" +#include "gear/GearPointProperties.h" +#include "gear/GEAR.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include <DD4hep/Detector.h> +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include <DD4hep/Objects.h> + +#include "UTIL/CellIDDecoder.h" +#include "cellIDDecoder.h" +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" + +#include "PandoraMatrixAlg.h" +#include "CaloHitCreator.h" + +#include <algorithm> +#include <cmath> +#include <limits> + + +CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style) : + m_settings(settings), + m_pPandora(pPandora) +{ + m_encoder_str = ""; + m_encoder_str_MUON = ""; + m_encoder_str_LCal = ""; + m_encoder_str_LHCal = ""; + if(encoder_style==0) + { + m_encoder_str = "M:3,S-1:3,I:9,J:9,K-1:6";// LCIO style + m_encoder_str_MUON="S-1:4,M:3,K-1:6,I:16,GRZone:3,J:32:16"; + m_encoder_str_LCal="I:10,J:10,K:10,S-1:2"; + m_encoder_str_LHCal=m_encoder_str; + } + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + IGeoSvc* Svc = 0; + StatusCode sc1 = svcloc->service("GeoSvc", Svc, false); + if ( !sc1 ) + { + throw "Failed to find GeoSvc ..."; + } + m_dd4hep = Svc->lcdd(); + const dd4hep::DetElement &detElement = m_dd4hep->detector("CaloDetector"); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + if(!Data) throw "Failed to get LayeredCalorimeterData ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + /* + m_compact = "/junofs/users/wxfang/MyGit/lcg97/UsingK4FWCore/0514/CEPCSW/Detector/DetEcalMatrix/compact/det.xml"; + dd4hep::Detector& description = dd4hep::Detector::getInstance(); + description.fromCompact( m_compact ); + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(description); + */ + + m_eCalBarrelOuterZ = Data->extent[3]; + m_eCalBarrelInnerPhi0 = Data->inner_phi0; + m_eCalBarrelInnerSymmetry = Data->inner_symmetry; + m_hCalBarrelOuterZ = (_GEAR->getHcalBarrelParameters().getExtent()[3]); + m_muonBarrelOuterZ = (_GEAR->getYokeBarrelParameters().getExtent()[3]); + m_coilOuterR = (_GEAR->getGearParameters("CoilParameters").getDoubleVal("Coil_cryostat_outer_radius")); + m_hCalBarrelInnerPhi0 = (_GEAR->getHcalBarrelParameters().getPhi0()); + m_hCalBarrelInnerSymmetry = (_GEAR->getHcalBarrelParameters().getSymmetryOrder()); + m_muonBarrelInnerPhi0 = (_GEAR->getYokeBarrelParameters().getPhi0()); + m_muonBarrelInnerSymmetry = (_GEAR->getYokeBarrelParameters().getSymmetryOrder()); + m_hCalEndCapOuterR = (_GEAR->getHcalEndcapParameters().getExtent()[1]); + m_hCalEndCapOuterZ = (_GEAR->getHcalEndcapParameters().getExtent()[3]); + m_hCalBarrelOuterR = (_GEAR->getHcalBarrelParameters().getExtent()[1]); + m_hCalBarrelOuterPhi0 =((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_phi0") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_phi0") + : 0)); + m_hCalBarrelOuterSymmetry = ((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_order") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_order") + : 0)); + + + const gear::LayerLayout &hCalEndCapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + m_hCalEndCapLayerThickness = hCalEndCapLayerLayout.getThickness(hCalEndCapLayerLayout.getNLayers() - 1); + m_hCalBarrelLayerThickness = hCalBarrelLayerLayout.getThickness(hCalBarrelLayerLayout.getNLayers() - 1); + if ((m_hCalEndCapLayerThickness < std::numeric_limits<float>::epsilon()) || (m_hCalBarrelLayerThickness < std::numeric_limits<float>::epsilon())) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::~CaloHitCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateCaloHits(const CollectionMaps& collectionMaps) +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateECalCaloHits (collectionMaps)); + // not used for ECAL Matrix + /* + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateMuonCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLHCalCaloHits(collectionMaps)); + */ + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& collectionMaps) +{ + std::cout<<"start CreateECalCaloHits:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_eCalCaloHitCollections.begin(), iterEnd = m_settings.m_eCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getEcalEndcapParameters().getLayerLayout()); + const dd4hep::DetElement &detElement = m_dd4hep->detector("CaloDetector"); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>& barrelLayerLayout = Data->layers; + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateECalCaloHits pCaloHit Collection type mismatch"); + + float eCalToMip(m_settings.m_eCalToMip), eCalMipThreshold(m_settings.m_eCalMipThreshold), eCalToEMGeV(m_settings.m_eCalToEMGeV), + eCalToHadGeVBarrel(m_settings.m_eCalToHadGeVBarrel), eCalToHadGeVEndCap(m_settings.m_eCalToHadGeVEndCap); + + // Hybrid ECAL including pure ScECAL. + if (m_settings.m_useEcalScLayers) + { + std::string collectionName(*iter); + std::transform(collectionName.begin(), collectionName.end(), collectionName.begin(), ::tolower); + + if (collectionName.find("ecal", 0) == std::string::npos) + std::cout << "WARNING: mismatching hybrid Ecal collection name. " << collectionName << std::endl; + + if (collectionName.find("si", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalSiToMip; + eCalMipThreshold = m_settings.m_eCalSiMipThreshold; + eCalToEMGeV = m_settings.m_eCalSiToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalSiToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalSiToHadGeVEndCap; + } + else if (collectionName.find("sc", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalScToMip; + eCalMipThreshold = m_settings.m_eCalScMipThreshold; + eCalToEMGeV = m_settings.m_eCalScToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalScToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalScToHadGeVEndCap; + } + } + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false;//FIXME, maybe this means the MIP thershold cut haven't be applied yet ? + /* + dd4hep::Position position = m_cellIDConverter->position(pCaloHit->getCellID()); + long id_sys,id_x,id_y,id_z ; + GetCoding(pCaloHit, id_sys, id_x, id_y, id_z); + std::cout << "ECAL id =" << pCaloHit->getCellID()<<",sys="<<id_sys<<",x="<<id_x<<",y="<<id_y<<",z="<<id_z << std::endl; + std::cout << "ECAL id =" << pCaloHit->getCellID()<<",x="<<position.x()<<",y="<<position.y()<<",z="<<position.z() << std::endl; + */ + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_eCalBarrelOuterZ) + { + caloHitParameters.m_layer = GetBarrelLayer(pCaloHit, barrelLayerLayout); + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_eCalBarrelInnerSymmetry, m_eCalBarrelInnerPhi0, 6, caloHitParameters, absorberCorrection);//6 + caloHitParameters.m_hadronicEnergy = eCalToHadGeVBarrel * pCaloHit->getEnergy(); + + } + else + { // will not be used for ECAL Matrix + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1;//FIXME, should use + 1? because the decoded layer is start from 0. + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + caloHitParameters.m_hadronicEnergy = eCalToHadGeVEndCap * pCaloHit->getEnergy(); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = eCalToEMGeV * pCaloHit->getEnergy(); + + // ATTN If using strip splitting, must correct cell sizes for use in PFA to minimum of strip width and strip length + if (m_settings.m_stripSplittingOn) + { + const float splitCellSize(std::min(caloHitParameters.m_cellSize0.Get(), caloHitParameters.m_cellSize1.Get())); + caloHitParameters.m_cellSize0 = splitCellSize; + caloHitParameters.m_cellSize1 = splitCellSize; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract ecal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract ecal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout<< "Failed to extract ecal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_hCalCaloHitCollections.begin(), iterEnd = m_settings.m_hCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateHCalCaloHits Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_hCalBarrelOuterZ) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_hCalBarrelInnerSymmetry, m_hCalBarrelInnerPhi0, + m_hCalBarrelInnerSymmetry - int(cellIdDecoder(pCaloHit)[ staveCoding] / 2), caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Error, Failed to extract hcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract hcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract hcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateMuonCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_muonCaloHitCollections.begin(), iterEnd = m_settings.m_muonCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getYokeEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getYokeBarrelParameters().getLayerLayout()); + const gear::LayerLayout &plugLayerLayout(_GEAR->getYokePlugParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_MUON); + const std::string layerCodingString(m_encoder_str_MUON); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("Muon Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::MUON; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1;//FIXME, should use +1? it starts from 0. + caloHitParameters.m_isInOuterSamplingLayer = true; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + const float radius(std::sqrt(pCaloHit->getPosition()[0] * pCaloHit->getPosition()[0] + + pCaloHit->getPosition()[1] * pCaloHit->getPosition()[1])); + + const bool isWithinCoil(radius < m_coilOuterR); + const bool isInBarrelRegion(std::fabs(pCaloHit->getPosition()[2]) < m_muonBarrelOuterZ); + + float absorberCorrection(1.); + + if (isInBarrelRegion && isWithinCoil) + { + this->GetEndCapCaloHitProperties(pCaloHit, plugLayerLayout, caloHitParameters, absorberCorrection); + } + else if (isInBarrelRegion) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_muonBarrelInnerSymmetry, m_muonBarrelInnerPhi0, + cellIdDecoder(pCaloHit)[ staveCoding ], caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + if (m_settings.m_muonDigitalHits > 0) + { + caloHitParameters.m_isDigital = true; + caloHitParameters.m_inputEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_hadronicEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_electromagneticEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_mipEquivalentEnergy = 1.f; + } + else + { + caloHitParameters.m_isDigital = false; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_electromagneticEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_muonToMip; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract muon hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract muon hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract muon hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lCalCaloHitCollections.begin(), iterEnd = m_settings.m_lCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLcalParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LCal); + const std::string layerCodingString(m_encoder_str_LCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = m_settings.m_eCalToEMGeV * pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = m_settings.m_eCalToHadGeVEndCap * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lHCalCaloHitCollections.begin(), iterEnd = m_settings.m_lHCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLHcalParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LHCal); + const std::string layerCodingString(m_encoder_str_LHCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LHCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lhcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const +{ + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + const pandora::CartesianVector positionVector(pCaloHitPosition[0], pCaloHitPosition[1], pCaloHitPosition[2]); + + caloHitParameters.m_cellGeometry = pandora::RECTANGULAR; + caloHitParameters.m_positionVector = positionVector; + caloHitParameters.m_expectedDirection = positionVector.GetUnitVector(); + caloHitParameters.m_pParentAddress = pCaloHit; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_time = pCaloHit->getTime(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::ENDCAP; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING CaloHitCreator::GetEndCapCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + caloHitParameters.m_cellNormalVector = (pCaloHit->getPosition()[2] > 0) ? pandora::CartesianVector(0, 0, 1) : + pandora::CartesianVector(0, 0, -1); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::BARREL; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + //std::cout<<"m_layer="<<caloHitParameters.m_layer.Get()<<",layerLayout.getNLayers() - 1="<<layerLayout.getNLayers() - 1<<",layerAbsorberThickness="<<layerAbsorberThickness<<std::endl; + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"interactionLength="<<interactionLength<<",layerAbsorberThickness="<<layerAbsorberThickness<<",radiationLength="<<radiationLength<<",physicalLayer="<<physicalLayer<<",l1="<<caloHitParameters.m_layer.Get()<<",l2="<<layerLayout.getNLayers()-1<<std::endl; + std::cout<<"WARNIN CaloHitCreator::GetBarrelCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + if (barrelSymmetryOrder > 2) + { + const float phi = barrelPhi0 + (2. * M_PI * static_cast<float>(staveNumber) / static_cast<float>(barrelSymmetryOrder)); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(-std::sin(phi), std::cos(phi), 0); + } + else + { + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + + if (pCaloHitPosition[1] != 0) + { + const float phi = barrelPhi0 + std::atan(pCaloHitPosition[0] / pCaloHitPosition[1]); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(std::sin(phi), std::cos(phi), 0); + } + else + { + caloHitParameters.m_cellNormalVector = (pCaloHitPosition[0] > 0) ? pandora::CartesianVector(1, 0, 0) : + pandora::CartesianVector(-1, 0, 0); + } + } +} + +void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::BARREL; + + const int physicalLayer = std::max(0, int(caloHitParameters.m_layer.Get()-1) ); + caloHitParameters.m_cellSize0 = layerLayout.at(physicalLayer).cellSize0; + caloHitParameters.m_cellSize1 = layerLayout.at(physicalLayer).cellSize1; + caloHitParameters.m_cellThickness = layerLayout.at(physicalLayer).sensitive_thickness; + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.at(physicalLayer).absorberThickness); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"interactionLength="<<interactionLength<<",layerAbsorberThickness="<<layerAbsorberThickness<<",radiationLength="<<radiationLength<<",physicalLayer="<<physicalLayer<<",l1="<<caloHitParameters.m_layer.Get()<<",l2="<<layerLayout.size()-1<<std::endl; + std::cout<<"WARNIN CaloHitCreator::GetBarrelCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.size(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.at(i).absorberThickness); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + if (barrelSymmetryOrder > 2) + { + float phi = barrelPhi0 + (2. * M_PI * float(staveNumber) / float(barrelSymmetryOrder)); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(-std::sin(phi), std::cos(phi), 0); + //std::cout<<"barrelPhi0="<<barrelPhi0<<",phi="<<phi<<",GetX()="<<caloHitParameters.m_cellNormalVector.Get().GetX()<<",GetY()="<<caloHitParameters.m_cellNormalVector.Get().GetY()<<",GetZ()="<<caloHitParameters.m_cellNormalVector.Get().GetZ()<<std::endl; + } + else + { + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + + if (pCaloHitPosition[1] != 0) + { + const float phi = barrelPhi0 + std::atan(pCaloHitPosition[0] / pCaloHitPosition[1]); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(std::sin(phi), std::cos(phi), 0); + } + else + { + caloHitParameters.m_cellNormalVector = (pCaloHitPosition[0] > 0) ? pandora::CartesianVector(1, 0, 0) : + pandora::CartesianVector(-1, 0, 0); + } + } +} +//------------------------------------------------------------------------------------------------------------------------------------------ +int CaloHitCreator::GetBarrelLayer(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout) const +{ + int layer = -1 ; + for (unsigned int i = 0, iMax = layerLayout.size(); i < iMax; ++i) + { + const float distance(layerLayout.at(i).distance); + const float sensitive_thickness(layerLayout.at(i).sensitive_thickness); + if( (distance - 0.5*sensitive_thickness) <= pCaloHit->getPosition().x && pCaloHit->getPosition().x <= (distance + 0.5*sensitive_thickness)) {layer = i+1 ; break;} + } + if(layer==-1) + { + int lmax = layerLayout.size()-1; + std::cout<<"Error BarrelLayer, set to default 1, Hit.x="<<pCaloHit->getPosition().x<<", min_x="<<layerLayout.at(0).distance-0.5*layerLayout.at(0).sensitive_thickness<<", max_x="<<layerLayout.at(lmax).distance+0.5*layerLayout.at(lmax).sensitive_thickness<<std::endl; + layer = 1; + } + return layer; +} + +int CaloHitCreator::GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const +{ + // Calo hit coordinate calculations + const float barrelMaximumRadius(this->GetMaximumRadius(pCaloHit, m_hCalBarrelOuterSymmetry, m_hCalBarrelOuterPhi0)); + const float endCapMaximumRadius(this->GetMaximumRadius(pCaloHit, m_settings.m_hCalEndCapInnerSymmetryOrder, m_settings.m_hCalEndCapInnerPhiCoordinate)); + const float caloHitAbsZ(std::fabs(pCaloHit->getPosition()[2])); + + // Distance from radial outer + float radialDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ < m_eCalBarrelOuterZ) + { + radialDistanceToEdge = (m_hCalBarrelOuterR - barrelMaximumRadius) / m_hCalBarrelLayerThickness; + } + else + { + radialDistanceToEdge = (m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness; + } + + // Distance from rear of endcap outer + float rearDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ >= m_eCalBarrelOuterZ) + { + rearDistanceToEdge = (m_hCalEndCapOuterZ - caloHitAbsZ) / m_hCalEndCapLayerThickness; + } + else + { + const float rearDistance((m_eCalBarrelOuterZ - caloHitAbsZ) / m_hCalBarrelLayerThickness); + + if (rearDistance < m_settings.m_layersFromEdgeMaxRearDistance) + { + const float overlapDistance((m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness); + rearDistanceToEdge = std::max(rearDistance, overlapDistance); + } + } + + return static_cast<int>(std::min(radialDistanceToEdge, rearDistanceToEdge)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float CaloHitCreator::GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const +{ + + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + if (symmetryOrder <= 2) + return std::sqrt((pCaloHitPosition[0] * pCaloHitPosition[0]) + (pCaloHitPosition[1] * pCaloHitPosition[1])); + + float maximumRadius(0.f); + const float twoPi(2.f * M_PI); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + i * twoPi / static_cast<float>(symmetryOrder); + float radius = pCaloHitPosition[0] * std::cos(phi) + pCaloHitPosition[1] * std::sin(phi); + + if (radius > maximumRadius) + maximumRadius = radius; + } + + return maximumRadius; +} + +void CaloHitCreator::GetCoding(const edm4hep::CalorimeterHit* pCaloHit, long& sys, long& x, long& y, long& z) const +{ + //sys = (pCaloHit->getCellID() << (64-8)) >> (64-8) ; + //x = (pCaloHit->getCellID() << (64-(8+16))) >> (64-(8+16)) ; + //y = (pCaloHit->getCellID() << (64-(8+16+16))) >> (64-(8+16+16)) ; + //z = (pCaloHit->getCellID() << (64-(8+16+16+16))) >> (64-(8+16+16+16)) ; + unsigned long long id = pCaloHit->getCellID(); + sys = id & 0xFF ; + x = (id >> 8) & 0xFFFF ; + y = (id >> (8+16)) & 0xFFFF ; + z = (id >> (8+16+16)) & 0xFFFF ; +} +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetLayerCoding(const std::string &encodingString) const +{ + if (encodingString.find("layer") != std::string::npos) + return std::string("layer"); + + if (encodingString.find("K-1") != std::string::npos) + return std::string("K-1"); + + if (encodingString.find("K") != std::string::npos) + return std::string("K"); + + return std::string("unknown_layer_encoding"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetStaveCoding(const std::string &encodingString) const +{ + if (encodingString.find("stave") != std::string::npos) + return std::string("stave"); + + if (encodingString.find("S-1") != std::string::npos) + return std::string("S-1"); + + return std::string("unknown_stave_encoding") ; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalToMip(1.f), + m_hCalToMip(1.f), + m_muonToMip(1.f), + m_eCalMipThreshold(0.f), + m_hCalMipThreshold(0.f), + m_muonMipThreshold(0.f), + m_eCalToEMGeV(1.f), + m_eCalToHadGeVBarrel(1.f), + m_eCalToHadGeVEndCap(1.f), + m_hCalToEMGeV(1.f), + m_hCalToHadGeV(1.f), + m_muonDigitalHits(1), + m_muonHitEnergy(0.5f), + m_maxHCalHitHadronicEnergy(10000.f), + m_nOuterSamplingLayers(3), + m_layersFromEdgeMaxRearDistance(250.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_stripSplittingOn(0), + m_useEcalScLayers(0), + m_eCalSiToMip(1.f), + m_eCalScToMip(1.f), + m_eCalSiMipThreshold(0.f), + m_eCalScMipThreshold(0.f), + m_eCalSiToEMGeV(1.f), + m_eCalScToEMGeV(1.f), + m_eCalSiToHadGeVBarrel(1.f), + m_eCalScToHadGeVBarrel(1.f), + m_eCalSiToHadGeVEndCap(1.f), + m_eCalScToHadGeVEndCap(1.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp new file mode 100644 index 00000000..3ab6cc80 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp @@ -0,0 +1,488 @@ +/** + * @file MarlinPandora/src/GeometryCreator.cc + * + * @brief Implementation of the geometry creator class. + * + * $Log: $ + */ +#include "GaudiKernel/IService.h" + +#include "GearSvc/IGearSvc.h" +#include "gear/BField.h" +#include "gear/GEAR.h" +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include "GeometryCreator.h" + +#include <DD4hep/Detector.h> +#include <DDRec/DetectorData.h> + +GeometryCreator::GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::~GeometryCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//pandora::StatusCode GeometryCreator::CreateGeometry() const +//pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) const +pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) +{ + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + IGeoSvc* Svc = 0; + StatusCode sc1 = svcloc->service("GeoSvc", Svc, false); + if ( !sc1 ) + { + throw "Failed to find GeoSvc ..."; + } + m_dd4hep = Svc->lcdd(); + + + //auto _gear = service<IGearSvc>("GearSvc"); + //if ( !_gear ) + //{ + // throw "Failed to find GearSvc ..."; + //} + //_GEAR = _gear->getGearMgr(); + + + try + { + SubDetectorTypeMap subDetectorTypeMap; + this->SetMandatorySubDetectorParameters(subDetectorTypeMap); + + SubDetectorNameMap subDetectorNameMap; + this->SetAdditionalSubDetectorParameters(subDetectorNameMap); + + if (std::string::npos != _GEAR->getDetectorName().find("ILD")) + this->SetILDSpecificGeometry(subDetectorTypeMap, subDetectorNameMap); + + for (SubDetectorTypeMap::const_iterator iter = subDetectorTypeMap.begin(), iterEnd = subDetectorTypeMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + + for (SubDetectorNameMap::const_iterator iter = subDetectorNameMap.begin(), iterEnd = subDetectorNameMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + } + catch (gear::Exception &exception) + { + std::cout << "Failure in marlin pandora geometry creator, gear exception: " << exception.what() << std::endl; + throw exception; + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const +{ + std::cout << "Begin SetMandatorySubDetectorParameters:" << std::endl; + PandoraApi::Geometry::SubDetector::Parameters eCalBarrelParameters, eCalEndCapParameters, hCalBarrelParameters, hCalEndCapParameters, + muonBarrelParameters, muonEndCapParameters; + + this->SetDefaultSubDetectorParameters(m_dd4hep, "CaloDetector", pandora::ECAL_BARREL, eCalBarrelParameters); + //this->SetDefaultSubDetectorParameters(_GEAR->getEcalBarrelParameters(), "ECalBarrel", pandora::ECAL_BARREL, eCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getEcalEndcapParameters(), "ECalEndCap", pandora::ECAL_ENDCAP, eCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalBarrelParameters(), "HCalBarrel", pandora::HCAL_BARREL, hCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalEndcapParameters(), "HCalEndCap", pandora::HCAL_ENDCAP, hCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeBarrelParameters(), "MuonBarrel", pandora::MUON_BARREL, muonBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeEndcapParameters(), "MuonEndCap", pandora::MUON_ENDCAP, muonEndCapParameters); + + subDetectorTypeMap[pandora::ECAL_BARREL] = eCalBarrelParameters; + subDetectorTypeMap[pandora::ECAL_ENDCAP] = eCalEndCapParameters; + subDetectorTypeMap[pandora::HCAL_BARREL] = hCalBarrelParameters; + subDetectorTypeMap[pandora::HCAL_ENDCAP] = hCalEndCapParameters; + subDetectorTypeMap[pandora::MUON_BARREL] = muonBarrelParameters; + subDetectorTypeMap[pandora::MUON_ENDCAP] = muonEndCapParameters; + + PandoraApi::Geometry::SubDetector::Parameters trackerParameters; + const gear::TPCParameters &tpcParameters(_GEAR->getTPCParameters()); + trackerParameters.m_subDetectorName = "Tracker"; + trackerParameters.m_subDetectorType = pandora::INNER_TRACKER; + trackerParameters.m_innerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[0]; + trackerParameters.m_innerZCoordinate = 0.f; + trackerParameters.m_innerPhiCoordinate = 0.f; + trackerParameters.m_innerSymmetryOrder = 0; + trackerParameters.m_outerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[1]; + trackerParameters.m_outerZCoordinate = tpcParameters.getMaxDriftLength(); + trackerParameters.m_outerPhiCoordinate = 0.f; + trackerParameters.m_outerSymmetryOrder = 0; + trackerParameters.m_isMirroredInZ = true; + trackerParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::INNER_TRACKER] = trackerParameters; + + PandoraApi::Geometry::SubDetector::Parameters coilParameters; + const gear::GearParameters &gearParameters(_GEAR->getGearParameters("CoilParameters")); + coilParameters.m_subDetectorName = "Coil"; + coilParameters.m_subDetectorType = pandora::COIL; + coilParameters.m_innerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_inner_radius"); + coilParameters.m_innerZCoordinate = 0.f; + coilParameters.m_innerPhiCoordinate = 0.f; + coilParameters.m_innerSymmetryOrder = 0; + coilParameters.m_outerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_outer_radius"); + coilParameters.m_outerZCoordinate = gearParameters.getDoubleVal("Coil_cryostat_half_z"); + coilParameters.m_outerPhiCoordinate = 0.f; + coilParameters.m_outerSymmetryOrder = 0; + coilParameters.m_isMirroredInZ = true; + coilParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::COIL] = coilParameters; + std::cout << "End SetMandatorySubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const +{ + std::cout << "Begin SetAdditionalSubDetectorParameters:" << std::endl; + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getEcalPlugParameters(), "ECalPlug", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << " warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getHcalRingParameters(), "HCalRing", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout<< "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLcalParameters(), "LCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLHcalParameters(), "LHCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + std::cout << "End SetAdditionalSubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const +{ + const gear::LayerLayout &layerLayout = inputParameters.getLayerLayout(); + + parameters.m_subDetectorName = subDetectorName; + parameters.m_subDetectorType = subDetectorType; + parameters.m_innerRCoordinate = inputParameters.getExtent()[0]; + parameters.m_innerZCoordinate = inputParameters.getExtent()[2]; + parameters.m_innerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_innerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_outerRCoordinate = inputParameters.getExtent()[1]; + parameters.m_outerZCoordinate = inputParameters.getExtent()[3]; + parameters.m_outerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_outerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_isMirroredInZ = true; + parameters.m_nLayers = layerLayout.getNLayers(); + std::cout << "inputParameters.getExtent()[0]="<<inputParameters.getExtent()[0]<<",inputParameters.getExtent()[1]="<<inputParameters.getExtent()[1]<<",inputParameters.getExtent()[2]="<<inputParameters.getExtent()[2]<<",inputParameters.getExtent()[3]="<<inputParameters.getExtent()[3]<< std::endl; + + // ATTN Not always going to be correct for any optional subdetectors, but impact of this is negligible for ILD + const float radiationLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + for (int i = 0; i < layerLayout.getNLayers(); ++i) + { + PandoraApi::Geometry::LayerParameters layerParameters; + layerParameters.m_closestDistanceToIp = layerLayout.getDistance(i) + (0.5 * (layerLayout.getThickness(i) + layerLayout.getAbsorberThickness(i))); + layerParameters.m_nRadiationLengths = radiationLength * layerLayout.getAbsorberThickness(i); + layerParameters.m_nInteractionLengths = interactionLength * layerLayout.getAbsorberThickness(i); + parameters.m_layerParametersVector.push_back(layerParameters); + } +} + +void GeometryCreator::SetDefaultSubDetectorParameters(const dd4hep::Detector* theDetector , const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const +{ + //const std::vector< dd4hep::DetElement > &detElements = theDetector.detectors("EcalMatrix", true); + const dd4hep::DetElement &detElement = theDetector->detector(subDetectorName); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + + + parameters.m_subDetectorName = subDetectorName; + parameters.m_subDetectorType = subDetectorType; + parameters.m_innerRCoordinate = Data->extent[0]; + parameters.m_innerZCoordinate = Data->extent[2]; + parameters.m_innerPhiCoordinate = Data->inner_phi0; + parameters.m_innerSymmetryOrder = Data->inner_symmetry; + parameters.m_outerRCoordinate = Data->extent[1]; + parameters.m_outerZCoordinate = Data->extent[3]; + parameters.m_outerPhiCoordinate = Data->outer_phi0; + parameters.m_outerSymmetryOrder = Data->outer_symmetry; + parameters.m_nLayers = Data->layers.size(); + parameters.m_isMirroredInZ = true; + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>& layers= Data->layers; + std::cout << "Extent()[0]="<<Data->extent[0]<<",Extent()[1]="<<Data->extent[1]<<",Extent()[2]="<<Data->extent[2]<<",Extent()[3]="<<Data->extent[3]<< std::endl; + + // ATTN Not always going to be correct for any optional subdetectors, but impact of this is negligible for ILD + const float radiationLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + //for (int i = 0; i < layerLayout.getNLayers(); ++i) + for (auto const& layer : layers) + { + PandoraApi::Geometry::LayerParameters layerParameters; + //layerParameters.m_closestDistanceToIp = layer.distance + 0.5 * layer.sensitive_thickness;//Thickness of the sensitive element (e.g. scintillator) + layerParameters.m_closestDistanceToIp = layer.distance ; + layerParameters.m_nRadiationLengths = radiationLength * layer.absorberThickness; + layerParameters.m_nInteractionLengths = interactionLength * layer.absorberThickness; + std::cout<<"m_closestDistanceToIp="<<layerParameters.m_closestDistanceToIp.Get()<<",m_nRadiationLengths="<<layerParameters.m_nRadiationLengths.Get()<<",m_nInteractionLengths="<<layerParameters.m_nInteractionLengths.Get()<<std::endl; + parameters.m_layerParametersVector.push_back(layerParameters); + } +} +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const +{ + // Set positions of gaps in ILD detector and add information missing from GEAR parameters file + try + { + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + } + catch (gear::Exception &) + { + // aLaVideauGeometry + return this->SetILD_SDHCALSpecificGeometry(subDetectorTypeMap); + } + + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + subDetectorNameMap["HCalRing"].m_innerSymmetryOrder = m_settings.m_hCalRingInnerSymmetryOrder; + subDetectorNameMap["HCalRing"].m_innerPhiCoordinate = m_settings.m_hCalRingInnerPhiCoordinate; + subDetectorNameMap["HCalRing"].m_outerSymmetryOrder = m_settings.m_hCalRingOuterSymmetryOrder; + subDetectorNameMap["HCalRing"].m_outerPhiCoordinate = m_settings.m_hCalRingOuterPhiCoordinate; + + // Gaps in detector active material + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalEndCapBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelConcentricGaps()); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const +{ + // Non-default values (and those missing from GEAR parameters file)... + // The following 2 parameters have no sense for Videau Geometry, set them to 0 + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = 0; + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = 0; + + // Endcap is identical to standard ILD geometry, only HCAL barrel is different + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + // TODO implement gaps between modules + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelBoxGaps() const +{ + const std::string detectorName(_GEAR->getDetectorName()); + + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const unsigned int innerSymmetryOrder(hCalBarrelParameters.getSymmetryOrder()); + const unsigned int outerSymmetryOrder(hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order")); + + if ((0 == innerSymmetryOrder) || (2 != outerSymmetryOrder / innerSymmetryOrder)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float innerRadius(hCalBarrelParameters.getExtent()[0]); + const float outerRadius(hCalBarrelParameters.getExtent()[1]); + const float outerZ(hCalBarrelParameters.getExtent()[3]); + const float phi0(hCalBarrelParameters.getPhi0()); + + const float staveGap(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, phi0, innerRadius, outerRadius, + -outerZ, outerZ, staveGap)); + + const float outerPseudoPhi0(M_PI / static_cast<float>(innerSymmetryOrder)); + const float cosOuterPseudoPhi0(std::cos(outerPseudoPhi0)); + + if ((0 == outerPseudoPhi0) || (0.f == cosOuterPseudoPhi0)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float middleStaveGap(hCalBarrelParameters.getDoubleVal("Hcal_middle_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, outerPseudoPhi0, + innerRadius / cosOuterPseudoPhi0, outerRadius, -outerZ, outerZ, middleStaveGap)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalEndCapBoxGaps() const +{ + const gear::CalorimeterParameters &hCalEndCapParameters = _GEAR->getHcalEndcapParameters(); + + const float staveGap(hCalEndCapParameters.getDoubleVal("Hcal_stave_gaps")); + const float innerRadius(hCalEndCapParameters.getExtent()[0]); + const float outerRadius(hCalEndCapParameters.getExtent()[1]); + const float innerZ(hCalEndCapParameters.getExtent()[2]); + const float outerZ(hCalEndCapParameters.getExtent()[3]); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, innerZ, outerZ, staveGap, + pandora::CartesianVector(-innerRadius, 0, 0))); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, -outerZ, -innerZ, staveGap, + pandora::CartesianVector(innerRadius, 0, 0))); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelConcentricGaps() const +{ + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const float gapWidth(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + + PandoraApi::Geometry::ConcentricGap::Parameters gapParameters; + + gapParameters.m_minZCoordinate = -0.5f * gapWidth; + gapParameters.m_maxZCoordinate = 0.5f * gapWidth; + gapParameters.m_innerRCoordinate = hCalBarrelParameters.getExtent()[0]; + gapParameters.m_innerPhiCoordinate = hCalBarrelParameters.getPhi0(); + gapParameters.m_innerSymmetryOrder = hCalBarrelParameters.getSymmetryOrder(); + gapParameters.m_outerRCoordinate = hCalBarrelParameters.getExtent()[1]; + gapParameters.m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + gapParameters.m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::ConcentricGap::Create(*m_pPandora, gapParameters)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, + float minZ, float maxZ, float gapWidth, pandora::CartesianVector vertexOffset) const +{ + const pandora::CartesianVector basicGapVertex(pandora::CartesianVector(-0.5f * gapWidth, innerRadius, minZ) + vertexOffset); + const pandora::CartesianVector basicSide1(gapWidth, 0, 0); + const pandora::CartesianVector basicSide2(0, outerRadius - innerRadius, 0); + const pandora::CartesianVector basicSide3(0, 0, maxZ - minZ); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + (2. * M_PI * static_cast<float>(i) / static_cast<float>(symmetryOrder)); + const float sinPhi(std::sin(phi)); + const float cosPhi(std::cos(phi)); + + PandoraApi::Geometry::BoxGap::Parameters gapParameters; + + gapParameters.m_vertex = pandora::CartesianVector(cosPhi * basicGapVertex.GetX() + sinPhi * basicGapVertex.GetY(), + -sinPhi * basicGapVertex.GetX() + cosPhi * basicGapVertex.GetY(), basicGapVertex.GetZ()); + gapParameters.m_side1 = pandora::CartesianVector(cosPhi * basicSide1.GetX() + sinPhi * basicSide1.GetY(), + -sinPhi * basicSide1.GetX() + cosPhi * basicSide1.GetY(), basicSide1.GetZ()); + gapParameters.m_side2 = pandora::CartesianVector(cosPhi * basicSide2.GetX() + sinPhi * basicSide2.GetY(), + -sinPhi * basicSide2.GetX() + cosPhi * basicSide2.GetY(), basicSide2.GetZ()); + gapParameters.m_side3 = pandora::CartesianVector(cosPhi * basicSide3.GetX() + sinPhi * basicSide3.GetY(), + -sinPhi * basicSide3.GetX() + cosPhi * basicSide3.GetY(), basicSide3.GetZ()); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::BoxGap::Create(*m_pPandora, gapParameters)); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalEndCapInnerSymmetryOrder(4), + m_eCalEndCapInnerPhiCoordinate(0.f), + m_eCalEndCapOuterSymmetryOrder(8), + m_eCalEndCapOuterPhiCoordinate(0.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_hCalEndCapOuterSymmetryOrder(16), + m_hCalEndCapOuterPhiCoordinate(0.f), + m_hCalRingInnerSymmetryOrder(8), + m_hCalRingInnerPhiCoordinate(0.f), + m_hCalRingOuterSymmetryOrder(16), + m_hCalRingOuterPhiCoordinate(0.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp new file mode 100644 index 00000000..21a2a741 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp @@ -0,0 +1,372 @@ +/** + * @file MarlinPandora/src/MCParticleCreator.cc + * + * @brief Implementation of the mc particle creator class. + * + * $Log: $ + */ + + +#include "edm4hep/MCParticleConst.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/SimCalorimeterHitConst.h" +#include "edm4hep/CaloHitContributionConst.h" +#include "edm4hep/Track.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/SimTrackerHitConst.h" + + + + +#include "PandoraMatrixAlg.h" +#include "MCParticleCreator.h" + +#include <cmath> +#include <limits> +#include <assert.h> + +MCParticleCreator::MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora), + m_bField(settings.m_bField) +{ +m_id_pMC_map = new std::map<unsigned int, const edm4hep::MCParticle*>; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::~MCParticleCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode MCParticleCreator::CreateMCParticles(const CollectionMaps& collectionMaps ) const +{ + for (StringVector::const_iterator iter = m_settings.m_mcParticleCollections.begin(), iterEnd = m_settings.m_mcParticleCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_MC.find(*iter) == collectionMaps.collectionMap_MC.end()) continue; + try + { + const std::vector<edm4hep::MCParticle>& pMCParticleCollection = (collectionMaps.collectionMap_MC.find(*iter))->second; + std::cout<<"Do CreateMCParticles, collection:"<<(*iter)<<", size="<<pMCParticleCollection.size()<<std::endl; + for (int im = 0; im < pMCParticleCollection.size(); im++) + { + try + { + const edm4hep::MCParticle& pMcParticle = pMCParticleCollection.at(im); + PandoraApi::MCParticle::Parameters mcParticleParameters; + mcParticleParameters.m_energy = sqrt(pMcParticle.getMomentum()[0] * pMcParticle.getMomentum()[0] + pMcParticle.getMomentum()[1] * pMcParticle.getMomentum()[1] + pMcParticle.getMomentum()[2] * pMcParticle.getMomentum()[2] + pMcParticle.getMass() * pMcParticle.getMass()); + mcParticleParameters.m_particleId = pMcParticle.getPDG(); + mcParticleParameters.m_mcParticleType = pandora::MC_3D; + mcParticleParameters.m_pParentAddress = &pMcParticle; + unsigned int p_id = pMcParticle.id(); + const edm4hep::MCParticle* p_mc = &pMcParticle; + (*m_id_pMC_map) [p_id] = p_mc; + mcParticleParameters.m_momentum = pandora::CartesianVector(pMcParticle.getMomentum()[0], pMcParticle.getMomentum()[1], + pMcParticle.getMomentum()[2]); + mcParticleParameters.m_vertex = pandora::CartesianVector(pMcParticle.getVertex()[0], pMcParticle.getVertex()[1], + pMcParticle.getVertex()[2]); + mcParticleParameters.m_endpoint = pandora::CartesianVector(pMcParticle.getEndpoint()[0], pMcParticle.getEndpoint()[1], + pMcParticle.getEndpoint()[2]); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*m_pPandora, mcParticleParameters)); + + // Create parent-daughter relationships + for(std::vector<edm4hep::ConstMCParticle>::const_iterator itDaughter = pMcParticle.daughters_begin(), + itDaughterEnd = pMcParticle.daughters_end(); itDaughter != itDaughterEnd; ++itDaughter) + { + for (int ida = 0; ida < pMCParticleCollection.size(); ida++) + { + if(pMCParticleCollection.at(ida).id()==(*itDaughter).id()) + { + + const edm4hep::MCParticle& dMcParticle = pMCParticleCollection.at(ida); + if(&pMcParticle == &dMcParticle){std::cout<< "error, mother and daughter are the same mc particle, don't save SetMCParentDaughterRelationship"<<std::endl;} + else PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*m_pPandora, &pMcParticle, &dMcParticle)); + break; + } + } + } + + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract MCParticle: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract MCParticle: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract MCParticles collection: " << *iter << ", " << std::endl; + } + } + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const TrackVector &trackVector) const +{ + for (StringVector::const_iterator iter = m_settings.m_lcTrackRelationCollections.begin(), iterEnd = m_settings.m_lcTrackRelationCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pMCRelationCollection = pLCEvent->getCollection(*iter); + UTIL::LCRelationNavigator navigate(pMCRelationCollection); + + for (TrackVector::const_iterator trackIter = trackVector.begin(), trackIterEnd = trackVector.end(); + trackIter != trackIterEnd; ++trackIter) + { + try + { + EVENT::Track *pTrack = *trackIter; + const EVENT::LCObjectVec &objectVec = navigate.getRelatedToObjects(*trackIter); + + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getPhi(), pTrack->getD0(), pTrack->getZ0(), pTrack->getOmega(), pTrack->getTanLambda(), m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + + // Use momentum magnitude to identify best mc particle + MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + + for (EVENT::LCObjectVec::const_iterator itRel = objectVec.begin(), itRelEnd = objectVec.end(); itRel != itRelEnd; ++itRel) + { + EVENT::MCParticle *pMCParticle = NULL; + pMCParticle = dynamic_cast<MCParticle *>(*itRel); + + if (NULL == pMCParticle) + continue; + + const float trueMomentum(pandora::CartesianVector(pMCParticle->getMomentum()[0], pMCParticle->getMomentum()[1], + pMCParticle->getMomentum()[2]).GetMagnitude()); + + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle = pMCParticle; + bestDeltaMomentum = deltaMomentum; + } + } + + if (NULL == pBestMCParticle) + continue; + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, + pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + streamlog_out(ERROR) << "Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract track to mc particle relationship: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract track to mc particle relationships collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const CalorimeterHitVector &calorimeterHitVector) const +{ + typedef std::map<MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_lcCaloHitRelationCollections.begin(), iterEnd = m_settings.m_lcCaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pMCRelationCollection = pLCEvent->getCollection(*iter); + UTIL::LCRelationNavigator navigate(pMCRelationCollection); + + for (CalorimeterHitVector::const_iterator caloHitIter = calorimeterHitVector.begin(), + caloHitIterEnd = calorimeterHitVector.end(); caloHitIter != caloHitIterEnd; ++caloHitIter) + { + try + { + mcParticleToEnergyWeightMap.clear(); + const EVENT::LCObjectVec &objectVec = navigate.getRelatedToObjects(*caloHitIter); + + for (EVENT::LCObjectVec::const_iterator itRel = objectVec.begin(), itRelEnd = objectVec.end(); itRel != itRelEnd; ++itRel) + { + EVENT::SimCalorimeterHit *pSimHit = dynamic_cast<SimCalorimeterHit *>(*itRel); + + if (NULL == pSimHit) + continue; + + for (int iCont = 0, iEnd = pSimHit->getNMCContributions(); iCont < iEnd; ++iCont) + { + mcParticleToEnergyWeightMap[pSimHit->getParticleCont(iCont)] += pSimHit->getEnergyCont(iCont); + } + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + *caloHitIter, mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + streamlog_out(ERROR) << "Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract calo hit to mc particle relationship: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract calo hit to mc particle relationships collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ + +//-------------- using sim calo hit and digi calo hit, no weight here--------------------------------------------------------------------------------------------------------------- +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const +{ + std::cout<<"Do CreateCaloHitToMCParticleRelationships"<<std::endl; + typedef std::map<const edm4hep::MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_CaloHitRelationCollections.begin(), iterEnd = m_settings.m_CaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloRel.find(*iter) == collectionMaps.collectionMap_CaloRel.end()) continue; + try + { + const std::vector<edm4hep::MCRecoCaloAssociation>& pMCRecoCaloAssociationCollection = (collectionMaps.collectionMap_CaloRel.find(*iter))->second; + + for (unsigned i_calo=0; i_calo < calorimeterHitVector.size(); i_calo++) + { + try + { + mcParticleToEnergyWeightMap.clear(); + for(unsigned ic=0; ic < pMCRecoCaloAssociationCollection.size(); ic++) + { + if( pMCRecoCaloAssociationCollection.at(ic).getRec().id() != (*(calorimeterHitVector.at(i_calo))).id() ) continue; + + const edm4hep::ConstSimCalorimeterHit pSimHit = pMCRecoCaloAssociationCollection.at(ic).getSim(); + for (int iCont = 0, iEnd = pSimHit.contributions_size(); iCont < iEnd; ++iCont) + { + edm4hep::ConstCaloHitContribution conb = pSimHit.getContributions(iCont); + const edm4hep::ConstMCParticle ipa = conb.getParticle(); + float ien = conb.getEnergy(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const edm4hep::MCParticle * p_tmp = (*m_id_pMC_map)[ipa.id()]; + mcParticleToEnergyWeightMap[p_tmp] += ien; + } + + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + calorimeterHitVector.at(i_calo), mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract calo hit to mc particle relationship " << std::endl; + } + } + } + catch (...) + { + std::cout<<"DEBUG5 Failed to extract calo hit to mc particle relationships collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + + +//-------------- using sim tracker hit and tracker hit, no weight here--------------------------------------------------------------------------------------------------------------- +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const +{ + std::cout<<"Do CreateTrackToMCParticleRelationships"<<std::endl; + for (unsigned ik = 0; ik < trackVector.size(); ik++) + { + const edm4hep::Track *pTrack = trackVector.at(ik); + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + // Use momentum magnitude to identify best mc particle + edm4hep::MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + try + { + for (StringVector::const_iterator iter = m_settings.m_TrackRelationCollections.begin(), iterEnd = m_settings.m_TrackRelationCollections.end(); iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_TrkRel.find(*iter) == collectionMaps.collectionMap_TrkRel.end()) continue; + const std::vector<edm4hep::MCRecoTrackerAssociation>& pMCRecoTrackerAssociationCollection = (collectionMaps.collectionMap_TrkRel.find(*iter))->second; + for(unsigned ith=0 ; ith<pTrack->trackerHits_size(); ith++) + { + for(unsigned ic=0; ic < pMCRecoTrackerAssociationCollection.size(); ic++) + { + if( pMCRecoTrackerAssociationCollection.at(ic).getRec().id() != pTrack->getTrackerHits(ith).id() ) continue; + const edm4hep::ConstSimTrackerHit pSimHit = pMCRecoTrackerAssociationCollection.at(ic).getSim(); + const edm4hep::ConstMCParticle ipa = pSimHit.getMCParticle(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const float trueMomentum(pandora::CartesianVector(ipa.getMomentum()[0], ipa.getMomentum()[1], ipa.getMomentum()[2]).GetMagnitude()); + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle =const_cast<edm4hep::MCParticle*>((*m_id_pMC_map)[ipa.id()]); + bestDeltaMomentum = deltaMomentum; + } + } + } + } + + if (NULL == pBestMCParticle) continue; + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract track to mc particle relationship: " << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::Settings::Settings() +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp new file mode 100644 index 00000000..07527dbb --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp @@ -0,0 +1,932 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "GearSvc/IGearSvc.h" +#include "PandoraMatrixAlg.h" +#include "EventSeeder/IEventSeeder.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/Vector3d.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CaloHitContribution.h" +#include "edm4hep/ClusterConst.h" +#include "UTIL/ILDConf.h" +#include <cmath> +#include <algorithm> +#include "gear/BField.h" +#include <gear/GEAR.h> + +#include "LCContent.h" + + +pandora::Pandora* PandoraMatrixAlg::m_pPandora=0; + +DECLARE_COMPONENT( PandoraMatrixAlg ) + +template<typename T ,typename T1> +StatusCode getCol(T & t, T1 & t1) +{ + try { + t1 = t.get(); + } + catch ( GaudiException &e ) { + std::cout << "Collection " << t.fullKey() << " is unavailable in event " << std::endl; + } + return StatusCode::SUCCESS; +} + + + +PandoraMatrixAlg::PandoraMatrixAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + m_CollectionMaps = new CollectionMaps(); + + declareProperty("ReadMCParticle" , m_mcParCol_r, "Handle of the MCParticle input collection" ); + declareProperty("ReadECALBarrel" , m_ECALBarrel_r, "Handle of the ECALBarrel input collection" ); + declareProperty("ReadECALEndcap" , m_ECALEndcap_r, "Handle of the ECALEndcap input collection" ); + declareProperty("ReadECALOther" , m_ECALOther_r, "Handle of the ECALOther input collection" ); + declareProperty("ReadHCALBarrel" , m_HCALBarrel_r, "Handle of the HCALBarrel input collection" ); + declareProperty("ReadHCALEndcap" , m_HCALEndcap_r, "Handle of the HCALEndcap input collection" ); + declareProperty("ReadHCALOther" , m_HCALOther_r, "Handle of the HCALOther input collection" ); + declareProperty("ReadMUON" , m_MUON_r, "Handle of the MUON input collection" ); + declareProperty("ReadLCAL" , m_LCAL_r, "Handle of the LCAL input collection" ); + declareProperty("ReadLHCAL" , m_LHCAL_r, "Handle of the LHCAL input collection" ); + declareProperty("ReadBCAL" , m_BCAL_r, "Handle of the BCAL input collection" ); + declareProperty("ReadKinkVertices" , m_KinkVertices_r, "Handle of the KinkVertices input collection" ); + declareProperty("ReadProngVertices" , m_ProngVertices_r, "Handle of the ProngVertices input collection" ); + declareProperty("ReadSplitVertices" , m_SplitVertices_r, "Handle of the SplitVertices input collection" ); + declareProperty("ReadV0Vertices" , m_V0Vertices_r, "Handle of the V0Vertices input collection" ); + declareProperty("ReadTracks" , m_MarlinTrkTracks_r, "Handle of the Tracks input collection" ); + declareProperty("MCRecoCaloAssociation" , m_MCRecoCaloAssociation_r, "Handle of the MCRecoCaloAssociation input collection" ); + declareProperty("MCRecoTrackerAssociation" , m_MCRecoTrackerAssociation_r, "Handle of the MCRecoTrackerAssociation input collection" ); + declareProperty("WriteClusterCollection" , m_ClusterCollection_w, "Handle of the ClusterCollection output collection" ); + declareProperty("WriteReconstructedParticleCollection", m_ReconstructedParticleCollection_w, "Handle of the ReconstructedParticleCollection output collection" ); + declareProperty("WriteVertexCollection" , m_VertexCollection_w, "Handle of the VertexCollection output collection" ); + +} + + +void PandoraMatrixAlg::FinaliseSteeringParameters(ISvcLocator* svcloc) +{ + // ATTN: This function seems to be necessary for operations that cannot easily be performed at construction of the processor, + // when the steering file is parsed e.g. the call to GEAR to get the inner bfield + + m_caloHitCreatorSettings.m_absorberRadLengthECal = m_geometryCreatorSettings.m_absorberRadLengthECal; + m_caloHitCreatorSettings.m_absorberIntLengthECal = m_geometryCreatorSettings.m_absorberIntLengthECal; + m_caloHitCreatorSettings.m_absorberRadLengthHCal = m_geometryCreatorSettings.m_absorberRadLengthHCal; + m_caloHitCreatorSettings.m_absorberIntLengthHCal = m_geometryCreatorSettings.m_absorberIntLengthHCal; + m_caloHitCreatorSettings.m_absorberRadLengthOther = m_geometryCreatorSettings.m_absorberRadLengthOther; + m_caloHitCreatorSettings.m_absorberIntLengthOther = m_geometryCreatorSettings.m_absorberIntLengthOther; + + m_caloHitCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder; + m_caloHitCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate; + + m_trackCreatorSettings.m_prongSplitVertexCollections = m_trackCreatorSettings.m_prongVertexCollections; + m_trackCreatorSettings.m_prongSplitVertexCollections.insert(m_trackCreatorSettings.m_prongSplitVertexCollections.end(), + m_trackCreatorSettings.m_splitVertexCollections.begin(), m_trackCreatorSettings.m_splitVertexCollections.end()); + + //m_settings.m_innerBField = marlin::Global::GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + gear::GearMgr* _GEAR = iSvc->getGearMgr(); + m_settings.m_innerBField = _GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + std::cout<<"m_innerBField="<<m_settings.m_innerBField<<std::endl; + m_mcParticleCreatorSettings.m_bField = m_settings.m_innerBField; +} + + + + +StatusCode PandoraMatrixAlg::initialize() +{ + + std::cout<<"hi init PandoraMatrixAlg"<<std::endl; + + std::string s_output =m_AnaOutput; + m_fout = new TFile(s_output.c_str(),"RECREATE"); + m_tree = new TTree("evt","tree"); + m_tree->Branch("m_pReco_PID" , &m_pReco_PID); + m_tree->Branch("m_pReco_mass" , &m_pReco_mass); + m_tree->Branch("m_pReco_energy", &m_pReco_energy); + m_tree->Branch("m_pReco_px" , &m_pReco_px); + m_tree->Branch("m_pReco_py" , &m_pReco_py); + m_tree->Branch("m_pReco_pz" , &m_pReco_pz); + m_tree->Branch("m_pReco_charge", &m_pReco_charge); + + m_tree->Branch("m_mc_p_size", &m_mc_p_size); + m_tree->Branch("m_mc_pid" , &m_mc_pid ); + m_tree->Branch("m_mc_mass" , &m_mc_mass ); + m_tree->Branch("m_mc_px" , &m_mc_px ); + m_tree->Branch("m_mc_py" , &m_mc_py ); + m_tree->Branch("m_mc_pz" , &m_mc_pz ); + m_tree->Branch("m_mc_charge", &m_mc_charge); + m_tree->Branch("m_hasConversion", &m_hasConversion); + + + m_tree->Branch("m_hits_x", &m_hits_x); + m_tree->Branch("m_hits_y", &m_hits_y); + m_tree->Branch("m_hits_z", &m_hits_z); + m_tree->Branch("m_hits_E", &m_hits_E); + + + // XML file + m_settings.m_pandoraSettingsXmlFile = m_PandoraSettingsXmlFile ; + // Hadronic energy non-linearity correction + m_settings.m_inputEnergyCorrectionPoints = m_InputEnergyCorrectionPoints; + m_settings.m_outputEnergyCorrectionPoints = m_OutputEnergyCorrectionPoints; + // B-field parameters + m_settings.m_muonBarrelBField = m_MuonBarrelBField; + m_settings.m_muonEndCapBField = m_MuonEndCapBField; + + m_trackCreatorSettings.m_trackCollections = m_TrackCollections ; + m_trackCreatorSettings.m_kinkVertexCollections = m_KinkVertexCollections; + m_trackCreatorSettings.m_prongVertexCollections = m_ProngVertexCollections; + m_trackCreatorSettings.m_splitVertexCollections = m_SplitVertexCollections; + m_trackCreatorSettings.m_v0VertexCollections = m_V0VertexCollections; + + m_caloHitCreatorSettings.m_eCalCaloHitCollections = m_ECalCaloHitCollections; + m_caloHitCreatorSettings.m_hCalCaloHitCollections = m_HCalCaloHitCollections; + m_caloHitCreatorSettings.m_lCalCaloHitCollections = m_LCalCaloHitCollections; + m_caloHitCreatorSettings.m_lHCalCaloHitCollections = m_LHCalCaloHitCollections; + m_caloHitCreatorSettings.m_muonCaloHitCollections = m_MuonCaloHitCollections; + m_mcParticleCreatorSettings.m_mcParticleCollections = m_MCParticleCollections; + m_mcParticleCreatorSettings.m_CaloHitRelationCollections = m_RelCaloHitCollections; + m_mcParticleCreatorSettings.m_TrackRelationCollections = m_RelTrackCollections; + + + // Absorber properties + m_geometryCreatorSettings.m_absorberRadLengthECal = m_AbsorberRadLengthECal; + m_geometryCreatorSettings.m_absorberIntLengthECal = m_AbsorberIntLengthECal; + m_geometryCreatorSettings.m_absorberRadLengthHCal = m_AbsorberRadLengthHCal; + m_geometryCreatorSettings.m_absorberIntLengthHCal = m_AbsorberIntLengthHCal; + m_geometryCreatorSettings.m_absorberRadLengthOther = m_AbsorberRadLengthOther; + m_geometryCreatorSettings.m_absorberIntLengthOther = m_AbsorberIntLengthOther; + + // Name of PFO collection written by GaudiPandora + + m_pfoCreatorSettings.m_clusterCollectionName = m_ClusterCollectionName;// not used + m_pfoCreatorSettings.m_pfoCollectionName = m_PFOCollectionName;// + m_pfoCreatorSettings.m_startVertexCollectionName = m_StartVertexCollectionName; // + m_pfoCreatorSettings.m_startVertexAlgName = m_StartVertexAlgorithmName;// + + m_pfoCreatorSettings.m_emStochasticTerm = m_EMStochasticTerm; + m_pfoCreatorSettings.m_hadStochasticTerm = m_HadStochasticTerm; + m_pfoCreatorSettings.m_emConstantTerm = m_EMConstantTerm; + m_pfoCreatorSettings.m_hadConstantTerm = m_HadConstantTerm; + + // Calibration constants + m_caloHitCreatorSettings.m_eCalToMip = m_ECalToMipCalibration; + m_caloHitCreatorSettings.m_hCalToMip = m_HCalToMipCalibration; + m_caloHitCreatorSettings.m_eCalMipThreshold = m_ECalMipThreshold; + m_caloHitCreatorSettings.m_muonToMip = m_MuonToMipCalibration; + m_caloHitCreatorSettings.m_hCalMipThreshold = m_HCalMipThreshold; + m_caloHitCreatorSettings.m_eCalToEMGeV = m_ECalToEMGeVCalibration; + m_caloHitCreatorSettings.m_hCalToEMGeV = m_HCalToEMGeVCalibration; + m_caloHitCreatorSettings.m_eCalToHadGeVEndCap = m_ECalToHadGeVCalibrationEndCap; + m_caloHitCreatorSettings.m_eCalToHadGeVBarrel = m_ECalToHadGeVCalibrationBarrel; + m_caloHitCreatorSettings.m_hCalToHadGeV = m_HCalToHadGeVCalibration; + m_caloHitCreatorSettings.m_muonDigitalHits = m_DigitalMuonHits; + m_caloHitCreatorSettings.m_muonHitEnergy = m_MuonHitEnergy; + m_caloHitCreatorSettings.m_maxHCalHitHadronicEnergy = m_MaxHCalHitHadronicEnergy; + m_caloHitCreatorSettings.m_nOuterSamplingLayers = m_NOuterSamplingLayers; + m_caloHitCreatorSettings.m_layersFromEdgeMaxRearDistance = m_LayersFromEdgeMaxRearDistance; + + // Track relationship parameters + m_trackCreatorSettings.m_shouldFormTrackRelationships = m_ShouldFormTrackRelationships; + // Initial track hit specifications + m_trackCreatorSettings.m_minTrackHits = m_MinTrackHits; + m_trackCreatorSettings.m_minFtdTrackHits = m_MinFtdTrackHits; + m_trackCreatorSettings.m_maxTrackHits = m_MaxTrackHits; + ////m_trackCreatorSettings.m_useOldTrackStateCalculation = m_UseOldTrackStateCalculation; + // Track PFO usage parameters + m_trackCreatorSettings.m_d0TrackCut = m_D0TrackCut; + m_trackCreatorSettings.m_z0TrackCut = m_Z0TrackCut; + m_trackCreatorSettings.m_usingNonVertexTracks = m_UseNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedNonVertexTracks = m_UseUnmatchedNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedVertexTracks = m_UseUnmatchedVertexTracks; + m_trackCreatorSettings.m_unmatchedVertexTrackMaxEnergy = m_UnmatchedVertexTrackMaxEnergy; + m_trackCreatorSettings.m_d0UnmatchedVertexTrackCut = m_D0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_z0UnmatchedVertexTrackCut = m_Z0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_zCutForNonVertexTracks = m_ZCutForNonVertexTracks; + // Track "reaches ecal" parameters + m_trackCreatorSettings.m_reachesECalNTpcHits = m_ReachesECalNTpcHits; + m_trackCreatorSettings.m_reachesECalNFtdHits = m_ReachesECalNFtdHits; + m_trackCreatorSettings.m_reachesECalTpcOuterDistance = m_ReachesECalTpcOuterDistance; + m_trackCreatorSettings.m_reachesECalMinFtdLayer = m_ReachesECalMinFtdLayer; + m_trackCreatorSettings.m_reachesECalTpcZMaxDistance = m_ReachesECalTpcZMaxDistance; + m_trackCreatorSettings.m_reachesECalFtdZMaxDistance = m_ReachesECalFtdZMaxDistance; + m_trackCreatorSettings.m_curvatureToMomentumFactor = m_CurvatureToMomentumFactor; + m_trackCreatorSettings.m_minTrackECalDistanceFromIp = m_MinTrackECalDistanceFromIp; + // Final track quality parameters + m_trackCreatorSettings.m_maxTrackSigmaPOverP = m_MaxTrackSigmaPOverP; + m_trackCreatorSettings.m_minMomentumForTrackHitChecks = m_MinMomentumForTrackHitChecks; + m_trackCreatorSettings.m_tpcMembraneMaxZ = m_TpcMembraneMaxZ; + m_trackCreatorSettings.m_minTpcHitFractionOfExpected = m_MinTpcHitFractionOfExpected; + m_trackCreatorSettings.m_minFtdHitsForTpcHitFraction = m_MinFtdHitsForTpcHitFraction; + m_trackCreatorSettings.m_maxTpcInnerRDistance = m_MaxTpcInnerRDistance; + + + // Additional geometry parameters + m_geometryCreatorSettings.m_eCalEndCapInnerSymmetryOrder = m_ECalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapInnerPhiCoordinate = m_ECalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_eCalEndCapOuterSymmetryOrder = m_ECalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapOuterPhiCoordinate = m_ECalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_HCalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_HCalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapOuterSymmetryOrder = m_HCalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapOuterPhiCoordinate = m_HCalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingInnerSymmetryOrder = m_HCalRingInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingInnerPhiCoordinate = m_HCalRingInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingOuterSymmetryOrder = m_HCalRingOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingOuterPhiCoordinate = m_HCalRingOuterPhiCoordinate; + + // For Strip Splitting method and also for hybrid ECAL + m_caloHitCreatorSettings.m_stripSplittingOn = m_StripSplittingOn; + m_caloHitCreatorSettings.m_useEcalScLayers = m_UseEcalScLayers; + // Parameters for hybrid ECAL + // Energy to MIP for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToMip = m_ECalSiToMipCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToMip = m_ECalScToMipCalibration; + // MipThreshold for Si-layers and Sc-layers, respectively. + // Si + m_caloHitCreatorSettings.m_eCalSiMipThreshold = m_ECalSiMipThreshold; + //Sc + m_caloHitCreatorSettings.m_eCalScMipThreshold = m_ECalScMipThreshold; + // EcalToEM for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToEMGeV = m_ECalSiToEMGeVCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToEMGeV = m_ECalScToEMGeVCalibration; + // EcalToHad for Si-layers and Sc-layers of the endcaps, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVEndCap = m_ECalSiToHadGeVCalibrationEndCap; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVEndCap = m_ECalScToHadGeVCalibrationEndCap; + // EcalToHad for Si-layers and Sc-layers of the barrel, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVBarrel = m_ECalSiToHadGeVCalibrationBarrel; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVBarrel = m_ECalScToHadGeVCalibrationBarrel; + + try + { + ISvcLocator* svcloc = serviceLocator(); + this->FinaliseSteeringParameters(svcloc); + m_pPandora = new pandora::Pandora(); + m_pMCParticleCreator = new MCParticleCreator(m_mcParticleCreatorSettings, m_pPandora); + m_pGeometryCreator = new GeometryCreator(m_geometryCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pGeometryCreator->CreateGeometry(svcloc)); + m_pCaloHitCreator = new CaloHitCreator(m_caloHitCreatorSettings, m_pPandora, svcloc, 0); + m_pTrackCreator = new TrackCreator(m_trackCreatorSettings, m_pPandora, svcloc); + m_pPfoCreator = new PfoCreator(m_pfoCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->RegisterUserComponents()); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*m_pPandora, m_settings.m_pandoraSettingsXmlFile)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to initialize gaudi pandora: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Failed to initialize gaudi pandora: unrecognized exception" << std::endl; + throw; + } + + + return GaudiAlgorithm::initialize(); +} + +StatusCode PandoraMatrixAlg::execute() +{ + + try + { + std::cout<<"execute PandoraMatrixAlg"<<std::endl; + + updateMap(); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateMCParticles(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pCaloHitCreator->CreateCaloHits(*m_CollectionMaps)); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateCaloHitToMCParticleRelationships(*m_CollectionMaps, m_pCaloHitCreator->GetCalorimeterHitVector() )); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTrackAssociations(*m_CollectionMaps)); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTracks(*m_CollectionMaps)); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateTrackToMCParticleRelationships(*m_CollectionMaps, m_pTrackCreator->GetTrackVector() )); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pPandora)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pPfoCreator->CreateParticleFlowObjects(*m_CollectionMaps, m_ClusterCollection_w, m_ReconstructedParticleCollection_w, m_VertexCollection_w)); + + StatusCode sc0 = CreateMCRecoParticleAssociation(); + StatusCode sc = Ana(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pPandora)); + this->Reset(); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Gaudi pandora failed to process event: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Gaudi pandora failed to process event: unrecognized exception" << std::endl; + throw; + } + + info() << "PandoraMatrixAlg Processed " << _nEvt << " events " << endmsg; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode PandoraMatrixAlg::finalize() +{ + info() << "Finalized. Processed " << _nEvt << " events " <<",saved tree with entries="<<m_tree->GetEntries()<< endmsg; + m_fout->cd(); + m_tree->Write(); + m_fout->Close(); + delete m_pPandora; + delete m_pGeometryCreator; + delete m_pCaloHitCreator; + delete m_pTrackCreator; + delete m_pMCParticleCreator; + delete m_pPfoCreator; + return GaudiAlgorithm::finalize(); +} + + + + +pandora::StatusCode PandoraMatrixAlg::RegisterUserComponents() const +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterAlgorithms(*m_pPandora)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBasicPlugins(*m_pPandora)); + + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBFieldPlugin(*m_pPandora, + m_settings.m_innerBField, m_settings.m_muonBarrelBField, m_settings.m_muonEndCapBField)); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterNonLinearityEnergyCorrection(*m_pPandora, + "NonLinearity", pandora::HADRONIC, m_settings.m_inputEnergyCorrectionPoints, m_settings.m_outputEnergyCorrectionPoints)); + + + /* + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::RegisterAlgorithmFactory(*m_pPandora, + "ExternalClustering", new ExternalClusteringAlgorithm::Factory)); + */ + + return pandora::STATUS_CODE_SUCCESS; +} + + +void PandoraMatrixAlg::Reset() +{ + m_pCaloHitCreator->Reset(); + m_pTrackCreator->Reset(); + m_pMCParticleCreator->Reset(); + + std::vector<int>() .swap(m_pReco_PID ); + std::vector<float>().swap(m_pReco_mass); + std::vector<float>().swap(m_pReco_energy); + std::vector<float>().swap(m_pReco_px); + std::vector<float>().swap(m_pReco_py); + std::vector<float>().swap(m_pReco_pz); + std::vector<float>().swap(m_pReco_charge); + + std::vector<int>() .swap(m_mc_p_size); + std::vector<int>() .swap(m_mc_pid ); + std::vector<float>().swap(m_mc_mass ); + std::vector<float>().swap(m_mc_px ); + std::vector<float>().swap(m_mc_py ); + std::vector<float>().swap(m_mc_pz ); + std::vector<float>().swap(m_mc_charge); + + std::vector<float>() .swap(m_hits_x); + std::vector<float>() .swap(m_hits_y); + std::vector<float>() .swap(m_hits_z); + std::vector<float>() .swap(m_hits_E); + + m_hasConversion = 0; + + m_CollectionMaps->clear(); +} + +const pandora::Pandora *PandoraMatrixAlg::GetPandora() const +{ + if (NULL == m_pPandora) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return m_pPandora; +} +PandoraMatrixAlg::Settings::Settings() : + m_innerBField(3.5f), + m_muonBarrelBField(-1.5f), + m_muonEndCapBField(0.01f) +{ +} +CollectionMaps::CollectionMaps() +{ +} +void CollectionMaps::clear() +{ +CollectionMap_MC.clear(); +CollectionMap_CaloHit.clear(); +CollectionMap_Vertex.clear(); +CollectionMap_Track.clear(); +collectionMap_MC.clear(); +collectionMap_CaloHit.clear(); +collectionMap_Vertex.clear(); +collectionMap_Track.clear(); +collectionMap_CaloRel.clear(); +collectionMap_TrkRel.clear(); +} + +StatusCode PandoraMatrixAlg::updateMap() +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + m_CollectionMaps->CollectionMap_MC ["MCParticle"] = MCParticle ; + m_CollectionMaps->collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) m_CollectionMaps->collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALBarrel"] = ECALBarrel ; + m_CollectionMaps->collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALEndcap"] = ECALEndcap ; + m_CollectionMaps->collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALOther"] = ECALOther ; + m_CollectionMaps->collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALBarrel"] = HCALBarrel ; + m_CollectionMaps->collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALEndcap"] = HCALEndcap ; + m_CollectionMaps->collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALOther"] = HCALOther ; + m_CollectionMaps->collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["MUON"] = MUON ; + m_CollectionMaps->collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["LCAL"] = LCAL ; + m_CollectionMaps->collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["LHCAL"] = LHCAL ; + m_CollectionMaps->collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["BCAL"] = BCAL ; + m_CollectionMaps->collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["KinkVertices"] = KinkVertices ; + m_CollectionMaps->collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["ProngVertices"] = ProngVertices ; + m_CollectionMaps->collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["SplitVertices"] = SplitVertices ; + m_CollectionMaps->collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["V0Vertices"] = V0Vertices ; + m_CollectionMaps->collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + m_CollectionMaps->CollectionMap_Track["MarlinTrkTracks"] = MarlinTrkTracks ; + m_CollectionMaps->collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) m_CollectionMaps->collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel["RecoCaloAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) m_CollectionMaps->collectionMap_CaloRel ["RecoCaloAssociation"].push_back(mcRecoCaloAssociation->at(i)); + } + + else + { + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + if(MCParticle->at(i).parents_size()==0) + { + std::cout<<"create recoCaloAssociation by hand now"<<std::endl; + for(std::map<std::string, std::vector<edm4hep::CalorimeterHit> >::iterator iter = m_CollectionMaps->collectionMap_CaloHit.begin(); iter != m_CollectionMaps->collectionMap_CaloHit.end(); iter++) + { + std::string prefix = "RecoCaloAssociation_"; + std::string key = prefix + iter->first; + std::cout<<"create for "<<key<<std::endl; + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel[key] = v_cal ; + for(std::vector<edm4hep::CalorimeterHit>::iterator it=iter->second.begin(); it != iter->second.end(); it ++) + { + edm4hep::SimCalorimeterHit sim_hit( it->getCellID(), it->getEnergy(), it->getPosition() ); + edm4hep::CaloHitContribution conb ( MCParticle->at(i).getPDG(), it->getEnergy(), 0, it->getPosition() ); + conb.setParticle( MCParticle->at(i) ); + sim_hit.addContribution(conb); + edm4hep::MCRecoCaloAssociation calo_association; + calo_association.setRec(*it); + calo_association.setSim(sim_hit); + m_CollectionMaps->collectionMap_CaloRel[key].push_back(calo_association); + } + } + break; + } + } + } + } + + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + m_CollectionMaps->collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) m_CollectionMaps->collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + +StatusCode PandoraMatrixAlg::updateMap(CollectionMaps & tmp_map) +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation ); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + tmp_map.CollectionMap_MC ["MCParticle"] = MCParticle ; + tmp_map.collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) tmp_map.collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALBarrel"] = ECALBarrel ; + tmp_map.collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) tmp_map.collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALEndcap"] = ECALEndcap ; + tmp_map.collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) tmp_map.collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALOther"] = ECALOther ; + tmp_map.collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) tmp_map.collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALBarrel"] = HCALBarrel ; + tmp_map.collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) tmp_map.collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALEndcap"] = HCALEndcap ; + tmp_map.collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) tmp_map.collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALOther"] = HCALOther ; + tmp_map.collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) tmp_map.collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["MUON"] = MUON ; + tmp_map.collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) tmp_map.collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["LCAL"] = LCAL ; + tmp_map.collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) tmp_map.collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["LHCAL"] = LHCAL ; + tmp_map.collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) tmp_map.collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["BCAL"] = BCAL ; + tmp_map.collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) tmp_map.collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["KinkVertices"] = KinkVertices ; + tmp_map.collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) tmp_map.collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["ProngVertices"] = ProngVertices ; + tmp_map.collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) tmp_map.collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["SplitVertices"] = SplitVertices ; + tmp_map.collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) tmp_map.collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["V0Vertices"] = V0Vertices ; + tmp_map.collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) tmp_map.collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + tmp_map.CollectionMap_Track["MarlinTrkTracks"] = MarlinTrkTracks ; + tmp_map.collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) tmp_map.collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + tmp_map.collectionMap_CaloRel["RecoCaloAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) tmp_map.collectionMap_CaloRel ["RecoCaloAssociation"].push_back(mcRecoCaloAssociation->at(i)); + } + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + tmp_map.collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) tmp_map.collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + +StatusCode PandoraMatrixAlg::Ana() +{ + int n_current = m_tree->GetEntries()+1; + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + const edm4hep::MCRecoParticleAssociationCollection* reco_associa_col = m_MCRecoParticleAssociation_w.get(); + std::cout<<"reco_col size="<<reco_col->size()<<std::endl; + for(int i=0; i<reco_col->size();i++) + { + std::cout<<"reco="<<i<<std::endl; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + const float px = pReco.getMomentum()[0]; + const float py = pReco.getMomentum()[1]; + const float pz = pReco.getMomentum()[2]; + const float energy = pReco.getEnergy(); + const float mass = pReco.getMass(); + const float charge = pReco.getCharge(); + const int type = pReco.getType(); + std::cout<<"MYDBUG evt="<<n_current<<",rec i="<<i<<",particleId="<<type<<",mass="<<mass<<",charge="<<charge<<",energy="<<energy<<",px="<<px<<",py="<<py<<",pz="<<pz<<std::endl; + m_pReco_PID.push_back(type); + m_pReco_mass.push_back(mass); + m_pReco_charge.push_back(charge); + m_pReco_energy.push_back(energy); + m_pReco_px.push_back(px); + m_pReco_py.push_back(py); + m_pReco_pz.push_back(pz); + for(int j=0; j < reco_associa_col->size(); j++) + { + if(reco_associa_col->at(j).getRec().id() != pReco.id() ) continue; + std::cout<<"MC pid ="<<reco_associa_col->at(j).getSim().getPDG()<<", px="<<reco_associa_col->at(j).getSim().getMomentum()[0]<<", py="<<reco_associa_col->at(j).getSim().getMomentum()[1]<<",pz="<<reco_associa_col->at(j).getSim().getMomentum()[2]<<std::endl; + } + } + const edm4hep::MCParticleCollection* MCParticle = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + m_mc_p_size.push_back(MCParticle->at(i).parents_size()); + m_mc_pid .push_back(MCParticle->at(i).getPDG()); + m_mc_mass .push_back(MCParticle->at(i).getMass()); + m_mc_px .push_back(MCParticle->at(i).getMomentum()[0]); + m_mc_py .push_back(MCParticle->at(i).getMomentum()[1]); + m_mc_pz .push_back(MCParticle->at(i).getMomentum()[2]); + m_mc_charge.push_back(MCParticle->at(i).getCharge()); + //for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) da_pids.push_back( MCParticle->at(i).getDaughters(j).getPDG()); + if(MCParticle->at(i).parents_size()==0) std::cout<<"MYDBUG evt="<<n_current<<", mc i="<<i<<",px="<<MCParticle->at(i).getMomentum()[0]<<",py="<<MCParticle->at(i).getMomentum()[1]<<",pz="<<MCParticle->at(i).getMomentum()[2]<<std::endl; + if (MCParticle->at(i).getPDG() != 22) continue; + int hasEm = 0; + int hasEp = 0; + for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) + { + if (MCParticle->at(i).getDaughters(j).getPDG() == 11 ) hasEm=1; + else if (MCParticle->at(i).getDaughters(j).getPDG() == -11 ) hasEp=1; + } + if(hasEm && hasEp) m_hasConversion=1; + } + } + //sanity check calo info + const edm4hep::CalorimeterHitCollection* CaloCol = nullptr; + sc = getCol(m_ECALBarrel_r, CaloCol); + if (NULL != CaloCol ) + { + for(unsigned int i=0 ; i< CaloCol->size(); i++) + { + m_hits_x.push_back(CaloCol->at(i).getPosition()[0]); + m_hits_y.push_back(CaloCol->at(i).getPosition()[1]); + m_hits_z.push_back(CaloCol->at(i).getPosition()[2]); + m_hits_E.push_back(CaloCol->at(i).getEnergy() ); + } + } + + m_tree->Fill(); + return StatusCode::SUCCESS; +} + +// create simple MCRecoParticleAssociation using calorimeter hit only +StatusCode PandoraMatrixAlg::CreateMCRecoParticleAssociation() +{ + edm4hep::MCRecoParticleAssociationCollection* pMCRecoParticleAssociationCollection = m_MCRecoParticleAssociation_w.createAndPut(); + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + std::cout<<"CreateMCRecoParticleAssociation, reco_col size="<<reco_col->size()<<std::endl; + for(int i=0; i<reco_col->size();i++) + { + std::map<int, edm4hep::ConstMCParticle> mc_map; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + for(int j=0; j < pReco.clusters_size(); j++) + { + edm4hep::ConstCluster cluster = pReco.getClusters(j); + for(int k=0; k < cluster.hits_size(); k++) + { + edm4hep::ConstCalorimeterHit hit = cluster.getHits(k); + for(std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> >::iterator iter = m_CollectionMaps->collectionMap_CaloRel.begin(); iter != m_CollectionMaps->collectionMap_CaloRel.end(); iter++) + { + for(std::vector<edm4hep::MCRecoCaloAssociation>::iterator it = iter->second.begin(); it != iter->second.end(); it ++) + { + if(it->getRec().id() != hit.id()) continue; + for(std::vector<edm4hep::ConstCaloHitContribution>::const_iterator itc = it->getSim().contributions_begin(); itc != it->getSim().contributions_end(); itc++) + { + if(mc_map.find(itc->getParticle().id()) == mc_map.end()) mc_map[itc->getParticle().id()] = itc->getParticle() ; + } + } + } + } + } + for(std::map<int, edm4hep::ConstMCParticle>::iterator it = mc_map.begin(); it != mc_map.end(); it ++) + { + edm4hep::MCRecoParticleAssociation association = pMCRecoParticleAssociationCollection->create(); + association.setRec(pReco); + association.setSim(it->second); + } + } + return StatusCode::SUCCESS; +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp new file mode 100644 index 00000000..1c6069c5 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp @@ -0,0 +1,429 @@ +/** + * @file MarlinPandora/src/PfoCreator.cc + * + * @brief Implementation of the pfo creator class. + * + * $Log: $ + */ + +//#include "CalorimeterHitType.h" + +#include "Api/PandoraApi.h" + +#include "Objects/Cluster.h" +#include "Objects/ParticleFlowObject.h" +#include "Objects/Track.h" + +#include "Pandora/PdgTable.h" +#include "PfoCreator.h" +#include "PandoraMatrixAlg.h" + +#include <algorithm> +#include <cmath> + +PfoCreator::PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::~PfoCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection) +{ + m_collectionMaps = &collectionMaps; + edm4hep::ClusterCollection* pClusterCollection = _pClusterCollection.createAndPut(); + edm4hep::ReconstructedParticleCollection* pReconstructedParticleCollection = _pReconstructedParticleCollection.createAndPut(); + edm4hep::VertexCollection* pStartVertexCollection = _pStartVertexCollection.createAndPut(); + + const pandora::PfoList *pPandoraPfoList = NULL; + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pPandora, pPandoraPfoList)); + + + //IMPL::LCFlagImpl lcFlagImpl(pClusterCollection->getFlag()); + //lcFlagImpl.setBit(LCIO::CLBIT_HITS); + //pClusterCollection->setFlag(lcFlagImpl.getFlag()); + + pandora::StringVector subDetectorNames; + this->InitialiseSubDetectorNames(subDetectorNames); + //pClusterCollection->parameters().setValues("ClusterSubdetectorNames", subDetectorNames); + + // Create lcio "reconstructed particles" from the pandora "particle flow objects" + std::cout<<"pPandoraPfoList size="<<pPandoraPfoList->size()<<std::endl; + for (pandora::PfoList::const_iterator pIter = pPandoraPfoList->begin(), pIterEnd = pPandoraPfoList->end(); pIter != pIterEnd; ++pIter) + { + const pandora::ParticleFlowObject *const pPandoraPfo(*pIter); + //IMPL::ReconstructedParticleImpl *const pReconstructedParticle(new ReconstructedParticleImpl()); + edm4hep::ReconstructedParticle pReconstructedParticle0 = pReconstructedParticleCollection->create(); + edm4hep::ReconstructedParticle* pReconstructedParticle = &pReconstructedParticle0; + + const bool hasTrack(!pPandoraPfo->GetTrackList().empty()); + const pandora::ClusterList &clusterList(pPandoraPfo->GetClusterList()); + + //std::cout<<"ClusterList size="<<clusterList.size()<<std::endl; + float clustersTotalEnergy(0.f); + pandora::CartesianVector referencePoint(0.f, 0.f, 0.f), clustersWeightedPosition(0.f, 0.f, 0.f); + for (pandora::ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter) + { + const pandora::Cluster *const pPandoraCluster(*cIter); + pandora::CaloHitList pandoraCaloHitList; + pPandoraCluster->GetOrderedCaloHitList().FillCaloHitList(pandoraCaloHitList); + pandoraCaloHitList.insert(pandoraCaloHitList.end(), pPandoraCluster->GetIsolatedCaloHitList().begin(), pPandoraCluster->GetIsolatedCaloHitList().end()); + + pandora::FloatVector hitE, hitX, hitY, hitZ; + //IMPL::ClusterImpl *const p_Cluster(new ClusterImpl()); + edm4hep::Cluster p_Cluster0 = pClusterCollection->create(); + edm4hep::Cluster* p_Cluster = &p_Cluster0; + this->SetClusterSubDetectorEnergies(subDetectorNames, p_Cluster, pandoraCaloHitList, hitE, hitX, hitY, hitZ); + + float clusterCorrectEnergy(0.f); + this->SetClusterEnergyAndError(pPandoraPfo, pPandoraCluster, p_Cluster, clusterCorrectEnergy); + + pandora::CartesianVector clusterPosition(0.f, 0.f, 0.f); + const unsigned int nHitsInCluster(pandoraCaloHitList.size()); + this->SetClusterPositionAndError(nHitsInCluster, hitE, hitX, hitY, hitZ, p_Cluster, clusterPosition); + + if (!hasTrack) + { + clustersWeightedPosition += clusterPosition * clusterCorrectEnergy; + clustersTotalEnergy += clusterCorrectEnergy; + } + + //pClusterCollection->addElement(p_Cluster); + edm4hep::ConstCluster p_ClusterCon = *p_Cluster; + pReconstructedParticle->addCluster(p_ClusterCon); + } + + if (!hasTrack) + { + if (clustersTotalEnergy < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CreateParticleFlowObjects: invalid cluster energy " << clustersTotalEnergy << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = clustersWeightedPosition * (1.f / clustersTotalEnergy); + } + } + else + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CalculateTrackBasedReferencePoint(pPandoraPfo, referencePoint)); + } + + this->SetRecoParticleReferencePoint(referencePoint, pReconstructedParticle); + this->AddTracksToRecoParticle(pPandoraPfo, pReconstructedParticle); + this->SetRecoParticlePropertiesFromPFO(pPandoraPfo, pReconstructedParticle); + + edm4hep::Vertex pStartVertex0 = pStartVertexCollection->create(); + edm4hep::Vertex* pStartVertex = &pStartVertex0; + //pStartVertex->setAlgorithmType(m_settings.m_startVertexAlgName.c_str()); + pStartVertex->setAlgorithmType(0); + const float ref_value[3] = {referencePoint.GetX(),referencePoint.GetY(),referencePoint.GetZ()}; + pStartVertex->setPosition(edm4hep::Vector3f(ref_value)); + pStartVertex->setAssociatedParticle(*pReconstructedParticle); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const +{ + subDetectorNames.push_back("ecal"); + subDetectorNames.push_back("hcal"); + subDetectorNames.push_back("yoke"); + subDetectorNames.push_back("lcal"); + subDetectorNames.push_back("lhcal"); + subDetectorNames.push_back("bcal"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const p_Cluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const +{ + for (pandora::CaloHitList::const_iterator hIter = pandoraCaloHitList.begin(), hIterEnd = pandoraCaloHitList.end(); hIter != hIterEnd; ++hIter) + { + const pandora::CaloHit *const pPandoraCaloHit(*hIter); + edm4hep::CalorimeterHit *const pCalorimeterHit0 = (edm4hep::CalorimeterHit*)(pPandoraCaloHit->GetParentAddress()); + const edm4hep::CalorimeterHit pCalorimeterHit = *pCalorimeterHit0; + + p_Cluster->addHit(pCalorimeterHit); + + const float caloHitEnergy(pCalorimeterHit.getEnergy()); + hitE.push_back(caloHitEnergy); + hitX.push_back(pCalorimeterHit.getPosition()[0]); + hitY.push_back(pCalorimeterHit.getPosition()[1]); + hitZ.push_back(pCalorimeterHit.getPosition()[2]); + /* + std::vector<float> &subDetectorEnergies = p_Cluster->subdetectorEnergies(); + subDetectorEnergies.resize(subDetectorNames.size()); + + switch (CHT(pCalorimeterHit->getType()).caloID()) + { + case CHT::ecal: subDetectorEnergies[ECAL_INDEX ] += caloHitEnergy; break; + case CHT::hcal: subDetectorEnergies[HCAL_INDEX ] += caloHitEnergy; break; + case CHT::yoke: subDetectorEnergies[YOKE_INDEX ] += caloHitEnergy; break; + case CHT::lcal: subDetectorEnergies[LCAL_INDEX ] += caloHitEnergy; break; + case CHT::lhcal: subDetectorEnergies[LHCAL_INDEX] += caloHitEnergy; break; + case CHT::bcal: subDetectorEnergies[BCAL_INDEX ] += caloHitEnergy; break; + default: streamlog_out(WARNING) << "PfoCreator::SetClusterSubDetectorEnergies: no subdetector found for hit with type: " << pCalorimeterHit->getType() << std::endl; + } + */ + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const p_Cluster, float &clusterCorrectEnergy) const +{ + const bool isEmShower((pandora::PHOTON == pPandoraPfo->GetParticleId()) || (pandora::E_MINUS == std::abs(pPandoraPfo->GetParticleId()))); + clusterCorrectEnergy = (isEmShower ? pPandoraCluster->GetCorrectedElectromagneticEnergy(*m_pPandora) : pPandoraCluster->GetCorrectedHadronicEnergy(*m_pPandora)); + + if (clusterCorrectEnergy < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + + const float stochasticTerm(isEmShower ? m_settings.m_emStochasticTerm : m_settings.m_hadStochasticTerm); + const float constantTerm(isEmShower ? m_settings.m_emConstantTerm : m_settings.m_hadConstantTerm); + const float energyError(std::sqrt(stochasticTerm * stochasticTerm / clusterCorrectEnergy + constantTerm * constantTerm) * clusterCorrectEnergy); + + p_Cluster->setEnergy(clusterCorrectEnergy); + p_Cluster->setEnergyError(energyError); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const p_Cluster, pandora::CartesianVector &clusterPositionVec) const +{ + ClusterShapes *const pClusterShapes(new ClusterShapes(nHitsInCluster, hitE.data(), hitX.data(), hitY.data(), hitZ.data())); + + try + { + p_Cluster->setPhi(std::atan2(pClusterShapes->getEigenVecInertia()[1], pClusterShapes->getEigenVecInertia()[0])); + p_Cluster->setITheta(std::acos(pClusterShapes->getEigenVecInertia()[2])); + p_Cluster->setPosition(pClusterShapes->getCentreOfGravity()); + //ATTN these two lines below would only compile with ilcsoft HEAD V2015-10-13 and above + //p_Cluster->setPositionError(pClusterShapes->getCenterOfGravityErrors()); + //p_Cluster->setDirectionError(pClusterShapes->getEigenVecInertiaErrors()); + clusterPositionVec.SetValues(pClusterShapes->getCentreOfGravity()[0], pClusterShapes->getCentreOfGravity()[1], pClusterShapes->getCentreOfGravity()[2]); + } + catch (...) + { + std::cout<<"WARNING PfoCreator::SetClusterPositionAndError: unidentified exception caught." << std::endl; + } + + delete pClusterShapes; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + float totalTrackMomentumAtDca(0.f), totalTrackMomentumAtStart(0.f); + pandora::CartesianVector referencePointAtDCAWeighted(0.f, 0.f, 0.f), referencePointAtStartWeighted(0.f, 0.f, 0.f); + + bool hasSiblings(false); + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pPandoraTrack(*tIter); + + if (!this->IsValidParentTrack(pPandoraTrack, trackList)) + continue; + + if (this->HasValidSiblingTrack(pPandoraTrack, trackList)) + { + // Presence of sibling tracks typically represents a conversion + const pandora::CartesianVector &trackStartPoint((pPandoraTrack->GetTrackStateAtStart()).GetPosition()); + const float trackStartMomentum(((pPandoraTrack->GetTrackStateAtStart()).GetMomentum()).GetMagnitude()); + referencePointAtStartWeighted += trackStartPoint * trackStartMomentum; + totalTrackMomentumAtStart += trackStartMomentum; + hasSiblings = true; + } + else + { + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pPandoraTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + + const float z0(pPandoraTrack->GetZ0()); + pandora::CartesianVector intersectionPoint(0.f, 0.f, 0.f); + + //intersectionPoint.SetValues(pLcioTrack->getD0() * std::cos(pLcioTrack->getPhi()), pLcioTrack->getD0() * std::sin(pLcioTrack->getPhi()), z0); + if(pLcioTrack.trackStates_size()==0) throw "zero trackStates size find"; + intersectionPoint.SetValues(pLcioTrack.getTrackStates(0).D0 * std::cos(pLcioTrack.getTrackStates(0).phi), pLcioTrack.getTrackStates(0).D0 * std::sin(pLcioTrack.getTrackStates(0).phi), z0); + const float trackMomentumAtDca((pPandoraTrack->GetMomentumAtDca()).GetMagnitude()); + referencePointAtDCAWeighted += intersectionPoint * trackMomentumAtDca; + totalTrackMomentumAtDca += trackMomentumAtDca; + } + } + + if (hasSiblings) + { + if (totalTrackMomentumAtStart < std::numeric_limits<float>::epsilon()) + { + std::cout<<" WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtStart << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtStartWeighted * (1.f / totalTrackMomentumAtStart); + } + } + else + { + if (totalTrackMomentumAtDca < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtDca << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtDCAWeighted * (1.f / totalTrackMomentumAtDca); + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &parentTrackList(pPandoraTrack->GetParentList()); + + for (pandora::TrackList::const_iterator iter = parentTrackList.begin(), iterEnd = parentTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a parent not in the all track list; still use it if it is the closest to the ip + std::cout<<"WARNING PfoCreator::IsValidParentTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->IsClosestTrackToIP(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All parents are associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a sibling not in the all track list; still use it if it has a second sibling that is in the list + std::cout<<"WARNING PfoCreator::HasValidSiblingTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->AreAnyOtherSiblingsInList(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All siblings associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::Track *pClosestTrack(NULL); + float closestTrackDisplacement(std::numeric_limits<float>::max()); + + for (pandora::TrackList::const_iterator iter = allTrackList.begin(), iterEnd = allTrackList.end(); iter != iterEnd; ++iter) + { + const pandora::Track *const pTrack(*iter); + const float trialTrackDisplacement(pTrack->GetTrackStateAtStart().GetPosition().GetMagnitude()); + + if (trialTrackDisplacement < closestTrackDisplacement) + { + closestTrackDisplacement = trialTrackDisplacement; + pClosestTrack = pTrack; + } + } + + return (pPandoraTrack == pClosestTrack); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float referencePointArray[3] = {referencePoint.GetX(), referencePoint.GetY(), referencePoint.GetZ()}; + pReconstructedParticle->setReferencePoint(referencePointArray); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pTrack(*tIter); + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + pReconstructedParticle->addTrack(pLcioTrack); + + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float momentum[3] = {pPandoraPfo->GetMomentum().GetX(), pPandoraPfo->GetMomentum().GetY(), pPandoraPfo->GetMomentum().GetZ()}; + pReconstructedParticle->setMomentum(momentum); + pReconstructedParticle->setEnergy(pPandoraPfo->GetEnergy()); + pReconstructedParticle->setMass(pPandoraPfo->GetMass()); + pReconstructedParticle->setCharge(pPandoraPfo->GetCharge()); + pReconstructedParticle->setType(pPandoraPfo->GetParticleId()); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::Settings::Settings(): + m_emStochasticTerm(0.17f), + m_hadStochasticTerm(0.6f), + m_emConstantTerm(0.01f), + m_hadConstantTerm(0.03f) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp new file mode 100644 index 00000000..1a3c0f15 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp @@ -0,0 +1,987 @@ +/** + * @file MarlinPandora/src/TrackCreator.cc + * + * @brief Implementation of the track creator class. + * + * $Log: $ + */ + + +#include "UTIL/ILDConf.h" + +#include "edm4hep/Vertex.h" +#include "edm4hep/ReconstructedParticle.h" + +#include "gear/BField.h" +#include "gear/CalorimeterParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/TPCParameters.h" +#include "gear/FTDParameters.h" +#include "gear/FTDLayerLayout.h" + +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" +#include "PandoraMatrixAlg.h" + +#include "TrackCreator.h" +#include "Pandora/PdgTable.h" + +#include <algorithm> +#include <cmath> +#include <limits> + +TrackCreator::TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc) : + m_settings(settings), + m_pPandora(pPandora) +{ + + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + m_bField = (_GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z()); + m_tpcInnerR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[0]); + m_tpcOuterR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[1]); + m_tpcMaxRow = (_GEAR->getTPCParameters().getPadLayout().getNRows()); + m_tpcZmax = (_GEAR->getTPCParameters().getMaxDriftLength()); + m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder()); + m_eCalBarrelInnerPhi0 = (_GEAR->getEcalBarrelParameters().getPhi0()); + m_eCalBarrelInnerR = (_GEAR->getEcalBarrelParameters().getExtent()[0]); + m_eCalEndCapInnerZ = (_GEAR->getEcalEndcapParameters().getExtent()[2]); + // fg: FTD description in GEAR has changed ... + try + { + m_ftdInnerRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDInnerRadius"); + m_ftdOuterRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDOuterRadius"); + m_ftdZPositions = _GEAR->getGearParameters("FTD").getDoubleVals("FTDZCoordinate"); + m_nFtdLayers = m_ftdZPositions.size(); + } + catch (gear::UnknownParameterException &) + { + const gear::FTDLayerLayout &ftdLayerLayout(_GEAR->getFTDParameters().getFTDLayerLayout()); + std::cout << " Filling FTD parameters from gear::FTDParameters - n layers: " << ftdLayerLayout.getNLayers() << std::endl; + + for(unsigned int i = 0, N = ftdLayerLayout.getNLayers(); i < N; ++i) + { + // Create a disk to represent even number petals front side + m_ftdInnerRadii.push_back(ftdLayerLayout.getSensitiveRinner(i)); + m_ftdOuterRadii.push_back(ftdLayerLayout.getMaxRadius(i)); + + // Take the mean z position of the staggered petals + const double zpos(ftdLayerLayout.getZposition(i)); + m_ftdZPositions.push_back(zpos); + std::cout << " layer " << i << " - mean z position = " << zpos << std::endl; + } + + m_nFtdLayers = m_ftdZPositions.size() ; + } + + // Check tpc parameters + if ((std::fabs(m_tpcZmax) < std::numeric_limits<float>::epsilon()) || (std::fabs(m_tpcInnerR) < std::numeric_limits<float>::epsilon()) + || (std::fabs(m_tpcOuterR - m_tpcInnerR) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + m_cosTpc = m_tpcZmax / std::sqrt(m_tpcZmax * m_tpcZmax + m_tpcInnerR * m_tpcInnerR); + + // Check ftd parameters + if ((0 == m_nFtdLayers) || (m_nFtdLayers != m_ftdInnerRadii.size()) || (m_nFtdLayers != m_ftdOuterRadii.size())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((std::fabs(m_ftdOuterRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon()) || + (std::fabs(m_ftdInnerRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + } + + m_tanLambdaFtd = m_ftdZPositions[0] / m_ftdOuterRadii[0]; + + // Calculate etd and set parameters + // fg: make SET and ETD optional - as they might not be in the model ... + try + { + const DoubleVector &etdZPositions(_GEAR->getGearParameters("ETD").getDoubleVals("ETDLayerZ")); + const DoubleVector &setInnerRadii(_GEAR->getGearParameters("SET").getDoubleVals("SETLayerRadius")); + + if (etdZPositions.empty() || setInnerRadii.empty()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + m_minEtdZPosition = *(std::min_element(etdZPositions.begin(), etdZPositions.end())); + m_minSetRadius = *(std::min_element(setInnerRadii.begin(), setInnerRadii.end())); + } + catch(gear::UnknownParameterException &) + { + std::cout << "Warnning, ETDLayerZ or SETLayerRadius parameters missing from GEAR parameters!" << std::endl + << " -> both will be set to " << std::numeric_limits<float>::quiet_NaN() << std::endl; + + //fg: Set them to NAN, so that they cannot be used to set trackParameters.m_reachesCalorimeter = true; + m_minEtdZPosition = std::numeric_limits<float>::quiet_NaN(); + m_minSetRadius = std::numeric_limits<float>::quiet_NaN(); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::~TrackCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTrackAssociations(const CollectionMaps& collectionMaps) +{ +// Don't use it now, because the Vertex.getAssociatedParticle() doesn't work for LCIO to plcio transfer +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractKinks(collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractProngsAndSplits(const CollectionMaps& collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractV0s(const CollectionMaps& collectionMaps)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractKinks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::ExtractKinks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_kinkVertexCollections.begin(), iterEnd = m_settings.m_kinkVertexCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.CollectionMap_Vertex.find(*iter) == collectionMaps.CollectionMap_Vertex.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const edm4hep::VertexCollection *pKinkCollection = (collectionMaps.CollectionMap_Vertex.find(*iter))->second; + + for (int i = 0, iMax = pKinkCollection->size(); i < iMax; ++i) + { + try + { + const edm4hep::Vertex pVertex0 = pKinkCollection->at(i); + const edm4hep::Vertex* pVertex = &(pVertex0); + + if (NULL == pVertex) throw ("Collection type mismatch"); + + std::cout<<"pVertex0 getChi2="<<pVertex0.getChi2()<<std::endl; + std::cout<<"pVertex getChi2="<<pVertex->getChi2()<<std::endl; + std::cout<<"Hi 0 "<<std::endl; + const plcio::ConstReconstructedParticle pReconstructedParticle0 = pVertex0.getAssociatedParticle(); + std::cout<<"Hi 1"<<std::endl; + //EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const plcio::ConstReconstructedParticle pReconstructedParticle = pVertex->getAssociatedParticle(); + std::cout<<"Hi 2:"<<&pReconstructedParticle<<std::endl; + //const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + //plcio::ConstTrack trackVec = pReconstructedParticle.getTracks(); + + std::cout<<"pReconstructedParticle0 en="<<pReconstructedParticle0.getEnergy()<<std::endl; + std::cout<<"pReconstructedParticle en="<<pReconstructedParticle.getEnergy()<<std::endl; + //if (this->IsConflictingRelationship(trackVec))continue; + if (this->IsConflictingRelationship(pReconstructedParticle))continue; + + //const int vertexPdgCode(pReconstructedParticle->getType()); + const int vertexPdgCode(pReconstructedParticle.getType()); + + // Extract the kink vertex information + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + for (unsigned int iTrack = 0, nTracks = pReconstructedParticle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + //plcio::ConstTrack pTrack = trackVec.getTracks(iTrack); + plcio::ConstTrack pTrack = pReconstructedParticle.getTracks(iTrack); + //(0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + (0 == iTrack) ? m_parentTrackList.insert(pTrack.id()) : m_daughterTrackList.insert(pTrack.id()); + //std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.getTrackerHits().size() << std::endl; + std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.trackerHits_size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + if (0 == iTrack) + { + trackPdgCode = vertexPdgCode; + } + else + { + switch (vertexPdgCode) + { + case pandora::PI_PLUS : + case pandora::K_PLUS : + trackPdgCode = pandora::MU_PLUS; + break; + case pandora::PI_MINUS : + case pandora::K_MINUS : + trackPdgCode = pandora::MU_MINUS; + break; + case pandora::HYPERON_MINUS_BAR : + case pandora::SIGMA_PLUS : + trackPdgCode = pandora::PI_PLUS; + break; + case pandora::SIGMA_MINUS : + case pandora::HYPERON_MINUS : + trackPdgCode = pandora::PI_PLUS; + break; + default : + //(pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + (pTrack.getTrackStates(0).omega > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) ) ); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) ) ); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) )); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) )); + } + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_prongSplitVertexCollections.begin(), iterEnd = m_settings.m_prongSplitVertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pProngOrSplitCollection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pProngOrSplitCollection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pProngOrSplitCollection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the prong/split vertex information + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + (0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + streamlog_out(DEBUG) << "Prong or Split Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract prong/split vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract prong/split vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::ExtractV0s(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_v0VertexCollections.begin(), iterEnd = m_settings.m_v0VertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pV0Collection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pV0Collection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pV0Collection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the v0 vertex information + const int vertexPdgCode(pReconstructedParticle->getType()); + + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + m_v0TrackList.insert(pTrack); + streamlog_out(DEBUG) << "V0Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + switch (vertexPdgCode) + { + case pandora::PHOTON : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::E_PLUS : trackPdgCode = pandora::E_MINUS; + break; + case pandora::LAMBDA : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PROTON : trackPdgCode = pandora::PI_MINUS; + break; + case pandora::LAMBDA_BAR : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PROTON_BAR; + break; + case pandora::K_SHORT : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + default : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track sibling relationships + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract v0 vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract v0 vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const +{ + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + std::cout<<"Particle en="<<Particle.getEnergy()<<std::endl; + for (unsigned int iTrack = 0, nTracks = Particle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + edm4hep::ConstTrack pTrack = Particle.getTracks(iTrack) ; + unsigned int pTrack_id = pTrack.id() ; + + //if (this->IsDaughter(pTrack) || this->IsParent(pTrack) || this->IsV0(pTrack)) + if (this->IsDaughter(pTrack_id) || this->IsParent(pTrack_id) || this->IsV0(pTrack_id)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTracks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::CreateTracks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_trackCollections.begin(), iterEnd = m_settings.m_trackCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_Track.find(*iter) == collectionMaps.collectionMap_Track.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::Track>& pTrackCollection = (collectionMaps.collectionMap_Track.find(*iter))->second; + std::cout<<(*iter)<<" size="<<pTrackCollection.size()<<std::endl; + + for (int i = 0, iMax = pTrackCollection.size(); i < iMax; ++i) + { + try + { + const edm4hep::Track& pTrack0 = pTrackCollection.at(i); + const edm4hep::Track* pTrack = (const edm4hep::Track*)(&pTrack0); + + if (NULL == pTrack) throw ("Collection type mismatch"); + + int minTrackHits = m_settings.m_minTrackHits; + //const float tanLambda(std::fabs(pTrack->getTanLambda())); + //std::cout<<"track states size="<<pTrack->trackStates_size()<<std::endl; + const float tanLambda(std::fabs(pTrack->getTrackStates(0).tanLambda)); + + if (tanLambda > m_tanLambdaFtd) + { + int expectedFtdHits(0); + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((tanLambda > m_ftdZPositions[iFtdLayer] / m_ftdOuterRadii[iFtdLayer]) && + (tanLambda < m_ftdZPositions[iFtdLayer] / m_ftdInnerRadii[iFtdLayer])) + { + expectedFtdHits++; + } + } + + minTrackHits = std::max(m_settings.m_minFtdTrackHits, expectedFtdHits); + } + + const int nTrackHits(static_cast<int>(pTrack->trackerHits_size())); + + if ((nTrackHits < minTrackHits) || (nTrackHits > m_settings.m_maxTrackHits)) + continue; + + // Proceed to create the pandora track + PandoraApi::Track::Parameters trackParameters; + //trackParameters.m_d0 = pTrack->getD0(); + trackParameters.m_d0 = pTrack->getTrackStates(0).D0; + //trackParameters.m_z0 = pTrack->getZ0(); + trackParameters.m_z0 = pTrack->getTrackStates(0).Z0; + trackParameters.m_pParentAddress = pTrack; + // By default, assume tracks are charged pions + const float signedCurvature(pTrack->getTrackStates(0).omega); + trackParameters.m_particleId = (signedCurvature > 0) ? pandora::PI_PLUS : pandora::PI_MINUS; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass(pandora::PI_PLUS); + + // Use particle id information from V0 and Kink finders + TrackToPidMap::const_iterator iter_t = m_trackToPidMap.find(*pTrack); + + if(iter_t != m_trackToPidMap.end()) + { + trackParameters.m_particleId = (*iter_t).second; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass((*iter_t).second); + } + + if (std::numeric_limits<float>::epsilon() < std::fabs(signedCurvature)) + trackParameters.m_charge = static_cast<int>(signedCurvature / std::fabs(signedCurvature)); + + this->GetTrackStates(pTrack, trackParameters); + this->TrackReachesECAL(pTrack, trackParameters); + this->DefineTrackPfoUsage(pTrack, trackParameters); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Track::Create(*m_pPandora, trackParameters)); + m_trackVector.push_back(pTrack); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract a track: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "WARNNING Failed to extract a track "<< std::endl; + } + } + } + catch (...) + { + std::cout<<"WARNING Failed to extract track collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + //const TrackState *pTrackState = pTrack->getTrackState(TrackState::AtIP); + edm4hep::TrackState pTrackState = pTrack->getTrackStates(1); // ref /cvmfs/cepcsw.ihep.ac.cn/prototype/LCIO/include/EVENT/TrackState.h + + //if (!pTrackState) throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + //const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState->getOmega())); + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + //trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState->getPhi()), std::sin(pTrackState->getPhi()), pTrackState->getTanLambda()) * pt; + trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState.phi), std::sin(pTrackState.phi), pTrackState.tanLambda) * pt; + //this->CopyTrackState(pTrack->getTrackState(TrackState::AtFirstHit), trackParameters.m_trackStateAtStart); + this->CopyTrackState(pTrack->getTrackStates(2), trackParameters.m_trackStateAtStart); + + //fg: curling TPC tracks have pointers to track segments stored -> need to get track states from last segment! + //const EVENT::Track *pEndTrack = (pTrack->getTracks().empty() ? pTrack : pTrack->getTracks().back()); + auto pEndTrack = (pTrack->tracks_size() ==0 ) ? *pTrack : pTrack->getTracks(pTrack->tracks_size()-1); + + //std::cout<<"GetTrackStates 1.6"<<", end track trackStates_size()="<<pEndTrack.trackStates_size()<<std::endl; + + //this->CopyTrackState(pEndTrack->getTrackState(TrackState::AtLastHit), trackParameters.m_trackStateAtEnd); + //this->CopyTrackState(pEndTrack->getTrackState(TrackState::AtCalorimeter), trackParameters.m_trackStateAtCalorimeter); + + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtEnd); + //this->CopyTrackState(pEndTrack.getTrackStates(4), trackParameters.m_trackStateAtCalorimeter); + //FIXME ? LCIO input only has 4 states, so 4 can't be used. + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtCalorimeter); + + + trackParameters.m_isProjectedToEndCap = ((std::fabs(trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetZ()) < m_eCalEndCapInnerZ) ? false : true); + + // Convert generic time (length from reference point to intersection, divided by momentum) into nanoseconds + const float minGenericTime(this->CalculateTrackTimeAtCalorimeter(pTrack)); + const float particleMass(trackParameters.m_mass.Get()); + const float particleEnergy(std::sqrt(particleMass * particleMass + trackParameters.m_momentumAtDca.Get().GetMagnitudeSquared())); + trackParameters.m_timeAtCalorimeter = minGenericTime * particleEnergy / 299.792f; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float TrackCreator::CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const +{ + //const pandora::Helix helix(pTrack->getPhi(), pTrack->getD0(), pTrack->getZ0(), pTrack->getOmega(), pTrack->getTanLambda(), m_bField); + const pandora::Helix helix(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const pandora::CartesianVector &referencePoint(helix.GetReferencePoint()); + + // First project to endcap + float minGenericTime(std::numeric_limits<float>::max()); + + pandora::CartesianVector bestECalProjection(0.f, 0.f, 0.f); + const int signPz((helix.GetMomentum().GetZ() > 0.f) ? 1 : -1); + (void) helix.GetPointInZ(static_cast<float>(signPz) * m_eCalEndCapInnerZ, referencePoint, bestECalProjection, minGenericTime); + + // Then project to barrel surface(s) + pandora::CartesianVector barrelProjection(0.f, 0.f, 0.f); + if (m_eCalBarrelInnerSymmetry > 0) + { + // Polygon + float twopi_n = 2. * M_PI / (static_cast<float>(m_eCalBarrelInnerSymmetry)); + + for (int i = 0; i < m_eCalBarrelInnerSymmetry; ++i) + { + float genericTime(std::numeric_limits<float>::max()); + const float phi(twopi_n * static_cast<float>(i) + m_eCalBarrelInnerPhi0); + + const pandora::StatusCode statusCode(helix.GetPointInXY(m_eCalBarrelInnerR * std::cos(phi), m_eCalBarrelInnerR * std::sin(phi), + std::cos(phi + 0.5 * M_PI), std::sin(phi + 0.5 * M_PI), referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + } + else + { + // Cylinder + float genericTime(std::numeric_limits<float>::max()); + const pandora::StatusCode statusCode(helix.GetPointOnCircle(m_eCalBarrelInnerR, referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + + if (bestECalProjection.GetMagnitudeSquared() < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return minGenericTime; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const +{ + //if (!pTrackState) throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + //const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState->getOmega())); + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + + //const double px(pt * std::cos(pTrackState->getPhi())); + const double px(pt * std::cos(pTrackState.phi)); + //const double py(pt * std::sin(pTrackState->getPhi())); + const double py(pt * std::sin(pTrackState.phi)); + //const double pz(pt * pTrackState->getTanLambda()); + const double pz(pt * pTrackState.tanLambda); + + const double xs(pTrackState.referencePoint[0]); + const double ys(pTrackState.referencePoint[1]); + const double zs(pTrackState.referencePoint[2]); + + inputTrackState = pandora::TrackState(xs, ys, zs, px, py, pz); +} + + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + + // Calculate hit position information + float hitZMin(std::numeric_limits<float>::max()); + float hitZMax(-std::numeric_limits<float>::max()); + float hitOuterR(-std::numeric_limits<float>::max()); + + int maxOccupiedFtdLayer=0; + + + const unsigned int nTrackHits(pTrack->trackerHits_size()); + for (unsigned int i = 0; i < nTrackHits; ++i) + { + + const edm4hep::ConstTrackerHit Hit ( pTrack->getTrackerHits(i) ); + const edm4hep::Vector3d pos = Hit.getPosition(); + + float x = float(pos[0]); + float y = float(pos[1]); + float z = float(pos[2]); + float r = std::sqrt(x * x + y * y); + + if (z > hitZMax) hitZMax = z; + + if (z < hitZMin) hitZMin = z; + + if (r > hitOuterR) hitOuterR = r; + + if ((r > m_tpcInnerR) && (r < m_tpcOuterR) && (std::fabs(z) <= m_tpcZmax)) continue; + + for (unsigned int j = 0; j < m_nFtdLayers; ++j) + { + if ((r > m_ftdInnerRadii[j]) && (r < m_ftdOuterRadii[j]) && + (std::fabs(z) - m_settings.m_reachesECalFtdZMaxDistance < m_ftdZPositions[j]) && + (std::fabs(z) + m_settings.m_reachesECalFtdZMaxDistance > m_ftdZPositions[j])) + { + //if (static_cast<int>(j) > maxOccupiedFtdLayer) maxOccupiedFtdLayer = static_cast<int>(j); + if ( j > maxOccupiedFtdLayer) maxOccupiedFtdLayer = j; + break; + } + } + } + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + // Look to see if there are hits in etd or set, implying track has reached edge of ecal + if ((hitOuterR > m_minSetRadius) || (hitZMax > m_minEtdZPosition)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + // Require sufficient hits in tpc or ftd, then compare extremal hit positions with tracker dimensions + if ((nTpcHits >= m_settings.m_reachesECalNTpcHits) || (nFtdHits >= m_settings.m_reachesECalNFtdHits)) + { + if ((hitOuterR - m_tpcOuterR > m_settings.m_reachesECalTpcOuterDistance) || + (std::fabs(hitZMax) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (std::fabs(hitZMin) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (maxOccupiedFtdLayer >= m_settings.m_reachesECalMinFtdLayer)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + } + + // If track is lowpt, it may curl up and end inside tpc inner radius + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float cosAngleAtDca(std::fabs(momentumAtDca.GetZ()) / momentumAtDca.GetMagnitude()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + if ((cosAngleAtDca > m_cosTpc) || (pT < m_settings.m_curvatureToMomentumFactor * m_bField * m_tpcOuterR)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + trackParameters.m_reachesCalorimeter = false; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + bool canFormPfo(false); + bool canFormClusterlessPfo(false); + + //if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack)) + if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack->id())) + { + //const float d0(std::fabs(pTrack->getD0())), z0(std::fabs(pTrack->getZ0())); + const float d0(std::fabs(pTrack->getTrackStates(0).D0)), z0(std::fabs(pTrack->getTrackStates(0).Z0)); + + //EVENT::TrackerHitVec trackerHitvec(pTrack->getTrackerHits()); + float rInner(std::numeric_limits<float>::max()), zMin(std::numeric_limits<float>::max()); + + //for (EVENT::TrackerHitVec::const_iterator iter = trackerHitvec.begin(), iterEnd = trackerHitvec.end(); iter != iterEnd; ++iter) + for (std::vector<edm4hep::ConstTrackerHit>::const_iterator iter = pTrack->trackerHits_begin(), iterEnd = pTrack->trackerHits_end(); iter != iterEnd; ++iter) + { + //const double *pPosition((*iter)->getPosition()); + const edm4hep::Vector3d pPosition = (*iter).getPosition(); + const float x(pPosition[0]), y(pPosition[1]), absoluteZ(std::fabs(pPosition[2])); + const float r(std::sqrt(x * x + y * y)); + + if (r < rInner) + rInner = r; + + if (absoluteZ < zMin) + zMin = absoluteZ; + } + + if (this->PassesQualityCuts(pTrack, trackParameters)) + { + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()), pZ(momentumAtDca.GetZ()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + const float zCutForNonVertexTracks(m_tpcInnerR * std::fabs(pZ / pT) + m_settings.m_zCutForNonVertexTracks); + const bool passRzQualityCuts((zMin < zCutForNonVertexTracks) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)); + + const bool isV0(this->IsV0(pTrack->id())); + const bool isDaughter(this->IsDaughter(pTrack->id())); + + // Decide whether track can be associated with a pandora cluster and used to form a charged PFO + if ((d0 < m_settings.m_d0TrackCut) && (z0 < m_settings.m_z0TrackCut) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks)) + { + canFormPfo = true; + } + else if (isV0 || isDaughter) + { + canFormPfo = true; + } + + // Decide whether track can be used to form a charged PFO, even if track fails to be associated with a pandora cluster + const float particleMass(trackParameters.m_mass.Get()); + const float trackEnergy(std::sqrt(momentumAtDca.GetMagnitudeSquared() + particleMass * particleMass)); + + if ((0 != m_settings.m_usingUnmatchedVertexTracks) && (trackEnergy < m_settings.m_unmatchedVertexTrackMaxEnergy)) + { + if ((d0 < m_settings.m_d0UnmatchedVertexTrackCut) && (z0 < m_settings.m_z0UnmatchedVertexTrackCut) && + (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormClusterlessPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks) && (0 != m_settings.m_usingUnmatchedNonVertexTracks)) + { + canFormClusterlessPfo = true; + } + else if (isV0 || isDaughter) + { + canFormClusterlessPfo = true; + } + } + } + else if (this->IsDaughter(pTrack->id()) || this->IsV0(pTrack->id())) + { + std::cout<<"WARNING Recovering daughter or v0 track " << trackParameters.m_momentumAtDca.Get().GetMagnitude() << std::endl; + canFormPfo = true; + } + } + + trackParameters.m_canFormPfo = canFormPfo; + trackParameters.m_canFormClusterlessPfo = canFormClusterlessPfo; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const +{ + // First simple sanity checks + if (trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetMagnitude() < m_settings.m_minTrackECalDistanceFromIp) + return false; + + //if (std::fabs(pTrack->getOmega()) < std::numeric_limits<float>::epsilon()) + if (std::fabs(pTrack->getTrackStates(0).omega) < std::numeric_limits<float>::epsilon()) + { + std::cout<<"ERROR Track has Omega = 0 " << std::endl; + return false; + } + + // Check momentum uncertainty is reasonable to use track + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + //const float sigmaPOverP(std::sqrt(pTrack->getCovMatrix()[5]) / std::fabs(pTrack->getOmega())); + const float sigmaPOverP(std::sqrt(pTrack->getTrackStates(0).covMatrix[5]) / std::fabs(pTrack->getTrackStates(0).omega)); + + if (sigmaPOverP > m_settings.m_maxTrackSigmaPOverP) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << "+-" << sigmaPOverP * (momentumAtDca.GetMagnitude()) + << " chi2 = " << pTrack->getChi2() << " " << pTrack->getNdf() + << " from " << pTrack->trackerHits_size() << std::endl; + return false; + } + + // Require reasonable number of TPC hits + if (momentumAtDca.GetMagnitude() > m_settings.m_minMomentumForTrackHitChecks) + { + const float pX(fabs(momentumAtDca.GetX())); + const float pY(fabs(momentumAtDca.GetY())); + const float pZ(fabs(momentumAtDca.GetZ())); + const float pT(std::sqrt(pX * pX + pY * pY)); + const float rInnermostHit(pTrack->getRadiusOfInnermostHit()); + + if ((std::numeric_limits<float>::epsilon() > std::fabs(pT)) || (std::numeric_limits<float>::epsilon() > std::fabs(pZ)) || (rInnermostHit == m_tpcOuterR)) + { + std::cout<<"ERROR Invalid track parameter, pT " << pT << ", pZ " << pZ << ", rInnermostHit " << rInnermostHit << std::endl; + return false; + } + + float nExpectedTpcHits(0.); + + if (pZ < m_tpcZmax / m_tpcOuterR * pT) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcOuterR - innerExpectedHitRadius) / (m_tpcOuterR - m_tpcInnerR)); + nExpectedTpcHits = m_tpcMaxRow * frac; + } + + if ((pZ <= m_tpcZmax / m_tpcInnerR * pT) && (pZ >= m_tpcZmax / m_tpcOuterR * pT)) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcZmax * pT / pZ - innerExpectedHitRadius) / (m_tpcOuterR - innerExpectedHitRadius)); + nExpectedTpcHits = frac * m_tpcMaxRow; + } + + // TODO Get TPC membrane information from GEAR when available + if (std::fabs(pZ) / momentumAtDca.GetMagnitude() < m_settings.m_tpcMembraneMaxZ / m_tpcInnerR) + nExpectedTpcHits = 0; + + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + const int minTpcHits = static_cast<int>(nExpectedTpcHits * m_settings.m_minTpcHitFractionOfExpected); + + if ((nTpcHits < minTpcHits) && (nFtdHits < m_settings.m_minFtdHitsForTpcHitFraction)) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << " Number of TPC hits = " << nTpcHits + << " < " << minTpcHits << " nftd = " << nFtdHits << std::endl; + return false; + } + } + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNTpcHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - 1 ]; + return pTrack->getSubDetectorHitNumbers(2 * lcio::ILDDetID::TPC - 1);// still use LCIO code now +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNFtdHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - 1 ]; + return pTrack->getSubDetectorHitNumbers( 2 * lcio::ILDDetID::FTD - 1 ); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::Settings::Settings() : + m_shouldFormTrackRelationships(1), + m_minTrackHits(5), + m_minFtdTrackHits(0), + m_maxTrackHits(5000.f), + m_d0TrackCut(50.f), + m_z0TrackCut(50.f), + m_usingNonVertexTracks(1), + m_usingUnmatchedNonVertexTracks(0), + m_usingUnmatchedVertexTracks(1), + m_unmatchedVertexTrackMaxEnergy(5.f), + m_d0UnmatchedVertexTrackCut(5.f), + m_z0UnmatchedVertexTrackCut(5.f), + m_zCutForNonVertexTracks(250.f), + m_reachesECalNTpcHits(11), + m_reachesECalNFtdHits(4), + m_reachesECalTpcOuterDistance(-100.f), + m_reachesECalMinFtdLayer(9), + m_reachesECalTpcZMaxDistance(-50.f), + m_reachesECalFtdZMaxDistance(1.f), + m_curvatureToMomentumFactor(0.3f / 2000.f), + m_minTrackECalDistanceFromIp(100.f), + m_maxTrackSigmaPOverP(0.15f), + m_minMomentumForTrackHitChecks(1.f), + m_tpcMembraneMaxZ(10.f), + m_maxTpcInnerRDistance(50.f), + m_minTpcHitFractionOfExpected(0.2f), + m_minFtdHitsForTpcHitFraction(2) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp new file mode 100644 index 00000000..819fa15d --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp @@ -0,0 +1,7 @@ +#include "Utility.h" + +std::string Convert (float number){ + std::ostringstream buff; + buff<<number; + return buff.str(); +} -- GitLab