From 2db586a17f771cf430984b175c8179a5c9ff4ec5 Mon Sep 17 00:00:00 2001 From: "guofangyi@ihep.ac.cn" <guofangyi@ihep.ac.cn> Date: Mon, 2 Dec 2024 07:26:09 +0000 Subject: [PATCH] Update CyberPFA --- Analysis/CMakeLists.txt | 1 + Analysis/GenMatch/CMakeLists.txt | 22 + Analysis/GenMatch/jcls_genmatch.py | 44 + Analysis/GenMatch/src/GenMatch.cpp | 708 ++++++++++ Analysis/GenMatch/src/GenMatch.h | 103 ++ Detector/DetCRD/CMakeLists.txt | 7 + .../Ecal_Crystal_Endcap_v01_02.xml | 61 + .../DetCRD/compact/TDR_o1_v01/TDR_o1_v01.xml | 2 +- .../DetCRD/scripts/TDR_o1_v01/calodigi.py | 113 +- Detector/DetCRD/scripts/TDR_o1_v01/rec.py | 167 +++ .../LongCrystalBarEndcapCalorimeter_v02.cpp | 598 +++++++++ Digitization/DigiCalo/CMakeLists.txt | 1 + Digitization/DigiCalo/src/CaloBar.h | 7 +- Digitization/DigiCalo/src/CaloCrystalShort.h | 89 ++ Digitization/DigiCalo/src/EcalDigiAlg.cpp | 1167 +++++++++++------ Digitization/DigiCalo/src/EcalDigiAlg.h | 135 +- .../DigiCalo/src/EcalDigiAlgShort.cpp | 535 ++++++++ Digitization/DigiCalo/src/EcalDigiAlgShort.h | 137 ++ Digitization/DigiCalo/src/HcalDigiAlg.cpp | 531 +++++--- Digitization/DigiCalo/src/HcalDigiAlg.h | 95 +- Reconstruction/RecPFACyber/CMakeLists.txt | 2 + .../RecPFACyber/include/CyberPFAlg.h | 20 +- .../include/Objects/Calo2DCluster.h | 5 +- .../include/Objects/Calo3DCluster.h | 3 + .../RecPFACyber/include/Objects/CaloUnit.h | 3 +- .../RecPFACyber/include/Objects/HoughObject.h | 4 +- .../include/Tools/CaloHitsCreator.h | 3 +- .../RecPFACyber/include/Tools/TrackCreator.h | 7 + Reconstruction/RecPFACyber/script/ana.py | 43 + Reconstruction/RecPFACyber/script/digi.py | 121 +- Reconstruction/RecPFACyber/script/rec.py | 33 +- .../RecPFACyber/script/roofit_jets.cpp | 229 ++++ Reconstruction/RecPFACyber/script/sim.py | 9 +- Reconstruction/RecPFACyber/script/tracking.py | 44 +- .../src/Algorithm/PFOReclusteringAlg.cpp | 360 ++--- .../Algorithm/TrackClusterConnectingAlg.cpp | 20 +- Reconstruction/RecPFACyber/src/CyberPFAlg.cpp | 66 +- .../RecPFACyber/src/Objects/Calo1DCluster.cc | 7 +- .../RecPFACyber/src/Objects/Calo2DCluster.cc | 4 +- .../RecPFACyber/src/Objects/Calo3DCluster.cc | 6 +- .../RecPFACyber/src/Objects/CaloUnit.cc | 2 +- .../RecPFACyber/src/Tools/CaloHitsCreator.cpp | 158 ++- .../RecPFACyber/src/Tools/OutputCreator.cpp | 46 +- .../RecPFACyber/src/Tools/TrackCreator.cpp | 146 ++- 44 files changed, 4866 insertions(+), 998 deletions(-) create mode 100644 Analysis/GenMatch/CMakeLists.txt create mode 100644 Analysis/GenMatch/jcls_genmatch.py create mode 100644 Analysis/GenMatch/src/GenMatch.cpp create mode 100644 Analysis/GenMatch/src/GenMatch.h create mode 100755 Detector/DetCRD/compact/CRD_common_v01/Ecal_Crystal_Endcap_v01_02.xml create mode 100644 Detector/DetCRD/scripts/TDR_o1_v01/rec.py create mode 100755 Detector/DetCRD/src/Calorimeter/LongCrystalBarEndcapCalorimeter_v02.cpp create mode 100644 Digitization/DigiCalo/src/CaloCrystalShort.h create mode 100644 Digitization/DigiCalo/src/EcalDigiAlgShort.cpp create mode 100644 Digitization/DigiCalo/src/EcalDigiAlgShort.h create mode 100644 Reconstruction/RecPFACyber/script/ana.py create mode 100644 Reconstruction/RecPFACyber/script/roofit_jets.cpp diff --git a/Analysis/CMakeLists.txt b/Analysis/CMakeLists.txt index 49735726..6fc2f919 100644 --- a/Analysis/CMakeLists.txt +++ b/Analysis/CMakeLists.txt @@ -4,3 +4,4 @@ add_subdirectory(TrackInspect) add_subdirectory(DumpEvent) add_subdirectory(ReadDigi) add_subdirectory(JetClustering) +add_subdirectory(GenMatch) diff --git a/Analysis/GenMatch/CMakeLists.txt b/Analysis/GenMatch/CMakeLists.txt new file mode 100644 index 00000000..ad3b745f --- /dev/null +++ b/Analysis/GenMatch/CMakeLists.txt @@ -0,0 +1,22 @@ +# Set the CMake module path if necessary + + +# Modules +gaudi_add_module(GenMatch + SOURCES src/GenMatch.cpp + LINK GearSvc + Gaudi::GaudiKernel + k4FWCore::k4FWCore + DetInterface + DataHelperLib + ${GEAR_LIBRARIES} + ${GSL_LIBRARIES} + ${ROOT_LIBRARIES} + ${FASTJET_LIBRARY} + EDM4HEP::edm4hep EDM4HEP::edm4hepDict +) +install(TARGETS GenMatch + EXPORT CEPCSWTargets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib + COMPONENT dev) diff --git a/Analysis/GenMatch/jcls_genmatch.py b/Analysis/GenMatch/jcls_genmatch.py new file mode 100644 index 00000000..5229515e --- /dev/null +++ b/Analysis/GenMatch/jcls_genmatch.py @@ -0,0 +1,44 @@ +import os, sys +from Gaudi.Configuration import * + +########### k4DataSvc #################### +from Configurables import k4DataSvc +#podioevent = k4DataSvc("EventDataSvc", input="./FullSim_Samples/nnHgg/Rec_TDR_o1_v01_E240_nnh_gg_test_003.root") +podioevent = k4DataSvc("EventDataSvc", input="/publicfs/cms/user/wangzebing/CEPC/CEPCSW_tdr24.9.1/CEPCSW/FullSim_samples/Rec_TDR_o1_v01_E240_nnh_gg.root") +########################################## + +########## CEPCSWData ################# +cepcswdatatop ="/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/data/latest" +####################################### + + +########## Podio Input ################### +from Configurables import PodioInput +inp = PodioInput("InputReader") +inp.collections = [ "CyberPFO", "MCParticle" ] +########################################## + + + +from Configurables import GenMatch +genmatch = GenMatch("GenMatch") +genmatch.nJets = 2 +genmatch.R = 0.6 +genmatch.OutputFile = "./RecJets_TDR_o1_v01_E240_nnh_gg.root" +#genmatch.OutputFile = "./FullSim_samples/RecJets_TDR_o1_v01_E240_nnh_gg_CalHits.root" + +############################################################################## +# POD I/O +############################################################################## + + +######################################## + +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg=[inp, genmatch ], + EvtSel="NONE", + EvtMax=3, + ExtSvc=[podioevent], + #OutputLevel=DEBUG +) diff --git a/Analysis/GenMatch/src/GenMatch.cpp b/Analysis/GenMatch/src/GenMatch.cpp new file mode 100644 index 00000000..a2d45125 --- /dev/null +++ b/Analysis/GenMatch/src/GenMatch.cpp @@ -0,0 +1,708 @@ +#include "GenMatch.h" + +#include "GaudiKernel/DataObject.h" +#include "GaudiKernel/IHistogramSvc.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/SmartDataPtr.h" + +#include "DetInterface/IGeomSvc.h" +#include "DD4hep/Detector.h" +#include "DD4hep/DD4hepUnits.h" +#include "CLHEP/Units/SystemOfUnits.h" +#include <math.h> +#include "fastjet/ClusterSequence.hh" +#include "fastjet/PseudoJet.hh" +//time measurement +#include <chrono> + +#include "TLorentzVector.h" + +using namespace fastjet; +using namespace std; + +DECLARE_COMPONENT( GenMatch ) + +//------------------------------------------------------------------------------ +GenMatch::GenMatch( const string& name, ISvcLocator* pSvcLocator ) + : Algorithm( name, pSvcLocator ) { + + declareProperty("InputPFOs", m_PFOColHdl, "Handle of the Input PFO collection"); + declareProperty("InputGEN", m_MCParticleGenHdl, "Handle of the Input GEN collection"); + //declareProperty("Algorithm", m_algo, "Jet clustering algorithm"); + //declareProperty("nJets", m_nJets, "Number of jets to be clustered"); + //declareProperty("R", m_R, "Jet clustering radius"); + //declareProperty("OutputFile", m_outputFile, "Output file name"); + +} + +//------------------------------------------------------------------------------ +StatusCode GenMatch::initialize(){ + + _nEvt = 0; + + // Create a new TTree + _file = TFile::Open(m_outputFile.value().c_str(), "RECREATE"); + _tree = new TTree("jets", "jets"); + + _tree->Branch("jet1_px", &jet1_px, "jet1_px/D"); + _tree->Branch("jet1_py", &jet1_py, "jet1_py/D"); + _tree->Branch("jet1_pz", &jet1_pz, "jet1_pz/D"); + _tree->Branch("jet1_E", &jet1_E, "jet1_E/D"); + _tree->Branch("jet1_costheta", &jet1_costheta, "jet1_costheta/D"); + _tree->Branch("jet1_phi", &jet1_phi, "jet1_phi/D"); + _tree->Branch("jet1_pt", &jet1_pt, "jet1_pt/D"); + _tree->Branch("jet1_nconstituents", &jet1_nconstituents, "jet1_nconstituents/I"); + _tree->Branch("jet2_px", &jet2_px, "jet2_px/D"); + _tree->Branch("jet2_py", &jet2_py, "jet2_py/D"); + _tree->Branch("jet2_pz", &jet2_pz, "jet2_pz/D"); + _tree->Branch("jet2_E", &jet2_E, "jet2_E/D"); + _tree->Branch("jet2_costheta", &jet2_costheta, "jet2_costheta/D"); + _tree->Branch("jet2_phi", &jet2_phi, "jet2_phi/D"); + _tree->Branch("jet2_pt", &jet2_pt, "jet2_pt/D"); + _tree->Branch("jet2_nconstituents", &jet2_nconstituents, "jet2_nconstituents/I"); + _tree->Branch("constituents_E1tot", &constituents_E1tot, "constituents_E1tot/D"); + _tree->Branch("constituents_E2tot", &constituents_E2tot, "constituents_E2tot/D"); + _tree->Branch("mass", &mass, "mass/D"); + _tree->Branch("ymerge", ymerge, "ymerge[6]/D"); + _tree->Branch("nparticles", &nparticles, "nparticles/I"); + _tree->Branch("jet1_GENMatch_id", &jet1_GENMatch_id, "jet1_GENMatch_id/I"); + _tree->Branch("jet2_GENMatch_id", &jet2_GENMatch_id, "jet2_GENMatch_id/I"); + _tree->Branch("jet1_GENMatch_mindR", &jet1_GENMatch_mindR, "jet1_GENMatch_mindR/D"); + _tree->Branch("jet2_GENMatch_mindR", &jet2_GENMatch_mindR, "jet2_GENMatch_mindR/D"); + + _tree->Branch("PFO_Energy_muon", &PFO_Energy_muon); + _tree->Branch("PFO_Energy_muon_GENMatch_dR", &PFO_Energy_muon_GENMatch_dR); + _tree->Branch("PFO_Energy_muon_GENMatch_ID", &PFO_Energy_muon_GENMatch_ID); + _tree->Branch("PFO_Energy_muon_GENMatch_E", &PFO_Energy_muon_GENMatch_E); + _tree->Branch("PFO_Energy_Charge", &PFO_Energy_Charge); + _tree->Branch("PFO_Energy_Charge_Ecal", &PFO_Energy_Charge_Ecal); + _tree->Branch("PFO_Energy_Charge_Hcal", &PFO_Energy_Charge_Hcal); + _tree->Branch("PFO_Energy_Charge_GENMatch_dR", &PFO_Energy_Charge_GENMatch_dR); + _tree->Branch("PFO_Energy_Charge_GENMatch_ID", &PFO_Energy_Charge_GENMatch_ID); + _tree->Branch("PFO_Energy_Charge_GENMatch_E", &PFO_Energy_Charge_GENMatch_E); + _tree->Branch("PFO_Hits_Charge_E", &PFO_Hits_Charge_E); + _tree->Branch("PFO_Hits_Charge_R", &PFO_Hits_Charge_R); + _tree->Branch("PFO_Hits_Charge_theta", &PFO_Hits_Charge_theta); + _tree->Branch("PFO_Hits_Charge_phi", &PFO_Hits_Charge_phi); + + _tree->Branch("PFO_Energy_Neutral", &PFO_Energy_Neutral); + _tree->Branch("PFO_Energy_Neutral_singleCluster", &PFO_Energy_Neutral_singleCluster); + _tree->Branch("PFO_Energy_Neutral_singleCluster_R", &PFO_Energy_Neutral_singleCluster_R); + _tree->Branch("PFO_Hits_Neutral_E", &PFO_Hits_Neutral_E); + _tree->Branch("PFO_Hits_Neutral_R", &PFO_Hits_Neutral_R); + _tree->Branch("PFO_Hits_Neutral_theta", &PFO_Hits_Neutral_theta); + _tree->Branch("PFO_Hits_Neutral_phi", &PFO_Hits_Neutral_phi); + + _tree->Branch("GEN_PFO_Energy_muon", &GEN_PFO_Energy_muon); + _tree->Branch("GEN_PFO_Energy_pipm", &GEN_PFO_Energy_pipm); + _tree->Branch("GEN_PFO_Energy_pi0", &GEN_PFO_Energy_pi0); + _tree->Branch("GEN_PFO_Energy_ppm", &GEN_PFO_Energy_ppm); + _tree->Branch("GEN_PFO_Energy_kpm", &GEN_PFO_Energy_kpm); + _tree->Branch("GEN_PFO_Energy_kL", &GEN_PFO_Energy_kL); + _tree->Branch("GEN_PFO_Energy_gamma", &GEN_PFO_Energy_gamma); + _tree->Branch("GEN_PFO_Energy_n", &GEN_PFO_Energy_n); + _tree->Branch("GEN_PFO_Energy_e", &GEN_PFO_Energy_e); + + + _tree->Branch("particle_index_muon", &particle_index_muon, "particle_index_muon/I"); + _tree->Branch("particle_index_Charge", &particle_index_Charge, "particle_index_Charge/I"); + _tree->Branch("particle_index_Neutral", &particle_index_Neutral, "particle_index_Neutral/I"); + _tree->Branch("particle_index_Neutral_singleCluster", &particle_index_Neutral_singleCluster, "particle_index_Neutral_singleCluster/I"); + + _tree->Branch("GEN_particle_gamma_index", &GEN_particle_gamma_index, "GEN_particle_gamma_index/I"); + _tree->Branch("GEN_particle_pipm_index", &GEN_particle_pipm_index, "GEN_particle_pipm_index/I"); + _tree->Branch("GEN_particle_pi0_index", &GEN_particle_pi0_index, "GEN_particle_pi0_index/I"); + _tree->Branch("GEN_particle_ppm_index", &GEN_particle_ppm_index, "GEN_particle_ppm_index/I"); + _tree->Branch("GEN_particle_kpm_index", &GEN_particle_kpm_index, "GEN_particle_kpm_index/I"); + _tree->Branch("GEN_particle_kL_index", &GEN_particle_kL_index, "GEN_particle_kL_index/I"); + _tree->Branch("GEN_particle_n_index", &GEN_particle_n_index, "GEN_particle_n_index/I"); + _tree->Branch("GEN_particle_e_index", &GEN_particle_e_index, "GEN_particle_e_index/I"); + + _tree->Branch("ymerge_gen", ymerge_gen, "ymerge_gen[6]/D"); + + _tree->Branch("mass_gen_match", &mass_gen_match, "mass_gen_match/D"); + _tree->Branch("GEN_jet1_px", &GEN_jet1_px, "GEN_jet1_px/D"); + _tree->Branch("GEN_jet1_py", &GEN_jet1_py, "GEN_jet1_py/D"); + _tree->Branch("GEN_jet1_pz", &GEN_jet1_pz, "GEN_jet1_pz/D"); + _tree->Branch("GEN_jet1_E", &GEN_jet1_E, "GEN_jet1_E/D"); + _tree->Branch("GEN_jet1_costheta", &GEN_jet1_costheta, "GEN_jet1_costheta/D"); + _tree->Branch("GEN_jet1_phi", &GEN_jet1_phi, "GEN_jet1_phi/D"); + _tree->Branch("GEN_jet1_pt", &GEN_jet1_pt, "GEN_jet1_pt/D"); + _tree->Branch("GEN_jet1_nconstituents", &GEN_jet1_nconstituents, "GEN_jet1_nconstituents/I"); + _tree->Branch("GEN_jet2_px", &GEN_jet2_px, "GEN_jet2_px/D"); + _tree->Branch("GEN_jet2_py", &GEN_jet2_py, "GEN_jet2_py/D"); + _tree->Branch("GEN_jet2_pz", &GEN_jet2_pz, "GEN_jet2_pz/D"); + _tree->Branch("GEN_jet2_E", &GEN_jet2_E, "GEN_jet2_E/D"); + _tree->Branch("GEN_jet2_costheta", &GEN_jet2_costheta, "GEN_jet2_costheta/D"); + _tree->Branch("GEN_jet2_phi", &GEN_jet2_phi, "GEN_jet2_phi/D"); + _tree->Branch("GEN_jet2_pt", &GEN_jet2_pt, "GEN_jet2_pt/D"); + _tree->Branch("GEN_jet2_nconstituents", &GEN_jet2_nconstituents, "GEN_jet2_nconstituents/I"); + _tree->Branch("GEN_ISR_E", &GEN_ISR_E, "GEN_ISR_E/D"); + _tree->Branch("GEN_ISR_pt", &GEN_ISR_pt, "GEN_ISR_pt/D"); + _tree->Branch("GEN_inv_E", &GEN_inv_E, "GEN_inv_E/D"); + _tree->Branch("GEN_inv_pt", &GEN_inv_pt, "GEN_inv_pt/D"); + _tree->Branch("GEN_constituents_E1tot", &GEN_constituents_E1tot, "GEN_constituents_E1tot/D"); + _tree->Branch("GEN_constituents_E2tot", &GEN_constituents_E2tot, "GEN_constituents_E2tot/D"); + _tree->Branch("GEN_mass", &GEN_mass, "GEN_mass/D"); + _tree->Branch("barrelRatio", &barrelRatio, "barrelRatio/D"); + _tree->Branch("mass_allParticles", &mass_allParticles, "mass_allParticles/D"); + _tree->Branch("GEN_nparticles", &GEN_nparticles, "GEN_nparticles/I"); + + return StatusCode::SUCCESS; + +} + +//------------------------------------------------------------------------------ +StatusCode GenMatch::execute(){ + + const edm4hep::ReconstructedParticleCollection* PFO = nullptr; + try { + PFO = m_PFOColHdl.get(); + } + catch ( GaudiException &e ){ + info() << "Collection " << m_PFOColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + return StatusCode::SUCCESS; + } + // Check if the collection is empty + if ( PFO->size() == 0 ) { + info() << "Collection " << m_PFOColHdl.fullKey() << " is empty in event " << _nEvt << endmsg; + return StatusCode::SUCCESS; + } + + const edm4hep::MCParticleCollection* MCParticlesGen = nullptr; + try { + MCParticlesGen = m_MCParticleGenHdl.get(); + } + catch ( GaudiException &e ){ + info() << "Collection " << m_MCParticleGenHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + return StatusCode::SUCCESS; + } + // Check if the collection is empty + if ( MCParticlesGen->size() == 0 ) { + info() << "Collection " << m_MCParticleGenHdl.fullKey() << " is empty in event " << _nEvt << endmsg; + return StatusCode::SUCCESS; + } + //initial indces + CleanVars(); + + //resize particles. there are many particles are empty, maybe upstream bugs + vector<PseudoJet> input_particles; + TLorentzVector input_particles_sum; + for(const auto& pfo : *PFO){ + if ( isnan(pfo.getMomentum()[0]) || isnan(pfo.getMomentum()[1]) || isnan(pfo.getMomentum()[2]) || pfo.getEnergy() == 0) { + info() << "Particle " << _particle_index << " px: " << pfo.getMomentum()[0] << " py: " << pfo.getMomentum()[1] << " pz: " << pfo.getMomentum()[2] << " E: " << pfo.getEnergy() << endmsg; + _particle_index++; + continue; + } + else{ + input_particles.push_back(PseudoJet(pfo.getMomentum()[0], pfo.getMomentum()[1], pfo.getMomentum()[2], pfo.getEnergy())); + _particle_index++; + _nparticles++; + TLorentzVector p4_pfo; + p4_pfo.SetPxPyPzE(pfo.getMomentum()[0], pfo.getMomentum()[1], pfo.getMomentum()[2], pfo.getEnergy()); + input_particles_sum += p4_pfo; + //std::cout << "Particle " << _particle_index << " px: "<<pfo.getMomentum()[0]<<" py: "<<pfo.getMomentum()[1]<<" pz: "<<pfo.getMomentum()[2]<<" E: "<<pfo.getEnergy() << ", mass "<< pfo.getMass() << std::endl; + + if (abs(pfo.getCharge()) > 0 && pfo.clusters_size() == 0){ + //PFO_Energy_muon[_particle_index_muon] = pfo.getEnergy(); + //_particle_index_muon++; + PFO_Energy_muon.push_back(pfo.getEnergy()); + + float mini_dR = 99.0; + float dR_temp = 99.0; + float deta = 99.0; + float dphi = 99.0; + int PFO_Energy_muon_GENMatch_ID_temp = -999; + float PFO_Energy_muon_GENMatch_E_temp = -999; + for(const auto& Gen : *MCParticlesGen){ + if (Gen.getGeneratorStatus() != 1) continue; + if ( abs(Gen.getPDG())==12 || abs(Gen.getPDG())==14 || abs(Gen.getPDG())==16 ) continue; + TLorentzVector p4_gen; + p4_gen.SetPxPyPzE(Gen.getMomentum()[0], Gen.getMomentum()[1], Gen.getMomentum()[2], Gen.getEnergy()); + deta = p4_pfo.Eta() - p4_gen.Eta(); + dphi = TVector2::Phi_mpi_pi(p4_pfo.Phi() - p4_gen.Phi()); + dR_temp = TMath::Sqrt(deta*deta + dphi*dphi); + if (dR_temp < mini_dR){ + mini_dR = dR_temp; + PFO_Energy_muon_GENMatch_ID_temp = Gen.getPDG(); + PFO_Energy_muon_GENMatch_E_temp = Gen.getEnergy(); + } + } + PFO_Energy_muon_GENMatch_dR.push_back(mini_dR); + PFO_Energy_muon_GENMatch_ID.push_back(PFO_Energy_muon_GENMatch_ID_temp); + PFO_Energy_muon_GENMatch_E.push_back(PFO_Energy_muon_GENMatch_E_temp); + + } + else if (abs(pfo.getCharge()) > 0 && pfo.clusters_size() > 0){ + //PFO_Energy_Charge[_particle_index_Charge] = pfo.getEnergy(); + //_particle_index_Charge++; + PFO_Energy_Charge.push_back(pfo.getEnergy()); + + float PFO_Energy_Charge_Ecal_temp = 0; + float PFO_Energy_Charge_Hcal_temp = 0; + int PFO_Energy_Charge_GENMatch_ID_temp = -999; + float PFO_Energy_Charge_GENMatch_E_temp = -999; + for (unsigned i = 0; i < pfo.clusters_size(); i++){ + if (TMath::Sqrt(pfo.getClusters(i).getPosition().x * pfo.getClusters(i).getPosition().x + pfo.getClusters(i).getPosition().y * pfo.getClusters(i).getPosition().y) < 2130){ + PFO_Energy_Charge_Ecal_temp += pfo.getClusters(i).getEnergy(); + }else{ + PFO_Energy_Charge_Hcal_temp += pfo.getClusters(i).getEnergy(); + } + } + + PFO_Energy_Charge_Ecal.push_back(PFO_Energy_Charge_Ecal_temp); + PFO_Energy_Charge_Hcal.push_back(PFO_Energy_Charge_Hcal_temp); + + float mini_dR = 99.0; + float dR_temp = 99.0; + float deta = 99.0; + float dphi = 99.0; + for(const auto& Gen : *MCParticlesGen){ + if (Gen.getGeneratorStatus() != 1) continue; + if ( abs(Gen.getPDG())==12 || abs(Gen.getPDG())==14 || abs(Gen.getPDG())==16 ) continue; + TLorentzVector p4_gen; + p4_gen.SetPxPyPzE(Gen.getMomentum()[0], Gen.getMomentum()[1], Gen.getMomentum()[2], Gen.getEnergy()); + deta = p4_pfo.Eta() - p4_gen.Eta(); + dphi = TVector2::Phi_mpi_pi(p4_pfo.Phi() - p4_gen.Phi()); + dR_temp = TMath::Sqrt(deta*deta + dphi*dphi); + if (dR_temp < mini_dR){ + mini_dR = dR_temp; + PFO_Energy_Charge_GENMatch_ID_temp = Gen.getPDG(); + PFO_Energy_Charge_GENMatch_E_temp = Gen.getEnergy(); + } + } + PFO_Energy_Charge_GENMatch_dR.push_back(mini_dR); + PFO_Energy_Charge_GENMatch_ID.push_back(PFO_Energy_Charge_GENMatch_ID_temp); + PFO_Energy_Charge_GENMatch_E.push_back(PFO_Energy_Charge_GENMatch_E_temp); + + + for (unsigned i = 0; i < pfo.clusters_size(); i++){ + std::vector<double> PFO_Hits_Charge_perCluster_E; + std::vector<double> PFO_Hits_Charge_perCluster_R; + std::vector<double> PFO_Hits_Charge_perCluster_theta; + std::vector<double> PFO_Hits_Charge_perCluster_phi; + for (unsigned j = 0; j < pfo.getClusters(i).hits_size(); j++){ + PFO_Hits_Charge_perCluster_E.push_back(pfo.getClusters(i).getHits(j).getEnergy()); + PFO_Hits_Charge_perCluster_R.push_back(TMath::Sqrt(pfo.getClusters(i).getHits(j).getPosition().x*pfo.getClusters(i).getHits(j).getPosition().x + pfo.getClusters(i).getHits(j).getPosition().y*pfo.getClusters(i).getHits(j).getPosition().y)); + PFO_Hits_Charge_perCluster_theta.push_back(pfo.getClusters(i).getHits(j).getPosition().z/std::asin(TMath::Sqrt(pfo.getClusters(i).getHits(j).getPosition().x*pfo.getClusters(i).getHits(j).getPosition().x + pfo.getClusters(i).getHits(j).getPosition().y*pfo.getClusters(i).getHits(j).getPosition().y + pfo.getClusters(i).getHits(j).getPosition().z*pfo.getClusters(i).getHits(j).getPosition().z))); + PFO_Hits_Charge_perCluster_phi.push_back(std::atan2(pfo.getClusters(i).getHits(j).getPosition().y, pfo.getClusters(i).getHits(j).getPosition().x)); + } + //info() << "[Clusters Hits] " << PFO_Hits_Charge_perCluster_E << endmsg; + //std::copy(PFO_Hits_Charge_perCluster_E.begin(), PFO_Hits_Charge_perCluster_E.end(), std::ostream_iterator<double>(std::cout, " ")); + //std::cout << "[Clusters Hits] " << std::endl; + PFO_Hits_Charge_E.push_back(PFO_Hits_Charge_perCluster_E); + PFO_Hits_Charge_R.push_back(PFO_Hits_Charge_perCluster_R); + PFO_Hits_Charge_theta.push_back(PFO_Hits_Charge_perCluster_theta); + PFO_Hits_Charge_phi.push_back(PFO_Hits_Charge_perCluster_phi); + } + + + } + else if (abs(pfo.getCharge()) == 0 && pfo.clusters_size() > 1){ + //PFO_Energy_Neutral[_particle_index_Neutral] += pfo.getEnergy(); + //_particle_index_Neutral++; + PFO_Energy_Neutral.push_back(pfo.getEnergy()); + } + else if (abs(pfo.getCharge()) == 0 && pfo.clusters_size() == 1){ + //PFO_Energy_Neutral_singleCluster[_particle_index_Neutral_singleCluster] = pfo.getEnergy(); + //PFO_Energy_Neutral_singleCluster_R[_particle_index_Neutral_singleCluster] = TMath::Sqrt(pfo.getClusters(0).getPosition().x * pfo.getClusters(0).getPosition().x + pfo.getClusters(0).getPosition().y * pfo.getClusters(0).getPosition().y + pfo.getClusters(0).getPosition().z * pfo.getClusters(0).getPosition().z); + //_particle_index_Neutral_singleCluster++; + PFO_Energy_Neutral_singleCluster.push_back(pfo.getEnergy()); + PFO_Energy_Neutral_singleCluster_R.push_back(TMath::Sqrt(pfo.getClusters(0).getPosition().x * pfo.getClusters(0).getPosition().x + pfo.getClusters(0).getPosition().y * pfo.getClusters(0).getPosition().y)); + + for (unsigned i = 0; i < pfo.clusters_size(); i++){ + std::vector<double> PFO_Hits_Neutral_perCluster_E; + std::vector<double> PFO_Hits_Neutral_perCluster_R; + std::vector<double> PFO_Hits_Neutral_perCluster_theta; + std::vector<double> PFO_Hits_Neutral_perCluster_phi; + for (unsigned j = 0; j < pfo.getClusters(i).hits_size(); j++){ + PFO_Hits_Neutral_perCluster_E.push_back(pfo.getClusters(i).getHits(j).getEnergy()); + PFO_Hits_Neutral_perCluster_R.push_back(TMath::Sqrt(pfo.getClusters(i).getHits(j).getPosition().x*pfo.getClusters(i).getHits(j).getPosition().x + pfo.getClusters(i).getHits(j).getPosition().y*pfo.getClusters(i).getHits(j).getPosition().y)); + PFO_Hits_Neutral_perCluster_theta.push_back(pfo.getClusters(i).getHits(j).getPosition().z/std::asin(TMath::Sqrt(pfo.getClusters(i).getHits(j).getPosition().x*pfo.getClusters(i).getHits(j).getPosition().x + pfo.getClusters(i).getHits(j).getPosition().y*pfo.getClusters(i).getHits(j).getPosition().y + pfo.getClusters(i).getHits(j).getPosition().z*pfo.getClusters(i).getHits(j).getPosition().z))); + PFO_Hits_Neutral_perCluster_phi.push_back(std::atan2(pfo.getClusters(i).getHits(j).getPosition().y, pfo.getClusters(i).getHits(j).getPosition().x)); + } + PFO_Hits_Neutral_E.push_back(PFO_Hits_Neutral_perCluster_E); + PFO_Hits_Neutral_R.push_back(PFO_Hits_Neutral_perCluster_R); + PFO_Hits_Neutral_theta.push_back(PFO_Hits_Neutral_perCluster_theta); + PFO_Hits_Neutral_phi.push_back(PFO_Hits_Neutral_perCluster_phi); + } + } + } + } + + particle_index_muon = _particle_index_muon; + particle_index_Charge = _particle_index_Charge; + particle_index_Neutral = _particle_index_Neutral; + particle_index_Neutral_singleCluster = _particle_index_Neutral_singleCluster; + + // create a jet definition + int nJets = m_nJets; + double R = m_R; + + JetDefinition jet_def(ee_kt_algorithm); + //JetDefinition jet_def(antikt_algorithm, R); + + // run the clustering, extract the jets + //std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + + ClusterSequence clust_seq(input_particles, jet_def); + + vector<PseudoJet> jets = sorted_by_pt(clust_seq.exclusive_jets(nJets)); + + //std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + + //_time = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() / 1000000.0; + + //info() << "FastJet clustering done in seconds: " << _time << endmsg; + + //string jet_def_str = jet_def.description(); + //debug() << "Clustering with " << jet_def_str << " for " << nJets << " jets with R = " << R << endmsg; + + // print the jets + TLorentzVector Particles_Gen_match_sum; + //info() << " px py pz E costheta phi " << endmsg; + for (unsigned i = 0; i < jets.size(); i++) { + //info() << " jet " << i << " " << jets[i].px() << " " << jets[i].py() << " " << jets[i].pz() << " " << jets[i].E() << " " << jets[i].cos_theta() << " " << jets[i].phi() << endmsg; + vector<PseudoJet> constituents = jets[i].constituents(); + + for (unsigned j = 0; j < constituents.size(); j++) { + if ( i == 1 ){ + constituents_E1tot += constituents[j].E(); + jet1_nparticles++; + } + if ( i == 2 ) { + constituents_E2tot += constituents[j].E(); + jet2_nparticles++; + } + //info() << " constituent " << j << " " << constituents[j].px() << " " << constituents[j].py() << " " << constituents[j].pz() << " " << constituents[j].E() << " " << constituents[j].cos_theta() << " " << constituents[j].phi() << endmsg; + + TLorentzVector p4_pfo; + p4_pfo.SetPxPyPzE(constituents[j].px(), constituents[j].py(), constituents[j].pz(), constituents[j].E()); + + float mini_dR = 0.3; + float dR_temp = 0.0; + float deta = 0.0; + float dphi =0.0; + TLorentzVector p4_gen_match; + for(const auto& Gen : *MCParticlesGen){ + if (Gen.getGeneratorStatus() != 1) continue; + if ( abs(Gen.getPDG())==12 || abs(Gen.getPDG())==14 || abs(Gen.getPDG())==16 ) continue; + TLorentzVector p4_gen; + p4_gen.SetPxPyPzE(Gen.getMomentum()[0], Gen.getMomentum()[1], Gen.getMomentum()[2], Gen.getEnergy()); + deta = p4_pfo.Eta() - p4_gen.Eta(); + dphi = TVector2::Phi_mpi_pi(p4_pfo.Phi() - p4_gen.Phi()); + dR_temp = TMath::Sqrt(deta*deta + dphi*dphi); + if (dR_temp < mini_dR){ + mini_dR = dR_temp; + p4_gen_match = p4_gen; + } + } + Particles_Gen_match_sum += p4_gen_match; + } + } + //info() << "Total energy of constituents: " << constituents_E1tot << " " << constituents_E2tot << endmsg; + + + double _ymin[20]; + for(int i=1; i<6;i++){ + _ymin[i-1] = clust_seq.exclusive_ymerge (i); + // info() << " -log10(y" << i << i+1 << ") = " << -log10(_ymin[i-1]) << endmsg; + } + + + mass = (jets[0] + jets[1]).m(); + + + vector<PseudoJet> input_particles_gen; + int NNeutrinoCount = 0; + for(const auto& Gen : *MCParticlesGen){ + //info() << "[[DEBUG]] Gen Particle stable 1 " << _gen_particle_index << " px: " << Gen.getMomentum()[0] << " py: " << Gen.getMomentum()[1] << " pz: " << Gen.getMomentum()[2] << " E: " << Gen.getEnergy() << " PDG ID: " << Gen.getPDG() << " GeneratorStatus: " << Gen.getGeneratorStatus() << endmsg; + if ( (abs(Gen.getPDG())==12 || abs(Gen.getPDG())==14 || abs(Gen.getPDG())==16) && Gen.getGeneratorStatus()!=2 ){ + NNeutrinoCount++; +//cout<<" Found Neutrino #"<<NNeutrinoCount<<endl; + if(NNeutrinoCount > 2) { + auto tmpP0 = Gen.getMomentum(); + TVector3 tmpP = TVector3(tmpP0.x, tmpP0.y, tmpP0.z); + GEN_inv_E += tmpP.Mag(); + GEN_inv_pt += tmpP.Perp(); +//cout<<" Inv energy "<<GEN_inv_E<<", pt "<<GEN_inv_pt<<endl; + } + _gen_particle_index++; + continue; + } + if (Gen.getGeneratorStatus() != 1) continue; + //info() << "[[DEBUG]] Gen Particle stable 1 " << _gen_particle_index << " px: " << Gen.getMomentum()[0] << " py: " << Gen.getMomentum()[1] << " pz: " << Gen.getMomentum()[2] << " E: " << Gen.getEnergy() << " PDG ID: " << Gen.getPDG() << " GeneratorStatus: " << Gen.getGeneratorStatus() << endmsg; + input_particles_gen.push_back(PseudoJet(Gen.getMomentum()[0], Gen.getMomentum()[1], Gen.getMomentum()[2], Gen.getEnergy())); + if (Gen.getPDG()==22){ + //GEN_PFO_Energy_gamma[_gen_particle_gamma_index] = Gen.getEnergy(); + //_gen_particle_gamma_index++; + GEN_PFO_Energy_gamma.push_back(Gen.getEnergy()); + int NParent = Gen.parents_size(); +//cout<<" Found photon. index "<<_gen_particle_index<<", Nparent = "<<NParent<<endl; + if(_gen_particle_index<4 && NParent==0){ + auto tmpP0 = Gen.getMomentum(); + TVector3 tmpP = TVector3(tmpP0.x, tmpP0.y, tmpP0.z); + GEN_ISR_E += tmpP.Mag(); + GEN_ISR_pt += tmpP.Perp(); +//cout<<" Found ISR photon. E = "<<GEN_ISR_E<<", pt = "<<GEN_ISR_pt<<endl; + } + } + else if (Gen.getPDG()==211 || Gen.getPDG()==-211){ + //GEN_PFO_Energy_pipm[_gen_particle_pipm_index] = Gen.getEnergy(); + //_gen_particle_pipm_index++; + GEN_PFO_Energy_pipm.push_back(Gen.getEnergy()); + } + else if (Gen.getPDG()==111){ + //GEN_PFO_Energy_pi0[_gen_particle_pi0_index] = Gen.getEnergy(); + //_gen_particle_pi0_index++; + GEN_PFO_Energy_pi0.push_back(Gen.getEnergy()); + } + else if (Gen.getPDG()==2212 || Gen.getPDG()==-2212){ + //GEN_PFO_Energy_ppm[_gen_particle_ppm_index] = Gen.getEnergy(); + //_gen_particle_ppm_index++; + GEN_PFO_Energy_ppm.push_back(Gen.getEnergy()); + } + else if (Gen.getPDG()==321 || Gen.getPDG()==-321){ + //GEN_PFO_Energy_kpm[_gen_particle_kpm_index] = Gen.getEnergy(); + //_gen_particle_kpm_index++; + GEN_PFO_Energy_kpm.push_back(Gen.getEnergy()); + } + else if (Gen.getPDG()==130){ + //GEN_PFO_Energy_kL[_gen_particle_kL_index] = Gen.getEnergy(); + //_gen_particle_kL_index++; + GEN_PFO_Energy_kL.push_back(Gen.getEnergy()); + } + + else if (abs(Gen.getPDG())==2112){ + //GEN_PFO_Energy_n[_gen_particle_n_index] = Gen.getEnergy(); + //_gen_particle_n_index++; + GEN_PFO_Energy_n.push_back(Gen.getEnergy()); + } + + else if (abs(Gen.getPDG())==11){ + //GEN_PFO_Energy_e[_gen_particle_e_index] = Gen.getEnergy(); + //_gen_particle_e_index++; + GEN_PFO_Energy_e.push_back(Gen.getEnergy()); + } + else if (abs(Gen.getPDG())==13){ + //GEN_PFO_Energy_e[_gen_particle_e_index] = Gen.getEnergy(); + //_gen_particle_e_index++; + GEN_PFO_Energy_muon.push_back(Gen.getEnergy()); + } + + _gen_particle_index++; + } + + int Nmc = 0; + int Nmc_barrel = 0; + int n_status1 = 0; + for(const auto& Gen : *MCParticlesGen){ + if (Gen.getGeneratorStatus() != 1) continue; + n_status1++; + + TVector3 part(Gen.getMomentum().x, Gen.getMomentum().y, Gen.getMomentum().z); + + if(n_status1<=4) + { + // ISR photon should not hit ECAL barrel + if(Gen.getPDG()==22 && Gen.getEnergy()>0 && fabs(part.CosTheta())<0.85) Nmc_barrel = 0; + continue; + } + Nmc++; + if(fabs(part.CosTheta())<0.85) Nmc_barrel++; + } + + barrelRatio = (double)Nmc_barrel/(double)Nmc; + + GEN_particle_gamma_index = _gen_particle_gamma_index; + GEN_particle_pipm_index = _gen_particle_pipm_index; + GEN_particle_pi0_index = _gen_particle_pi0_index; + GEN_particle_ppm_index = _gen_particle_ppm_index; + GEN_particle_kpm_index = _gen_particle_kpm_index; + GEN_particle_kL_index = _gen_particle_kL_index; + GEN_particle_n_index = _gen_particle_n_index; + GEN_particle_e_index = _gen_particle_e_index; + + //info() << "[[DEBUG]] Gen Particle stable 1 " << _gen_particle_index << " seperate: " << GEN_particle_gamma_index+GEN_particle_pipm_index+GEN_particle_pi0_index+GEN_particle_ppm_index+GEN_particle_kpm_index+GEN_particle_kL_index+GEN_particle_n_index << endmsg; + + // create a jet definition + + JetDefinition Genjet_def(ee_kt_algorithm); + //JetDefinition jet_def(antikt_algorithm, R); + + // run the clustering, extract the jets + //std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + + ClusterSequence Genclust_seq(input_particles_gen, Genjet_def); + + vector<PseudoJet> Genjets = sorted_by_pt(Genclust_seq.exclusive_jets(nJets)); + + //std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + + double _ymin_gen[20]; + for(int i=1; i<6;i++){ + _ymin_gen[i-1] = Genclust_seq.exclusive_ymerge (i); + //info() << " -log10(y" << i << i+1 << ") = " << -log10(_ymin_gen[i-1]) << endmsg; + } + + // ############## Jet Gen Match + for (unsigned i = 0; i < jets.size(); i++) { + float GEN_mini_dR = 999.; + int GEN_mini_ID_temp = -99.0; + float GEN_dR_temp = -99.0; + float GEN_deta = 0.0; + float GEN_dphi =0.0; + + for (unsigned j = 0; j < Genjets.size(); j++) { + GEN_deta = jets[i].eta() - Genjets[j].eta(); + GEN_dphi = TVector2::Phi_mpi_pi(jets[i].phi() - Genjets[j].phi()); + GEN_dR_temp = TMath::Sqrt(GEN_deta*GEN_deta + GEN_dphi*GEN_dphi); + + if (GEN_dR_temp < GEN_mini_dR){ + GEN_mini_dR = GEN_dR_temp; + GEN_mini_ID_temp = j; + } + } + if (i==0) { + jet1_GENMatch_id = GEN_mini_ID_temp; + jet1_GENMatch_mindR = GEN_mini_dR; + } + if (i==1) { + jet2_GENMatch_id = GEN_mini_ID_temp; + jet2_GENMatch_mindR = GEN_mini_dR; + } + } + + + + //for (unsigned i = 0; i < Genjets.size(); i++) { + // vector<PseudoJet> constituents = Genjets[i].constituents(); + // for (unsigned j = 0; j < constituents.size(); j++) { + + // for(const auto& Gen : *MCParticlesGen){ + // if (abs(constituents[j].px()-Gen.getMomentum()[0])<0.00001 && abs(constituents[j].py()-Gen.getMomentum()[1])<0.00001 && abs(constituents[j].pz()-Gen.getMomentum()[2])<0.00001 && abs(constituents[j].E()-Gen.getEnergy()[0])<0.00001 ) + // if (i==0) { + // jet1_GENMatch_id = GEN_mini_ID_temp; + // jet1_GENMatch_mindR = GEN_mini_dR; + // } + // if (i==1) { + // jet2_GENMatch_id = GEN_mini_ID_temp; + // jet2_GENMatch_mindR = GEN_mini_dR; + // } + // } + // + // } + //} + + + + + + // fill the tree + jet1_px = jets[0].px(); + jet1_py = jets[0].py(); + jet1_pz = jets[0].pz(); + jet1_E = jets[0].E(); + jet1_costheta = jets[0].cos_theta(); + jet1_phi = jets[0].phi(); + jet1_pt = jets[0].pt(); + jet1_nconstituents = jets[0].constituents().size(); + jet2_px = jets[1].px(); + jet2_py = jets[1].py(); + jet2_pz = jets[1].pz(); + jet2_E = jets[1].E(); + jet2_costheta = jets[1].cos_theta(); + jet2_phi = jets[1].phi(); + jet2_pt = jets[1].pt(); + jet2_nconstituents = jets[1].constituents().size(); + for(int i=0; i<6; i++){ + ymerge[i] = _ymin[i]; + } + for(int i=0; i<6; i++){ + ymerge_gen[i] = _ymin_gen[i]; + } + + mass_gen_match = Particles_Gen_match_sum.M(); + mass_allParticles = input_particles_sum.M(); + nparticles = _nparticles; + GEN_nparticles = _gen_particle_index; + + GEN_mass = (Genjets[0] + Genjets[1]).m(); + GEN_jet1_px = Genjets[0].px(); + GEN_jet1_py = Genjets[0].py(); + GEN_jet1_pz = Genjets[0].pz(); + GEN_jet1_E = Genjets[0].E(); + GEN_jet1_costheta = Genjets[0].cos_theta(); + GEN_jet1_phi = Genjets[0].phi(); + GEN_jet1_pt = Genjets[0].pt(); + GEN_jet1_nconstituents = Genjets[0].constituents().size(); + GEN_jet2_px = Genjets[1].px(); + GEN_jet2_py = Genjets[1].py(); + GEN_jet2_pz = Genjets[1].pz(); + GEN_jet2_E = Genjets[1].E(); + GEN_jet2_costheta = Genjets[1].cos_theta(); + GEN_jet2_phi = Genjets[1].phi(); + GEN_jet2_pt = Genjets[1].pt(); + GEN_jet2_nconstituents = Genjets[1].constituents().size(); + + _tree->Fill(); + + _nEvt++; + return StatusCode::SUCCESS; + +} + +//------------------------------------------------------------------------------ +StatusCode GenMatch::finalize(){ + debug() << "Finalizing..." << endmsg; + _file->Write(); + + delete _tree; + return StatusCode::SUCCESS; +} + + +void GenMatch::CleanVars(){ + + _particle_index = 0; + _gen_particle_index = _particle_index_muon = _particle_index_Charge = _particle_index_Neutral = _particle_index_Neutral_singleCluster = 0; + particle_index_muon = particle_index_Charge = particle_index_Neutral = particle_index_Neutral_singleCluster = 0; + _jet_index = 0; + _nparticles = 0; + _time = 0; + + jet1_px = jet1_py = jet1_pz = jet1_E = 0; + jet2_px = jet2_py = jet2_pz = jet2_E = 0; + jet1_costheta = jet1_phi = 0; + jet2_costheta = jet2_phi = 0; + jet1_pt = jet2_pt = jet1_GENMatch_mindR = jet2_GENMatch_mindR = 0; + jet1_nconstituents = jet2_nconstituents = nparticles = jet1_GENMatch_id = jet2_GENMatch_id = 0; + constituents_E1tot = constituents_E2tot = 0; + _gen_particle_gamma_index = _gen_particle_pipm_index = _gen_particle_pi0_index = _gen_particle_ppm_index = _gen_particle_kpm_index = _gen_particle_kL_index = _gen_particle_n_index = _gen_particle_e_index = 0; + GEN_particle_gamma_index = GEN_particle_pipm_index = GEN_particle_pi0_index = GEN_particle_ppm_index = GEN_particle_kpm_index = GEN_particle_kL_index = GEN_particle_n_index = GEN_particle_e_index = 0; + for(int i=0; i<6; i++){ + ymerge[i] = 0; + } + for(int i=0; i<6; i++){ + ymerge_gen[i] = 0; + } + + PFO_Energy_muon.clear(); PFO_Energy_muon_GENMatch_dR.clear(); PFO_Energy_muon_GENMatch_ID.clear(); PFO_Energy_muon_GENMatch_E.clear(); PFO_Energy_Charge.clear(); PFO_Energy_Charge_Ecal.clear(); PFO_Energy_Charge_Hcal.clear(); PFO_Energy_Charge_GENMatch_dR.clear(); PFO_Energy_Charge_GENMatch_ID.clear(); PFO_Energy_Charge_GENMatch_E.clear(); PFO_Energy_Neutral.clear(); PFO_Energy_Neutral_singleCluster.clear(); PFO_Energy_Neutral_singleCluster_R.clear(); + GEN_PFO_Energy_muon.clear(); GEN_PFO_Energy_pipm.clear(); GEN_PFO_Energy_pi0.clear(); GEN_PFO_Energy_ppm.clear(); GEN_PFO_Energy_kpm.clear(); GEN_PFO_Energy_kL.clear(); GEN_PFO_Energy_n.clear(); GEN_PFO_Energy_e.clear(); GEN_PFO_Energy_gamma.clear(); + PFO_Hits_Charge_E.clear(); PFO_Hits_Charge_R.clear(); PFO_Hits_Charge_theta.clear(); PFO_Hits_Charge_phi.clear(); + PFO_Hits_Neutral_E.clear(); PFO_Hits_Neutral_R.clear(); PFO_Hits_Neutral_theta.clear(); PFO_Hits_Neutral_phi.clear(); + + mass = mass_gen_match = GEN_mass = mass_allParticles = 0; + barrelRatio = 0; + GEN_inv_E = GEN_inv_pt = 0; + GEN_ISR_E = GEN_ISR_pt = 0; + GEN_jet1_px = GEN_jet1_py = GEN_jet1_pz = GEN_jet1_E = 0; + GEN_jet2_px = GEN_jet2_py = GEN_jet2_pz = GEN_jet2_E = 0; + GEN_jet1_costheta = GEN_jet1_phi = 0; + GEN_jet2_costheta = GEN_jet2_phi = 0; + GEN_jet1_pt = GEN_jet2_pt = 0; + GEN_jet1_nconstituents = GEN_jet2_nconstituents = GEN_nparticles = 0; + GEN_constituents_E1tot = GEN_constituents_E2tot = 0; + +} + diff --git a/Analysis/GenMatch/src/GenMatch.h b/Analysis/GenMatch/src/GenMatch.h new file mode 100644 index 00000000..abdab139 --- /dev/null +++ b/Analysis/GenMatch/src/GenMatch.h @@ -0,0 +1,103 @@ +#ifndef GenMatch_h +#define GenMatch_h 1 + +#include "UTIL/ILDConf.h" +#include "k4FWCore/DataHandle.h" +#include "GaudiKernel/Algorithm.h" +#include <random> +#include "GaudiKernel/NTuple.h" +#include "TFile.h" +#include "TTree.h" + +#include "edm4hep/ReconstructedParticleData.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/ReconstructedParticle.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCParticleCollectionData.h" + +class GenMatch : public Algorithm { + public: + // Constructor of this form must be provided + GenMatch( const std::string& name, ISvcLocator* pSvcLocator ); + + // Three mandatory member functions of any algorithm + StatusCode initialize() override; + StatusCode execute() override; + StatusCode finalize() override; + + private: + + DataHandle<edm4hep::ReconstructedParticleCollection> m_PFOColHdl{"CyberPFO", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCParticleCollection> m_MCParticleGenHdl{"MCParticle", Gaudi::DataHandle::Reader, this}; + Gaudi::Property<std::string> m_algo{this, "Algorithm", "ee_kt_algorithm"}; + Gaudi::Property<int> m_nJets{this, "nJets", 2}; + Gaudi::Property<double> m_R{this, "R", 0.6}; + Gaudi::Property<std::string> m_outputFile{this, "OutputFile", "GenMatch.root"}; + + int _nEvt; + int _particle_index; + int _jet_index; + int _nparticles; + int jet1_nparticles; + int jet2_nparticles; + double _time; + + TFile* _file; + TTree* _tree; + double jet1_px, jet1_py, jet1_pz, jet1_E; + double jet2_px, jet2_py, jet2_pz, jet2_E; + double jet1_costheta, jet1_phi; + double jet2_costheta, jet2_phi; + double jet1_pt, jet2_pt; + int jet1_nconstituents, jet2_nconstituents, nparticles, jet1_GENMatch_id, jet2_GENMatch_id; + double constituents_E1tot; + double constituents_E2tot; + double ymerge[6]; + double mass; + double mass_gen_match, jet1_GENMatch_mindR, jet2_GENMatch_mindR; + double mass_allParticles; + //double PFO_Energy_muon[50]; + //double PFO_Energy_Charge[50]; + //double PFO_Energy_Neutral[50]; + //double PFO_Energy_Neutral_singleCluster[600]; + //double PFO_Energy_Neutral_singleCluster_R[600]; + int _particle_index_muon, _particle_index_Charge, _particle_index_Neutral, _particle_index_Neutral_singleCluster; + int particle_index_muon, particle_index_Charge, particle_index_Neutral, particle_index_Neutral_singleCluster; + //double GEN_PFO_Energy_muon[50]; + //double GEN_PFO_Energy_pipm[120]; + //double GEN_PFO_Energy_pi0[120]; + //double GEN_PFO_Energy_ppm[120]; + //double GEN_PFO_Energy_kpm[120]; + //double GEN_PFO_Energy_kL[120]; + //double GEN_PFO_Energy_n[50]; + //double GEN_PFO_Energy_e[50]; + //double GEN_PFO_Energy_gamma[120]; + std::vector<double> PFO_Energy_muon, PFO_Energy_muon_GENMatch_dR, PFO_Energy_muon_GENMatch_E, PFO_Energy_Charge, PFO_Energy_Charge_Ecal, PFO_Energy_Charge_Hcal, PFO_Energy_Charge_GENMatch_dR, PFO_Energy_Charge_GENMatch_E, PFO_Energy_Neutral, PFO_Energy_Neutral_singleCluster, PFO_Energy_Neutral_singleCluster_R; + std::vector<int> PFO_Energy_Charge_GENMatch_ID, PFO_Energy_muon_GENMatch_ID; + std::vector<double> GEN_PFO_Energy_muon, GEN_PFO_Energy_pipm, GEN_PFO_Energy_pi0, GEN_PFO_Energy_ppm, GEN_PFO_Energy_kpm, GEN_PFO_Energy_kL, GEN_PFO_Energy_n, GEN_PFO_Energy_e, GEN_PFO_Energy_gamma; + std::vector<std::vector<double>> PFO_Hits_Charge_E, PFO_Hits_Charge_R, PFO_Hits_Charge_theta, PFO_Hits_Charge_phi; + std::vector<std::vector<double>> PFO_Hits_Neutral_E, PFO_Hits_Neutral_R, PFO_Hits_Neutral_theta, PFO_Hits_Neutral_phi; + //double PFO_Energy_muon[500]; + + int _gen_particle_index; + double barrelRatio; + double ymerge_gen[6]; + double GEN_mass; + double GEN_ISR_E, GEN_ISR_pt; + double GEN_inv_E, GEN_inv_pt; + double GEN_jet1_px, GEN_jet1_py, GEN_jet1_pz, GEN_jet1_E; + double GEN_jet2_px, GEN_jet2_py, GEN_jet2_pz, GEN_jet2_E; + double GEN_jet1_costheta, GEN_jet1_phi; + double GEN_jet2_costheta, GEN_jet2_phi; + double GEN_jet1_pt, GEN_jet2_pt; + int GEN_jet1_nconstituents, GEN_jet2_nconstituents, GEN_nparticles; + double GEN_constituents_E1tot; + double GEN_constituents_E2tot; + int _gen_particle_gamma_index, _gen_particle_pipm_index, _gen_particle_pi0_index, _gen_particle_ppm_index, _gen_particle_kpm_index, _gen_particle_kL_index, _gen_particle_n_index, _gen_particle_e_index; + int GEN_particle_gamma_index, GEN_particle_pipm_index, GEN_particle_pi0_index, GEN_particle_ppm_index, GEN_particle_kpm_index, GEN_particle_kL_index, GEN_particle_n_index, GEN_particle_e_index; + + void CleanVars(); + +}; +#endif + diff --git a/Detector/DetCRD/CMakeLists.txt b/Detector/DetCRD/CMakeLists.txt index 6f874165..37b2f66d 100644 --- a/Detector/DetCRD/CMakeLists.txt +++ b/Detector/DetCRD/CMakeLists.txt @@ -7,6 +7,7 @@ gaudi_add_module(DetCRD SOURCES src/Calorimeter/CRDEcal_v01.cpp src/Calorimeter/LongCrystalBarBarrelCalorimeter32Polygon_v01.cpp src/Calorimeter/LongCrystalBarEndcapCalorimeter_v01.cpp + src/Calorimeter/LongCrystalBarEndcapCalorimeter_v02.cpp src/Calorimeter/CRDEcal_Short_v02.cpp src/Calorimeter/CRDEcal_Endcap_Short_v01.cpp src/Calorimeter/RotatedPolyhedraBarrelCalorimeter_v01_geo.cpp @@ -75,6 +76,12 @@ add_test( WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} ) +add_test( + NAME Test_TDR_o1_v01_PFA + COMMAND gaudirun.py Detector/DetCRD/scripts/TDR_o1_v01/rec.py + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) + foreach(detoption TDR_o1_v01) add_test( NAME Test_${detoption}_Geo diff --git a/Detector/DetCRD/compact/CRD_common_v01/Ecal_Crystal_Endcap_v01_02.xml b/Detector/DetCRD/compact/CRD_common_v01/Ecal_Crystal_Endcap_v01_02.xml new file mode 100755 index 00000000..929405c5 --- /dev/null +++ b/Detector/DetCRD/compact/CRD_common_v01/Ecal_Crystal_Endcap_v01_02.xml @@ -0,0 +1,61 @@ +<lccdd> + <define> + <!-- <constant name="Ecal_endcap_inner_radius" value="2.5*mm"/> + <constant name="Ecal_endcap_inner_radius" value="2.5*mm"/> --> + <constant name="Ecal_endcap_nlayers" value="28"/> + <constant name="Ecal_scintillator_thickness" value="10*mm"/> + <constant name="Ecal_deadarea_thickness" value="8.5*mm"/> + </define> + + <detectors> + <detector id="DetID_ECAL_ENDCAP" name="EcalEndcap" type="LongCrystalBarEndcapCalorimeter_v02" readout="EcalEndcapsCollection" vis="CyanVis" calorimeterType="EMC_ENDCAP"> + <comment>Electromagnetic Calorimeter Endcap</comment> + + <envelope vis="SeeThrough"> + <shape type="BooleanShape" operation="Subtraction" material="Air"> + <shape type="BooleanShape" operation="Subtraction" material="Air"> + <shape type="Tube" rmin="0.0" rmax="Ecal_endcap_outer_radius - env_safety" dz="Ecal_endcap_zmax"/> <!--there is a thin plane in envolop --> + <shape type="Tube" rmin="0.0" rmax="Ecal_endcap_outer_radius + env_safety" dz="Ecal_endcap_zmin"/> + </shape> + <shape type="Box" dx="Ecal_endcap_inner_radius" dy="Ecal_endcap_inner_radius" dz="Ecal_endcap_zmax + env_safety"/> + </shape> + <rotation x="0" y="0" z="0"/> + </envelope> + + <type_flags type=" DetType_CALORIMETER + DetType_ENDCAP + DetType_EMC " /> + + <material name="CarbonFiber"/> + + <dimensions numsides="Ecal_x_module" > <!-- 0:cube 1:isosceles trapezoid 2:right trapezoid --> + <dimensions id="1" module_type="0" module_number="3" x_offset="766.5*mm" y_offset="766.5*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="326*mm" dim_y="326*mm" dim_z="300*mm"/> + <dimensions id="2" module_type="0" module_number="2" x_offset="1067.5*mm" y_offset="1067.5*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="276*mm" dim_y="276*mm" dim_z="300*mm"/> + <dimensions id="3" module_type="0" module_number="1" x_offset="1304*mm" y_offset="1304*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="197*mm" dim_y="197*mm" dim_z="300*mm"/> + <dimensions id="4" module_type="1" module_number="4" x_offset="570.5*mm" y_offset="0*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x1="574*mm" dim_x2="495*mm" dim_y1="441*mm" dim_y2="441*mm" dim_z="300*mm" /> + <dimensions id="7" module_type="4" module_number="4" x_offset="570.5*mm" y_offset="0*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x1="574*mm" dim_x2="495*mm" dim_y1="441*mm" dim_y2="441*mm" dim_z="300*mm" /> + <dimensions id="5" module_type="2" module_number="4" x_offset="425.5*mm" y_offset="435*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x1="318*mm" dim_x2="356*mm" dim_y1="356*mm" dim_y2="356*mm" dim_z="300*mm"/> + <dimensions id="8" module_type="5" module_number="4" x_offset="425.5*mm" y_offset="435*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x1="318*mm" dim_x2="356*mm" dim_y1="356*mm" dim_y2="356*mm" dim_z="300*mm"/> + <dimensions id="6" module_type="3" module_number="1" x_offset="425.5*mm" y_offset="425.5*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="178*mm" dim_y="140*mm" dim_z="300*mm"/> + <dimensions id="9" module_type="6" module_number="1" x_offset="425.5*mm" y_offset="425.5*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="178*mm" dim_y="140*mm" dim_z="300*mm"/> + <dimensions id="10" module_type="7" module_number="1" x_offset="425.5*mm" y_offset="425.5*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="178*mm" dim_y="140*mm" dim_z="300*mm"/> + <dimensions id="11" module_type="8" module_number="1" x_offset="425.5*mm" y_offset="425.5*mm" z_offset="Ecal_endcap_zmin+Ecal_endcap_thickness/2" dim_x="178*mm" dim_y="140*mm" dim_z="300*mm"/> + <!-- 425.5 --> + </dimensions> + + <layer repeat="Ecal_endcap_nlayers" vis="CyanVis" material="G4_BGO" thickness = "Ecal_scintillator_thickness"> + <slice material="G4_BGO" thickness = "Ecal_scintillator_thickness" sensitive = "yes" limits="cal_limits" vis="CyanVis" /> + </layer> + </detector> + </detectors> + + <readouts> + <readout name="EcalEndcapsCollection"> + <segmentation type="NoSegmentation"/> + <id>system:5,module:1,part:7,stave:7,type:4,dlayer:4,slayer:1,bar:7</id> + </readout> + </readouts> + +</lccdd> + + + + diff --git a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01.xml b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01.xml index 881750ac..1bcac3c8 100644 --- a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01.xml +++ b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01.xml @@ -42,7 +42,7 @@ <!--include ref="../CRD_common_v01/OTKEndcap_v01_01.xml"/--> <include ref="../CRD_common_v01/Ecal_Crystal_Barrel_v01_02.xml"/> - <include ref="../CRD_common_v01/Ecal_Crystal_Endcap_v01_01.xml"/> + <include ref="../CRD_common_v01/Ecal_Crystal_Endcap_v01_02.xml"/> <include ref="../CRD_common_v01/SHcalGlass_Barrel_v05.xml"/> <include ref="../CRD_common_v01/SHcalGlass_Endcaps_v01.xml"/> diff --git a/Detector/DetCRD/scripts/TDR_o1_v01/calodigi.py b/Detector/DetCRD/scripts/TDR_o1_v01/calodigi.py index 2b48aae4..46e93c7c 100644 --- a/Detector/DetCRD/scripts/TDR_o1_v01/calodigi.py +++ b/Detector/DetCRD/scripts/TDR_o1_v01/calodigi.py @@ -48,12 +48,14 @@ from Configurables import PodioInput podioinput = PodioInput("PodioReader", collections=[ # "EventHeader", "MCParticle", - "EcalBarrelCollection", - "EcalBarrelContributionCollection", - "HcalBarrelCollection", - "HcalBarrelContributionCollection", - "CompleteTracks", - "CompleteTracksParticleAssociation" + "EcalBarrelCollection", + "EcalBarrelContributionCollection", + "EcalEndcapsCollection", + "EcalEndcapsContributionCollection", + "HcalBarrelCollection", + "HcalBarrelContributionCollection", + "HcalEndcapsCollection", + "HcalEndcapsContributionCollection" ]) ########## Digitalization ################ @@ -61,19 +63,46 @@ podioinput = PodioInput("PodioReader", collections=[ ##ECAL## from Configurables import EcalDigiAlg EcalDigi = EcalDigiAlg("EcalDigiAlg") -EcalDigi.ReadOutName = "EcalBarrelCollection" -EcalDigi.SimCaloHitCollection = "EcalBarrelCollection" -EcalDigi.CaloHitCollection = "ECALBarrel" -EcalDigi.CaloAssociationCollection = "ECALBarrelAssoCol" -EcalDigi.CaloMCPAssociationCollection = "ECALBarrelParticleAssoCol" +EcalDigi.SimCaloHitCollection = ["EcalBarrelCollection", "EcalEndcapsCollection"] +EcalDigi.ReadOutName = ["EcalBarrelCollection", "EcalEndcapsCollection"] +EcalDigi.CaloHitCollection = ["ECALBarrel", "ECALEndcaps"] +EcalDigi.CaloAssociationCollection = ["ECALBarrelAssoCol", "ECALEndcapsAssoCol"] +EcalDigi.CaloMCPAssociationCollection = ["ECALBarrelParticleAssoCol", "ECALEndcapsParticleAssoCol"] EcalDigi.SkipEvt = 0 EcalDigi.Seed = 2079 #Digitalization parameters -EcalDigi.CalibrECAL = 1. -EcalDigi.AttenuationLength = 7e10 -EcalDigi.TimeResolution = 0.5 #unit: ns -EcalDigi.ChargeThresholdFrac = 0.05 -EcalDigi.Debug=1 +EcalDigi.TimeResolution = 0.7 # 0.7 ns +EcalDigi.EcalMIPEnergy = 8.9 # MIP energy 8.9 MeV for 1 cm BGO +EcalDigi.EcalMIP_Thre = 0.05 # 0.05 mip at each side, 0.1 mip for one bar +EcalDigi.UseRealisticDigi = 1 +# scintillation +EcalDigi.UseDigiScint = 1 +EcalDigi.EcalCryIntLY = 8200 #intrinsic LY 8200 [p.e./MIP] +EcalDigi.EcalCryMipLY = 200 #Detected effective LY 200 [p.e./MIP] +EcalDigi.AttenuationLength = 1e8 # 8000 mm for 5% non-uniformity +# SiPM +EcalDigi.SiPMDigiVerbose = 2 # 0:w/o response, w/o correction; 1:w/ response, w/o correction; 2:w/ response, w/ simple correction; 3:w/ response, w/ full correction +EcalDigi.EcalSiPMPDE = 0.25 # NDL-EQR06, PDE 0.25 +EcalDigi.EcalSiPMDCR = 0 # NDL-EQR06, dark count rate 2500000 [Hz] +EcalDigi.EcalTimeInterval = 0. # Time interval 0.000002 [s]. DCR*TimeInterval = dark count noise +EcalDigi.EcalSiPMCT = 0. # SiPM crosstalk Probability 12% +EcalDigi.EcalSiPMGainMean = 50 # 50 [ADC/p.e.] +EcalDigi.EcalSiPMGainSigma = 0.08 # 0.08 +# ADC +EcalDigi.ADC = 8192 # 13-bit, 8192 +EcalDigi.ADCSwitch = 8000 # 8000 +EcalDigi.Pedestal = 50 # Pedestal 50 ADC +EcalDigi.GainRatio_12 = 50 # Gain ratio 50 +EcalDigi.GainRatio_23 = 60 # Gain ratio 60 +# temperature control +EcalDigi.UseCryTemp = 0 +EcalDigi.UseCryTempCor = 0 +EcalDigi.UseSiPMTemp = 0 +EcalDigi.UseSiPMTempCor = 0 +EcalDigi.EcalTempGrad = 3./27 # 3./27 = 3K from 0 to 27 layer +EcalDigi.EcalBGOTempCoef = -0.0138 # -0.0138 [%/K] +EcalDigi.EcalSiPMGainTempCoef = -0.03 # -0.03 [%/K] +EcalDigi.EcalSiPMDCRTempCoef = 3.34/80 # 3.34/80 [10^{k*deltaT}] EcalDigi.WriteNtuple = 0 EcalDigi.OutFileName = "Digi_ECAL.root" ######################################### @@ -81,31 +110,41 @@ EcalDigi.OutFileName = "Digi_ECAL.root" ##HCAL## from Configurables import HcalDigiAlg HcalDigi = HcalDigiAlg("HcalDigiAlg") -HcalDigi.ReadOutName = "HcalBarrelCollection" -HcalDigi.SimCaloHitCollection = "HcalBarrelCollection" -HcalDigi.CaloHitCollection = "HCALBarrel" -HcalDigi.CaloAssociationCollection = "HCALBarrelAssoCol" -HcalDigi.CaloMCPAssociationCollection = "HCALBarrelParticleAssoCol" +HcalDigi.SimCaloHitCollection = ["HcalBarrelCollection", "HcalEndcapsCollection"] +HcalDigi.ReadOutName = ["HcalBarrelCollection", "HcalEndcapsCollection"] +HcalDigi.CaloHitCollection = ["HCALBarrel", "HCALEndcaps"] +HcalDigi.CaloAssociationCollection = ["HCALBarrelAssoCol", "HCALEndcapsAssoCol"] +HcalDigi.CaloMCPAssociationCollection = ["HCALBarrelParticleAssoCol", "HCALEndcapsParticleAssoCol"] HcalDigi.SkipEvt = 0 HcalDigi.Seed = 2079 -#Digitalization parameters -HcalDigi.MIPResponse = 0.007126 # MeV / MIP -HcalDigi.MIPThreshold = 0.1 # Unit: MIP HcalDigi.CalibrHCAL = 1. -HcalDigi.UseRealisticDigi = 1 # Flag to use digitization model. -HcalDigi.SiPMPixel = 57600 # 57600 for 6025PE (6*6 mm, 25 um pixel pitch) +#Digitalization parameters +HcalDigi.UseRealisticDigi = 0 #---------Flag to use digitization model. +HcalDigi.MIPResponse = 0.007126 # 0.007.126 GeV / MIP +HcalDigi.MIPThreshold = 0.1 # ----------Unit: MIP +HcalDigi.TemperatureVariation = 0 # Temperature variation 1K +# Scintillation +HcalDigi.UseTileLYMap = 0 +HcalDigi.MIPLY = 80 # Glass LY +HcalDigi.LYTempCoef = 0 # Glass LY with temperature HcalDigi.TileNonUniformity = 0.0 -HcalDigi.ADCError = 0.0 -HcalDigi.MIPADCMean = 80.*30.0 # Light yield 80 pe/mip -HcalDigi.PeADCMean = 30.0 -HcalDigi.PeADCSigma = 0. -HcalDigi.ADCBaselineHG = 0 -HcalDigi.ADCBaselineSigmaHG = 0. -HcalDigi.ADCBaselineLG = 0 -HcalDigi.ADCBaselineSigmaLG = 0. -HcalDigi.ADCHLRatio = 1 -HcalDigi.ADCSwitch = 1e7 -HcalDigi.ADCLimit = 1e7 +# SiPM +HcalDigi.SiPMPixel = 57600 #---------57600 for 6025PE (6*6 mm, 25 um pixel pitch) +HcalDigi.SiPMDCR = 1600 #---------1600 for 6025PE (6*6 mm, 25 um pixel pitch), 3200 for 6015PS () +HcalDigi.SiPMCT = 0.0 #---------SiPM crosstalk Probability 0.12 +HcalDigi.TimeInterval = 0. #---------Shaping time 2 us +HcalDigi.SiPMGainTempCoef = 0 #---------Temperature dependence of SiPM gain (-3%/K) +HcalDigi.SiPMDCRTempCoef = 0 #---------Temperature dependence of SiPM DCR (10^{k*deltaT}, k=3.34/80) +# ADC +HcalDigi.ADC = 8192 +HcalDigi.ADCSwitch = 1e7 # Switch at 8000 +HcalDigi.GainRatio_12 = 50 +HcalDigi.GainRatio_23 = 60 +HcalDigi.SiPMGainMean = 20 # SiPM gain: 2 ADC / p.e. +HcalDigi.SiPMGainSigma = 0.08 # Fluctuation of ADC / p.e. +HcalDigi.SiPMNoiseSigma = 0 # SiPM noise sigma +HcalDigi.Pedestal = 50 # Pedestal 50 ADC +HcalDigi.PedestalSigma = 4 # Sigma of electronic noise (4 ADC) HcalDigi.WriteNtuple = 0 HcalDigi.OutFileName = "Digi_HCAL.root" diff --git a/Detector/DetCRD/scripts/TDR_o1_v01/rec.py b/Detector/DetCRD/scripts/TDR_o1_v01/rec.py new file mode 100644 index 00000000..362421ef --- /dev/null +++ b/Detector/DetCRD/scripts/TDR_o1_v01/rec.py @@ -0,0 +1,167 @@ +import os, sys +from Gaudi.Configuration import * + +############## GeomSvc ################# +geometry_option = "TDR_o1_v01/TDR_o1_v01.xml" + +if not os.getenv("DETCRDROOT"): + print("Can't find the geometry. Please setup envvar DETCRDROOT." ) + sys.exit(-1) + +geometry_path = os.path.join(os.getenv("DETCRDROOT"), "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 DetGeomSvc +geomsvc = DetGeomSvc("GeomSvc") +geomsvc.compact = geometry_path +####################################### + +########### k4DataSvc #################### +from Configurables import k4DataSvc +podioevent = k4DataSvc("EventDataSvc", input="CaloDigi_TDR_o1_v01_00.root") +########################################## + +########## CEPCSWData ################# +cepcswdatatop ="/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/data/latest" +####################################### + +########## CrystalEcalEnergyCorrectionSvc ######## +from Configurables import CrystalEcalEnergyCorrectionSvc +crystalecalcorr = CrystalEcalEnergyCorrectionSvc("CrystalEcalEnergyCorrectionSvc") +crystalecalcorr.CorrectionFile = os.path.join(cepcswdatatop, "CEPCSWData/offline-data/Service/CrystalEcalSvc/data/CrackRegionEnergyCorrection.root") +################################################## + +########## Podio Input ################### +from Configurables import PodioInput +inp = PodioInput("InputReader") +inp.collections = [ + "ECALBarrel", + "ECALBarrelParticleAssoCol", +# "ECALEndcaps", +# "ECALEndcapsParticleAssoCol", + "HCALBarrel", + "HCALBarrelParticleAssoCol", +# "HCALEndcaps", +# "HCALEndcapsParticleAssoCol", + "MCParticle", + "CompleteTracks", + "CompleteTracksParticleAssociation"] +########################################## + +######### Reconstruction ################ +from Configurables import CyberPFAlg +CyberPFAlg = CyberPFAlg("CyberPFAlg") +##----Global parameters---- +CyberPFAlg.Seed = 1024 +CyberPFAlg.BField = 3. +CyberPFAlg.Debug = 0 +CyberPFAlg.SkipEvt = 0 +CyberPFAlg.WriteAna = 1 +CyberPFAlg.AnaFileName = "RecAnaTuple_TDR_o1_v01.root" +CyberPFAlg.UseMCPTrack = 0 +CyberPFAlg.UseTruthMatchTrack = 0 +CyberPFAlg.DoCleanTrack = 1 +CyberPFAlg.TrackIDFile = "/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/data/latest/CEPCSWData/offline-data/Reconstruction/CyberPFA_trackID/TrkID_BDT_BDTG.weights.xml" +CyberPFAlg.TrackIDMethod = "BDTG" +CyberPFAlg.EcalChargedCalib = 1.26 +CyberPFAlg.HcalChargedCalib = 4.0 +CyberPFAlg.EcalNeutralCalib = 1.0 +CyberPFAlg.HcalNeutralCalib = 4.0 +##----Readin collections---- +CyberPFAlg.MCParticleCollection = "MCParticle" +CyberPFAlg.TrackCollections = ["CompleteTracks"] +CyberPFAlg.MCRecoTrackParticleAssociationCollection = "CompleteTracksParticleAssociation" +#CyberPFAlg.ECalCaloHitCollections = ["ECALBarrel","ECALEndcaps"] +#CyberPFAlg.ECalReadOutNames = ["EcalBarrelCollection","EcalEndcapsCollection"] +#CyberPFAlg.ECalMCPAssociationName = ["ECALBarrelParticleAssoCol", "ECALEndcapsParticleAssoCol"] +#CyberPFAlg.HCalCaloHitCollections = ["HCALBarrel", "HCALEndcaps"] +#CyberPFAlg.HCalReadOutNames = ["HcalBarrelCollection", "HcalEndcapsCollection"] +#CyberPFAlg.HCalMCPAssociationName = ["HCALBarrelParticleAssoCol", "HCALEndcapsParticleAssoCol"] +CyberPFAlg.ECalCaloHitCollections = ["ECALBarrel"] +CyberPFAlg.ECalReadOutNames = ["EcalBarrelCollection"] +CyberPFAlg.ECalMCPAssociationName = ["ECALBarrelParticleAssoCol"] +CyberPFAlg.HCalCaloHitCollections = ["HCALBarrel"] +CyberPFAlg.HCalReadOutNames = ["HcalBarrelCollection"] +CyberPFAlg.HCalMCPAssociationName = ["HCALBarrelParticleAssoCol"] + +##--- Output collections --- +CyberPFAlg.OutputPFO = "outputPFO"; +CyberPFAlg.RecoPFOCollection = "CyberPFO" + +#----Algorithms---- +CyberPFAlg.AlgList = ["GlobalClusteringAlg", #1 + "LocalMaxFindingAlg", #2 + "TrackMatchingAlg", #3 + "HoughClusteringAlg", #4 + "ConeClustering2DAlg", #5 + "AxisMergingAlg", #6 + "EnergySplittingAlg", #9 + "EnergyTimeMatchingAlg", #11 + "HcalClusteringAlg", #12 + "TruthClusteringAlg", #15 + "TrackClusterConnectingAlg", #16 + "PFOReclusteringAlg" ] #17 +CyberPFAlg.AlgParNames = [ ["InputECALBars","OutputECAL1DClusters","OutputECALHalfClusters"],#1 + ["OutputLocalMaxName"],#2 + ["ReadinLocalMaxName","OutputLongiClusName"],#3 + ["ReadinLocalMaxName","LeftLocalMaxName","OutputLongiClusName"],#4 + ["ReadinLocalMaxName", "OutputLongiClusName"], #5 + ["OutputAxisName"], #6 + ["ReadinAxisName", "OutputClusName", "OutputTowerName"], #9 + ["ReadinHFClusterName", "ReadinTowerName","OutputClusterName"], #11 + ["InputHCALHits", "OutputHCALClusters"], #12 + ["DoECALClustering","DoHCALClustering","InputHCALHits","OutputHCALClusters"], #15 + ["ReadinECALClusterName", "ReadinHCALClusterName", "OutputCombPFO"], #16 + ["ECALChargedCalib", "HCALChargedCalib", "ECALNeutralCalib", "HCALNeutralCalib"] ]#17 +CyberPFAlg.AlgParTypes = [ ["string","string","string"],#1 + ["string"],#2 + ["string","string"],#3 + ["string","string","string"],#4 + ["string","string"], #5 + ["string"], #6 + ["string","string","string"], #9 + ["string","string","string"], #11 + ["string", "string"], #12 + ["bool","bool","string","string"], #15 + ["string","string","string"], #16 + ["double","double", "double","double"] ]#17 +CyberPFAlg.AlgParValues = [ ["BarCol","Cluster1DCol","HalfClusterCol"],#1 + ["AllLocalMax"],#2 + ["AllLocalMax","TrackAxis"],#3 + ["AllLocalMax","LeftLocalMax","HoughAxis"],#4 + ["LeftLocalMax","ConeAxis"], #5 + ["MergedAxis"], #6 + ["MergedAxis","ESHalfCluster","ESTower"], #9 + ["ESHalfCluster","ESTower","EcalCluster"], #11 + ["HCALBarrel", "SimpleHCALCluster"], #12 + ["0","1","HCALBarrel","HCALCluster"], #15 + ["EcalCluster", "SimpleHCALCluster", "outputPFO"], #16 + ["1.26","4.", "1.", "4."] ]#17 + + +from Configurables import GenMatch +genmatch = GenMatch("GenMatch") +genmatch.nJets = 2 +genmatch.R = 0.6 +genmatch.OutputFile = "Jets_TDR_o1_v01.root" + +############################################################################## +# POD I/O +############################################################################## +from Configurables import PodioOutput +out = PodioOutput("outputalg") +out.filename = "Rec_TDR_o1_v01_00.root" +out.outputCommands = ["keep *"] + +######################################## + +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg=[inp, CyberPFAlg, out ], + EvtSel="NONE", + EvtMax=5, + ExtSvc=[podioevent, geomsvc], + #OutputLevel=DEBUG +) diff --git a/Detector/DetCRD/src/Calorimeter/LongCrystalBarEndcapCalorimeter_v02.cpp b/Detector/DetCRD/src/Calorimeter/LongCrystalBarEndcapCalorimeter_v02.cpp new file mode 100755 index 00000000..1fadab16 --- /dev/null +++ b/Detector/DetCRD/src/Calorimeter/LongCrystalBarEndcapCalorimeter_v02.cpp @@ -0,0 +1,598 @@ +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/DetType.h" +#include "XML/Layering.h" +#include "XML/Utilities.h" +#include "DDRec/DetectorData.h" +#include "DDSegmentation/BitField64.h" +#include "DDSegmentation/Segmentation.h" +#include "DDSegmentation/MultiSegmentation.h" +// #include "LcgeoExceptions.h" + +using namespace std; + +using dd4hep::BUILD_ENVELOPE; +using dd4hep::BitField64; +using dd4hep::Box; +using dd4hep::Trapezoid; +using dd4hep::Trap; +using dd4hep::EightPointSolid; +using dd4hep::DetElement; +using dd4hep::DetType; +using dd4hep::Detector; +using dd4hep::Layering; +using dd4hep::Material; +using dd4hep::PlacedVolume; +using dd4hep::Position; +using dd4hep::Readout; +using dd4hep::Ref_t; +using dd4hep::RotationX; +using dd4hep::RotationY; +using dd4hep::RotationZ; +using dd4hep::RotationZYX; +using dd4hep::Segmentation; +using dd4hep::SensitiveDetector; +using dd4hep::Transform3D; +using dd4hep::Translation3D; +using dd4hep::Volume; +using dd4hep::_toString; + +using dd4hep::rec::LayeredCalorimeterData; + +static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens) { + xml_det_t x_det = element; + Layering layering(x_det); +// xml_dim_t dim = x_det.dimensions(); + string det_name = x_det.nameStr(); + +// Material air = theDetector.air(); + Material stavesMaterial = theDetector.material(x_det.materialStr()); +// int numSides = dim.numsides(); + + int det_id = x_det.id(); + + DetElement sdet(det_name,det_id); + + PlacedVolume pVol; + + // --- create an envelope volume and position it into the world --------------------- + + Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, element , sdet ) ; + +// sdet.setTypeFlag( DetType::CALORIMETER | DetType::ENDCAP | DetType::HADRONIC ) ; + +// if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ; + //----------------------------------------------------------------------------------- + + sens.setType("calorimeter"); + DetElement stave_det("module0stave0part0",det_id); + + double EcalEndcap_inner_radius = theDetector.constant<double>("Ecal_endcap_inner_radius"); + double EcalEndcap_outer_radius = theDetector.constant<double>("Ecal_endcap_outer_radius"); + double EcalEndcap_min_z = theDetector.constant<double>("Ecal_endcap_zmin"); + double EcalEndcap_max_z = theDetector.constant<double>("Ecal_endcap_zmax"); + + double EcalEndcap_deadarea_thickness = theDetector.constant<double>("Ecal_deadarea_thickness"); + + + std::cout << "module_type: " << std::endl; + + int endcapID = 0; + + double dim_x = 0.001; + double dim_x1 = 0.001; + double dim_x2 = 0.001; + double dim_y = 0.001; + double dim_y1 = 0.001; + double dim_y2 = 0.001; + double dim_z = 0.001; + double box_half_x= 0.001; + double box_half_y= 0.001; + double box_half_z= 0.001; + double trap_half_x1= 0.001; + double trap_half_x2= 0.001; + double trap_half_y1= 0.001; + double trap_half_y2= 0.001; + double trap_half_z= 0.001; + + double pos_x = 0; + double pos_y = 0; + double pos_z = 0; + double EndcapModule_center_pos_x = 0; + double EndcapModule_center_pos_y = 0; + double EndcapModule_center_pos_z = 0; + + + int all_module = 0; + for(xml_coll_t c(x_det.child(_U(dimensions)),_U(dimensions)); c; ++c) { + xml_comp_t l(c); + int N_bar = 0; + double volume_bar = 0; + + int module_type = l.attr<int>(_Unicode(module_type)); + int module_tag = l.attr<int>(_Unicode(id)) - 1; + int module_number = l.attr<int>(_Unicode(module_number)); + + if(module_type == 0){ + dim_x = l.attr<double>(_Unicode(dim_x)); + dim_y = l.attr<double>(_Unicode(dim_y)); + dim_z = l.attr<double>(_Unicode(dim_z)); + pos_x = l.attr<double>(_Unicode(x_offset)); + pos_y = l.attr<double>(_Unicode(y_offset)); + pos_z = l.attr<double>(_Unicode(z_offset)); + box_half_x = dim_x/2.0; + box_half_y = dim_y/2.0; + box_half_z = dim_z/2.0; + } + else if(module_type == 1 || module_type == 4){ + dim_x1 = l.attr<double>(_Unicode(dim_x1)); + dim_x2 = l.attr<double>(_Unicode(dim_x2)); + dim_y1 = l.attr<double>(_Unicode(dim_y1)); + dim_y2 = l.attr<double>(_Unicode(dim_y2)); + dim_z = l.attr<double>(_Unicode(dim_z)); + pos_x = l.attr<double>(_Unicode(x_offset)); + pos_y = l.attr<double>(_Unicode(y_offset)); + pos_z = l.attr<double>(_Unicode(z_offset)); + trap_half_x1 = dim_x1/2; + trap_half_x2 = dim_x2/2; + trap_half_y1 = dim_y1/2; + trap_half_y2 = dim_y2/2; + trap_half_z = dim_z/2; + } + else if(module_type == 2 || module_type == 5){ + dim_x1 = l.attr<double>(_Unicode(dim_x1)); + dim_x2 = l.attr<double>(_Unicode(dim_x2)); + dim_x = l.attr<double>(_Unicode(dim_y1)); + dim_y = l.attr<double>(_Unicode(dim_y1)); + dim_y1 = l.attr<double>(_Unicode(dim_y1)); + dim_y2 = l.attr<double>(_Unicode(dim_y2)); + dim_z = l.attr<double>(_Unicode(dim_z)); + pos_x = l.attr<double>(_Unicode(x_offset)); + pos_y = l.attr<double>(_Unicode(y_offset)); + pos_z = l.attr<double>(_Unicode(z_offset)); + trap_half_x1 = dim_x1; + trap_half_x2 = dim_x2; + trap_half_y1 = dim_y1; + trap_half_y2 = dim_y2; + trap_half_z = dim_z; + } + else { + dim_x = l.attr<double>(_Unicode(dim_x)); + dim_y = l.attr<double>(_Unicode(dim_y)); + dim_z = l.attr<double>(_Unicode(dim_z)); + pos_x = l.attr<double>(_Unicode(x_offset)); + pos_y = l.attr<double>(_Unicode(y_offset)); + pos_z = l.attr<double>(_Unicode(z_offset)); + } + + + std::cout << "module_type: " << module_type << std::endl; + std::cout << "module_number: " << module_number << std::endl; + std::cout << "dim_x: " << dim_x << std::endl; + std::cout << "dim_x1: " << dim_x1 << std::endl; + std::cout << "dim_x2: " << dim_x2 << std::endl; + std::cout << "dim_y: " << dim_y << std::endl; + std::cout << "dim_y1: " << dim_y1 << std::endl; + std::cout << "dim_y2: " << dim_y2 << std::endl; + std::cout << "dim_z: " << dim_z << std::endl; + std::cout << "pos_x: " << pos_x << std::endl; + std::cout << "pos_y: " << pos_y << std::endl; + std::cout << "pos_z: " << pos_z << std::endl; + + + Box EndcapModule(box_half_x,box_half_y,box_half_z); + Trapezoid EndcapTrapIso(trap_half_x1, trap_half_x2, trap_half_y1, trap_half_y2, trap_half_z); + Trap EndcapTrapRight(trap_half_y1, trap_half_z, trap_half_x1, trap_half_x2); + double vertices[] = {-dim_x, -dim_x, -dim_x, dim_y, dim_y, dim_y, dim_y, -dim_x, -dim_x, -dim_x, -dim_x, dim_x, dim_x, dim_x, dim_x, -dim_x}; + EightPointSolid EndcapPrism(dim_z/2, vertices); + + string envelopeVol_name = det_name+_toString(endcapID,"_EndcapModule%d"); + string envelopeVolTrapIso_name = det_name+_toString(endcapID,"_EndcapModule%d"); + string envelopeVolTrapRight_name = det_name+_toString(endcapID,"_EndcapModule%d"); + string envelopeVolPrism_name = det_name+_toString(endcapID,"_EndcapModule%d"); + + Volume envelopeVol(envelopeVol_name,EndcapModule,stavesMaterial); + Volume envelopeVolTrapIso(envelopeVolTrapIso_name,EndcapTrapIso,stavesMaterial); + Volume envelopeVolTrapRight(envelopeVolTrapRight_name,EndcapTrapRight,stavesMaterial); + Volume envelopeVolPrism(envelopeVolPrism_name,EndcapPrism,stavesMaterial); + + envelopeVol.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + envelopeVolTrapIso.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + envelopeVolTrapRight.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + envelopeVolPrism.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + + double layer_pos_z = -dim_z/2; + int layer_num = 1; + + for(xml_coll_t m(x_det,_U(layer)); m; ++m){ + xml_comp_t x_layer = m; + int repeat = x_layer.repeat(); + double layer_thickness = x_layer.thickness(); + string layer_name = (module_type == 0) ? envelopeVol_name+_toString(0,"_Layer%d") : (module_type == 1 || module_type == 4) ? envelopeVolTrapIso_name+_toString(1,"_Layer%d") : (module_type == 2 || module_type == 5) ? envelopeVolTrapRight_name+_toString(2,"_Layer%d") : envelopeVolPrism_name+_toString(3,"_Layer%d"); + DetElement layer(stave_det, layer_name, det_id); + Material layer_material = theDetector.material(x_layer.materialStr()); + + if(module_type == 0){ // for cube first place bar then place layer + double rot_layer = 0; + double active_layer_dim_x = box_half_x - EcalEndcap_deadarea_thickness; + double active_layer_dim_y = box_half_y - EcalEndcap_deadarea_thickness; + double active_layer_dim_z = layer_thickness/2.0; + + Volume layer_vol(layer_name, Box(active_layer_dim_x, active_layer_dim_y, active_layer_dim_z), layer_material); + + + for (int ihardware = 0; ihardware < int(active_layer_dim_y*2/layer_thickness); ihardware++){ + + string hardware_name = layer_name + _toString(ihardware,"_hardware%d"); + Material hardware_material = layer_material; + DetElement hardware(layer, _toString(ihardware,"hardware%d"), det_id); + Volume hardware_vol(hardware_name,Box(active_layer_dim_x, layer_thickness / 2.0, layer_thickness/2.0), hardware_material); + hardware_vol.setSensitiveDetector(sens); + hardware_vol.setAttributes(theDetector,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); + PlacedVolume hardware_phv = layer_vol.placeVolume(hardware_vol,Position(0, -active_layer_dim_y + layer_thickness/2 + layer_thickness*ihardware, 0)); + hardware_phv.addPhysVolID("bar",ihardware); + hardware.setPlacement(hardware_phv); + + } + + layer_vol.setAttributes(theDetector,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); + + layer_pos_z += layer_thickness / 2.0; + + for (int j = 0; j < repeat; j++){ + + rot_layer = (j%2==0)? M_PI/2 : 0; + + PlacedVolume layer_phv = envelopeVol.placeVolume(layer_vol, Transform3D(RotationZYX(rot_layer, 0, 0), Position(0,0,layer_pos_z))); + if(j%2==0) layer_phv.addPhysVolID("slayer", 0).addPhysVolID("dlayer", layer_num); + else{ + layer_phv.addPhysVolID("slayer", 1).addPhysVolID("dlayer", layer_num); + ++layer_num; + } + + layer.setPlacement(layer_phv); + layer_pos_z += layer_thickness; + } + + N_bar = N_bar + int(active_layer_dim_y*2/layer_thickness)*repeat; + volume_bar = volume_bar + active_layer_dim_x*2*2*active_layer_dim_y*layer_thickness*repeat; + } + else{ //for trap first place layer then place bar + layer_pos_z += layer_thickness / 2.0; + double rot_layer = 0; + double delta_layer = 0; + for (int j = 0; j < repeat; j++){ + + delta_layer = (module_type == 1 || module_type == 4) ? layer_thickness*(trap_half_x1 - trap_half_x2)/dim_z : (module_type == 2 || module_type == 5) ? layer_thickness*(dim_x2 - dim_x1)/dim_z : layer_thickness*(dim_x-dim_y)/dim_z; + + double active_layer_dim_x = (module_type == 1 || module_type == 4) ? trap_half_y1 - EcalEndcap_deadarea_thickness : (module_type == 2 || module_type == 5) ? trap_half_x1/2 - EcalEndcap_deadarea_thickness + j*delta_layer/2 : (dim_x+dim_y)/2 - EcalEndcap_deadarea_thickness + j*delta_layer/2; + double active_layer_dim_y = (module_type == 1 || module_type == 4) ? trap_half_x1 - EcalEndcap_deadarea_thickness - j*delta_layer : (module_type == 2 || module_type == 5) ? layer_thickness/2.0 : (dim_x+dim_y)/2 - EcalEndcap_deadarea_thickness + j*delta_layer/2; + double active_layer_dim_z = (module_type == 1 || module_type == 4) ? layer_thickness/2.0 : (module_type == 2 || module_type == 5) ? trap_half_y1/2 - EcalEndcap_deadarea_thickness : layer_thickness/2.0; + + Volume layer_vol(layer_name, Box(active_layer_dim_x, active_layer_dim_y, active_layer_dim_z), layer_material); + int hardware_num = 0; + + if(module_type== 1){ + hardware_num = (j%2==0) ? int(active_layer_dim_x*2/layer_thickness) : int(active_layer_dim_y*2/layer_thickness); + } + else if(module_type== 2){ + hardware_num = (j%2==0) ? int(active_layer_dim_z*2/layer_thickness) : int(active_layer_dim_x*2/layer_thickness); + } + else if(module_type== 4){ + hardware_num = (j%2==0) ? int(active_layer_dim_y*2/layer_thickness) : int(active_layer_dim_x*2/layer_thickness); + } + else if(module_type== 5){ + hardware_num = (j%2==0) ? int(active_layer_dim_x*2/layer_thickness) : int(active_layer_dim_z*2/layer_thickness); + } + else { + hardware_num = (j%2==0) ? int(active_layer_dim_x*2/layer_thickness) : int(active_layer_dim_y*2/layer_thickness); + } + + double hardware_x = 0; + double hardware_y = 0; + double hardware_z = 0; + double hardware_x_pos = 0; + double hardware_y_pos = 0; + double hardware_z_pos = 0; + + for (int ihardware = 0; ihardware < hardware_num; ihardware++){ + string hardware_name = layer_name + _toString(ihardware,"_hardware%d"); + Material hardware_material = layer_material; + DetElement hardware(layer, _toString(j,"layer%d") + _toString(ihardware,"hardware%d"), det_id); + if(module_type== 1){ + hardware_x = (j%2==0) ? layer_thickness / 2.0 : active_layer_dim_x; + hardware_y = (j%2==0) ? active_layer_dim_y : layer_thickness / 2.0; + hardware_z = layer_thickness/2.0; + } + else if(module_type== 2){ + hardware_x = (j%2==0) ? active_layer_dim_x : layer_thickness / 2.0; + hardware_y = layer_thickness / 2.0; + hardware_z = (j%2==0) ? layer_thickness / 2.0 : active_layer_dim_z; + } + else if(module_type== 3 || module_type== 7){ + hardware_x = (j%2==1) ? layer_thickness / 2.0 : active_layer_dim_x; + hardware_y = (j%2==1) ? active_layer_dim_y : layer_thickness / 2.0; + hardware_z = layer_thickness / 2.0; + } + else if(module_type== 4){ + hardware_x = (j%2==0) ? active_layer_dim_x : layer_thickness / 2.0; + hardware_y = (j%2==0) ? layer_thickness / 2.0 : active_layer_dim_y; + hardware_z = layer_thickness/2.0; + } + else if(module_type== 5){ + hardware_x = (j%2==0) ? layer_thickness / 2.0 : active_layer_dim_x; + hardware_y = layer_thickness / 2.0; + hardware_z = (j%2==0) ? active_layer_dim_z : layer_thickness / 2.0; + } + else if(module_type== 6 || module_type== 8){ + hardware_x = (j%2==1) ? active_layer_dim_x : layer_thickness / 2.0; + hardware_y = (j%2==1) ? layer_thickness / 2.0 : active_layer_dim_y; + hardware_z = layer_thickness / 2.0; + } + Volume hardware_vol(hardware_name,Box(hardware_x, hardware_y, hardware_z), hardware_material); + hardware_vol.setSensitiveDetector(sens); + hardware_vol.setAttributes(theDetector,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); + + volume_bar = volume_bar + hardware_x*2*2*hardware_y*hardware_z*2; + + if(module_type== 1){ + hardware_x_pos = (j%2==0) ? -active_layer_dim_x + layer_thickness/2 + layer_thickness*ihardware : 0; + hardware_y_pos = (j%2==0) ? 0 : -active_layer_dim_y + layer_thickness/2 + layer_thickness*ihardware; + hardware_z_pos = 0; + } + else if(module_type== 2){ + hardware_x_pos = (j%2==0) ? 0 : -active_layer_dim_x + layer_thickness/2 + layer_thickness*ihardware; + hardware_y_pos = 0; + hardware_z_pos = (j%2==0) ? -active_layer_dim_z + layer_thickness/2 + layer_thickness*ihardware : 0; + } + else if(module_type== 3 || module_type== 7){ + hardware_x_pos = (j%2==1) ? -active_layer_dim_x + layer_thickness/2 + layer_thickness*ihardware : 0; + hardware_y_pos = (j%2==1) ? 0 : -active_layer_dim_y + layer_thickness/2 + layer_thickness*ihardware; + hardware_z_pos = 0; + } + else if(module_type== 4){ + hardware_x_pos = (j%2==0) ? 0 : -active_layer_dim_x + layer_thickness/2 + layer_thickness*ihardware; + hardware_y_pos = (j%2==0) ? -active_layer_dim_y + layer_thickness/2 + layer_thickness*ihardware: 0 ; + hardware_z_pos = 0; + } + else if(module_type== 5){ + hardware_x_pos = (j%2==0) ? -active_layer_dim_x + layer_thickness/2 + layer_thickness*ihardware : 0; + hardware_y_pos = 0; + hardware_z_pos = (j%2==0) ? 0 : -active_layer_dim_z + layer_thickness/2 + layer_thickness*ihardware; + } + else if(module_type== 6 || module_type== 8){ + hardware_x_pos = (j%2==1) ? 0 : -active_layer_dim_x + layer_thickness/2 + layer_thickness*ihardware; + hardware_y_pos = (j%2==1) ? -active_layer_dim_y + layer_thickness/2 + layer_thickness*ihardware: 0 ; + hardware_z_pos = 0; + } + PlacedVolume hardware_phv = layer_vol.placeVolume(hardware_vol,Position(hardware_x_pos, hardware_y_pos, hardware_z_pos)); + hardware_phv.addPhysVolID("bar", ihardware); + hardware.setPlacement(hardware_phv); + } + + layer_vol.setAttributes(theDetector,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); + rot_layer = M_PI/2; + PlacedVolume layer_phv; + layer_phv = (module_type == 1 || module_type == 4) ? envelopeVolTrapIso.placeVolume(layer_vol, Transform3D(RotationZYX(rot_layer, 0, 0), Position(0,0,layer_pos_z))) : (module_type == 2 || module_type == 5) ? envelopeVolTrapRight.placeVolume(layer_vol, Transform3D(RotationZYX( 0, 0, 0), Position( -(dim_x2 - dim_x1)/2 + j*delta_layer/2 + EcalEndcap_deadarea_thickness, layer_pos_z, 0))) : envelopeVolPrism.placeVolume(layer_vol, Position(-dim_x + active_layer_dim_x + EcalEndcap_deadarea_thickness, -dim_x + active_layer_dim_y + EcalEndcap_deadarea_thickness, layer_pos_z)); + if(j%2==0) layer_phv.addPhysVolID("slayer", 0).addPhysVolID("dlayer", layer_num); + else{ + layer_phv.addPhysVolID("slayer", 1).addPhysVolID("dlayer", layer_num); + ++layer_num; + } + layer.setPlacement(layer_phv); + layer_pos_z += layer_thickness; + + N_bar = N_bar + hardware_num; + } + } + } + + std::cout << "N_bar: " << N_bar << std::endl; + std::cout << "volume_bar: " << volume_bar << std::endl; + + int sector_sum = 0; + if(module_type==1 || module_type==4) sector_sum = module_number; + else if(module_type==3 || module_type==6 || module_type==7 || module_type==8) sector_sum = module_number; + else sector_sum = module_number*2 + 1; + + for (int sector_num=0;sector_num<sector_sum;sector_num++){ + if(module_type==2 && sector_num<module_number) continue; + if(module_type==5 && sector_num>module_number) continue; + + double EndcapModule_pos_x = 0; + double EndcapModule_pos_y = 0; + double EndcapModule_pos_z = pos_z; + double rot_EM = 0; + double rot_ES = 0; + double rot_EZ = 0; + double rot_EY = 0; + double rot_EX = 0; + + if(module_type==0 ){ + if(sector_num<module_number){ + EndcapModule_pos_x = pos_x; + EndcapModule_pos_y = pos_y + (module_number-sector_num)*dim_y; + } + else if(sector_num==module_number){ + EndcapModule_pos_x = pos_x; + EndcapModule_pos_y = pos_y; + } + else{ + EndcapModule_pos_x = pos_x + (sector_num-module_number)*dim_x; + EndcapModule_pos_y = pos_y; + } + } + else if(module_type==1 || module_type==4){ + EndcapModule_pos_x = pos_x + sector_num*dim_y2; + EndcapModule_pos_y = pos_y; + } + else if(module_type==2 || module_type==5){ + if(sector_num<module_number){ + EndcapModule_pos_x = pos_y; + EndcapModule_pos_y = pos_x + (module_number-sector_num)*dim_y; + } + else if(sector_num==module_number){ + EndcapModule_pos_x = pos_x; + EndcapModule_pos_y = pos_y; + } + else{ + EndcapModule_pos_x = pos_x + (sector_num-module_number)*dim_x; + EndcapModule_pos_y = pos_y; + } + } + else{ + EndcapModule_pos_x = pos_x; + EndcapModule_pos_y = pos_y; + } + + + for(int stave_num=0;stave_num<4;stave_num++){ + if(module_type==1 && (stave_num==1 || stave_num==3)) continue; + if(module_type==4 && (stave_num==0 || stave_num==2)) continue; + if((module_type==3 || module_type==8) && (stave_num==1 || stave_num==3)) continue; + if((module_type==6 || module_type==7) && (stave_num==0 || stave_num==2)) continue; + + // Set the ID. The ID is composed of the module number, the stave number, the part number. + int stave_id = 0; + int part_id = 0; + if(module_type == 0){ + if(stave_num==0 && sector_num<=module_number) { stave_id = 7 + module_tag; part_id = sector_num; } + if(stave_num==0 && sector_num>module_number) { stave_id = sector_num + 4 + 2*module_tag; part_id = 3 - module_tag; } + if(stave_num==1 && sector_num<=module_number) { stave_id = 3 - module_tag; part_id = sector_num; } + if(stave_num==1 && sector_num>module_number) { stave_id = 6 - 2*module_tag - sector_num; part_id = 3 - module_tag; } + if(stave_num==2 && sector_num<=module_number) { stave_id = 3 - module_tag; part_id = 10 - sector_num; } + if(stave_num==2 && sector_num>module_number) { stave_id = 6 - 2*module_tag - sector_num; part_id = 7 + module_tag; } + if(stave_num==3 && sector_num<=module_number) { stave_id = 7 + module_tag; part_id = 10 - sector_num; } + if(stave_num==3 && sector_num>module_number) { stave_id = sector_num + 4 + 2*module_tag; part_id = 7 + module_tag; } + } + else if(module_type == 1 || module_type == 4) { + if(stave_num==0) { stave_id = 7 + sector_num; part_id = 5; } + if(stave_num==1) { stave_id = 5; part_id = 3 - sector_num; } + if(stave_num==2) { stave_id = 3 - sector_num; part_id = 5; } + if(stave_num==3) { stave_id = 5; part_id = 7 + sector_num; } + } + else if(module_type == 2){ + if(stave_num==0) { stave_id = 2 + sector_num; part_id = 4; } + if(stave_num==1) { stave_id = 8 - sector_num; part_id = 4; } + if(stave_num==2) { stave_id = 8 - sector_num; part_id = 6; } + if(stave_num==3) { stave_id = 2 + sector_num; part_id = 6; } + } + else if(module_type == 5){ + if(stave_num==0) { stave_id = 6; part_id = sector_num; } + if(stave_num==1) { stave_id = 4; part_id = sector_num; } + if(stave_num==2) { stave_id = 4; part_id = 10 - sector_num; } + if(stave_num==3) { stave_id = 6; part_id = 10 - sector_num; } + } + else { + if(stave_num==0) { stave_id = 6; part_id = 4; } + if(stave_num==1) { stave_id = 4; part_id = 4; } + if(stave_num==2) { stave_id = 4; part_id = 6; } + if(stave_num==3) { stave_id = 6; part_id = 6; } + } + + + + + + double rot_FZ = 0; + double rot_FY = 0; + double rot_FX = 0; + + if(module_type==0){ + EndcapModule_center_pos_x = (stave_num == 0) ? EndcapModule_pos_x : (stave_num == 1) ? -EndcapModule_pos_x : (stave_num == 2) ? -EndcapModule_pos_x : EndcapModule_pos_x; + EndcapModule_center_pos_y = (stave_num == 0) ? EndcapModule_pos_y : (stave_num == 1) ? EndcapModule_pos_y : (stave_num == 2) ? -EndcapModule_pos_y : -EndcapModule_pos_y; + } + else if(module_type==1 || module_type==4){ + EndcapModule_center_pos_x = (stave_num == 0) ? EndcapModule_pos_x : (stave_num == 1) ? EndcapModule_pos_y : (stave_num == 2) ? -EndcapModule_pos_x : EndcapModule_pos_y; + EndcapModule_center_pos_y = (stave_num == 0) ? EndcapModule_pos_y : (stave_num == 1) ? EndcapModule_pos_x : (stave_num == 2) ? -EndcapModule_pos_y : -EndcapModule_pos_x; + } + else{ + EndcapModule_center_pos_x = (stave_num == 0) ? EndcapModule_pos_x : (stave_num == 1) ? -EndcapModule_pos_x : (stave_num == 2) ? -EndcapModule_pos_x : EndcapModule_pos_x; + EndcapModule_center_pos_y = (stave_num == 0) ? EndcapModule_pos_y : (stave_num == 1) ? EndcapModule_pos_y : (stave_num == 2) ? -EndcapModule_pos_y : -EndcapModule_pos_y; + } + + rot_ES = (stave_num == 0) ? M_PI/2 : (stave_num == 1) ? 0 : (stave_num == 2) ? M_PI/2 : 0; + if(sector_num<=module_number) rot_EX = (stave_num == 0) ? M_PI : (stave_num == 1) ? 0 : (stave_num == 2) ? 0 : M_PI; + else rot_EX = (stave_num == 0) ? M_PI+M_PI/2 : (stave_num == 1) ? 0-M_PI/2 : (stave_num == 2) ? 0+M_PI/2 : M_PI-M_PI/2; + rot_EZ = (stave_num == 0) ? 0 : (stave_num == 1) ? 0 : (stave_num == 2) ? 0 : 0; + + + for(int module_num=0;module_num<2;module_num++) { + if(module_num==0 && (module_type==7 || module_type==8)) continue; + if(module_num==1 && (module_type==3 || module_type==6)) continue; + + int module_id = (module_num==0)? 0:1; + + if(module_type==2 || module_type==5){ + if(sector_num<=module_number) rot_EM = (module_id==0)?M_PI*3/2: M_PI/2; + else rot_EM = (module_id==0)?M_PI*3/2: M_PI/2; + if(sector_num>module_number) rot_EY = (module_id==0)? rot_EX+M_PI : rot_EX; + else rot_EY = rot_EX; + } + else rot_EM = (module_id==0)?M_PI:0; + + EndcapModule_center_pos_z = (module_id==0)? -EndcapModule_pos_z:EndcapModule_pos_z; + + PlacedVolume env_phv; + if(module_type==0){ + env_phv = envelope.placeVolume(envelopeVol, + Transform3D(RotationX(rot_EM), + Translation3D(EndcapModule_center_pos_x, + EndcapModule_center_pos_y, + EndcapModule_center_pos_z))); + env_phv.addPhysVolID("module", module_id).addPhysVolID("type", module_tag).addPhysVolID("part", part_id).addPhysVolID("stave", stave_id); + all_module++; + } + else if(module_type==1 || module_type==4){ + env_phv = envelope.placeVolume(envelopeVolTrapIso, + Transform3D(RotationZYX(rot_ES, 0, rot_EM), + Position(EndcapModule_center_pos_x, + EndcapModule_center_pos_y, + EndcapModule_center_pos_z))); + env_phv.addPhysVolID("module", module_id).addPhysVolID("type", module_tag).addPhysVolID("part", part_id).addPhysVolID("stave", stave_id); + all_module++; + } + else if(module_type==2 || module_type==5){ + if(sector_num==module_number){ + continue; + } + else{ + env_phv = envelope.placeVolume(envelopeVolTrapRight, + Transform3D(RotationZYX(rot_EZ, rot_EY, rot_EM), + Position(EndcapModule_center_pos_x, + EndcapModule_center_pos_y, + EndcapModule_center_pos_z))); + env_phv.addPhysVolID("module", module_id).addPhysVolID("type", module_tag).addPhysVolID("part", part_id).addPhysVolID("stave", stave_id); + all_module++; + } + } + else{ + if(module_id==0){ + rot_FZ = (stave_num == 0) ? M_PI/2 : (stave_num == 1) ? 0: (stave_num == 2) ? -M_PI/2 : M_PI; + } + else{ + rot_FZ = (stave_num == 0) ? M_PI : (stave_num == 1) ? -M_PI/2 : (stave_num == 2) ? 0 : M_PI/2; + } + rot_FY = (stave_num == 0) ? 0 : (stave_num == 1) ? 0 : (stave_num == 2) ? 0 : 0; + rot_FX = (module_id==0)?M_PI:0; + + env_phv = envelope.placeVolume(envelopeVolPrism, + Transform3D(RotationZYX(rot_FZ, rot_FY, rot_FX), + Position(EndcapModule_center_pos_x, + EndcapModule_center_pos_y, + EndcapModule_center_pos_z))); + env_phv.addPhysVolID("module", module_id).addPhysVolID("type", module_tag).addPhysVolID("part", part_id).addPhysVolID("stave", stave_id); + all_module++; + } + + DetElement sd = (module_id==0&&part_id==0&&stave_id==0) ? stave_det : stave_det.clone(_toString(module_id,"module%d")+_toString(stave_id,"stave%d")+_toString(part_id,"part%d")); + sd.setPlacement(env_phv); + } + } + } + endcapID++; + } + cout<<"EndcapModule: "<<all_module<<endl; + return sdet; +} + +DECLARE_DETELEMENT(LongCrystalBarEndcapCalorimeter_v02, create_detector) \ No newline at end of file diff --git a/Digitization/DigiCalo/CMakeLists.txt b/Digitization/DigiCalo/CMakeLists.txt index c3b4182c..79f1d1d9 100644 --- a/Digitization/DigiCalo/CMakeLists.txt +++ b/Digitization/DigiCalo/CMakeLists.txt @@ -1,6 +1,7 @@ # Modules gaudi_add_module(CaloDigi SOURCES src/EcalDigiAlg.cpp + SOURCES src/EcalDigiAlgShort.cpp SOURCES src/HcalDigiAlg.cpp LINK k4FWCore::k4FWCore GearSvc diff --git a/Digitization/DigiCalo/src/CaloBar.h b/Digitization/DigiCalo/src/CaloBar.h index 57d226bb..cff95a9d 100644 --- a/Digitization/DigiCalo/src/CaloBar.h +++ b/Digitization/DigiCalo/src/CaloBar.h @@ -18,9 +18,11 @@ public: int getSystem() const { return system; } int getModule() const { return module; } int getStave() const { return stave; } + int getPart() const { return part; } int getDlayer() const { return dlayer; } int getSlayer() const { return slayer; } int getBar() const { return bar; } + double getLength() const { return length; } double getQ1() const { return Q1; } double getQ2() const { return Q2; } double getT1() const { return T1; } @@ -30,19 +32,22 @@ public: double getEnergy() const { return (Q1+Q2)/2.; } void setcellID(unsigned long long _cellid) { cellID = _cellid; } - void setcellID(int _system, int _module, int _stave, int _dlayer, int _slayer, int _bar) { system=_system; module=_module; stave=_stave; dlayer=_dlayer; slayer=_slayer; bar=_bar; } + void setcellID(int _system, int _module, int _stave, int _part, int _dlayer, int _slayer, int _bar) { system=_system; module=_module; stave=_stave; part=_part; dlayer=_dlayer; slayer=_slayer; bar=_bar; } void setPosition( TVector3 posv3) { position.SetXYZ( posv3.x(), posv3.y(), posv3.z() ); } void setQ(double _q1, double _q2) { Q1=_q1; Q2=_q2; } void setT(double _t1, double _t2) { T1=_t1; T2=_t2; } + void setLength(double _length) { length = _length; } private: unsigned long long cellID; int system; int module; int stave; + int part; int dlayer; int slayer; int bar; + double length; TVector3 position; double Q1; // Q in left readout double Q2; // Q in right readout; diff --git a/Digitization/DigiCalo/src/CaloCrystalShort.h b/Digitization/DigiCalo/src/CaloCrystalShort.h new file mode 100644 index 00000000..2ed3da2c --- /dev/null +++ b/Digitization/DigiCalo/src/CaloCrystalShort.h @@ -0,0 +1,89 @@ +#ifndef _CRD_CALOCRYSTALSHORT_ +#define _CRD_CALOCRYSTALSHORT_ + +#include <DD4hep/Objects.h> +#include "TVector3.h" + +class CaloCrystalShort +{ +public: + CaloCrystalShort(unsigned long long _cellID, int _system, int _module, int _stave, int _layer, int _phi_x, int _z_y, TVector3 _pos, double _Q, double _T) + : cellID(_cellID), system(_system), module(_module), stave(_stave), layer(_layer), phi_x(_phi_x), z_y(_z_y), position(_pos), Q(_Q), T(_T) {}; + /* + CaloCrystalShort(unsigned long long _cellID, int _system, int _module, int _stave, int _layer, int _x, int _y, TVector3 _pos, double _Q, double _T) + : cellID(_cellID), system(_system), module(_module), stave(_stave), layer(_layer), x(_x), y(_y), position(_pos), Q(_Q), T(_T) {}; + */ + + CaloCrystalShort() {}; + + inline bool operator==(const CaloCrystalShort& x) const + { + return ((cellID == x.cellID) && getEnergy() == x.getEnergy()); + } + + unsigned long long getcellID() const { return cellID; } + + int getSystem() const { return system; } + + int getModule() const { return module; } + + int getStave() const { return stave; } + + int getLayer() const { return layer; } + + int getPhiX() const { return phi_x; } + + int getZY() const { return z_y; } + + double getQ() const { return Q; } + + double getT() const { return T; } + + TVector3 getPosition() const { return position; } + + double getEnergy() const { return Q; } + + void setcellID(unsigned long long _cellid) { cellID = _cellid; } + + void setcellID(int _system, int _module, int _stave, int _layer, int _phi_x, int _z_y) + { + system = _system; + module = _module; + stave = _stave; + layer = _layer; + phi_x = _phi_x; + z_y = _z_y; + } + + /* + void setcellID(int _system, int _module, int _stave, int _layer, int _x, int _y) + { + system = _system; + module = _module; + stave = _stave; + layer = _layer; + x = _x; + y = _y; + } + */ + + void setPosition(TVector3 posv3) { position.SetXYZ(posv3.x(), posv3.y(), posv3.z()); } + + void setQ(double _q) { Q = _q; } + + void setT(double _t) { T = _t; } + +private: + unsigned long long cellID; + int system; + int module; + int stave; + int layer; + int phi_x; + int z_y; + TVector3 position; + double Q; // Charge in readout + double T; // Time in readout; +}; + +#endif diff --git a/Digitization/DigiCalo/src/EcalDigiAlg.cpp b/Digitization/DigiCalo/src/EcalDigiAlg.cpp index 504a8288..f901df32 100644 --- a/Digitization/DigiCalo/src/EcalDigiAlg.cpp +++ b/Digitization/DigiCalo/src/EcalDigiAlg.cpp @@ -40,17 +40,59 @@ EcalDigiAlg::EcalDigiAlg(const std::string& name, ISvcLocator* svcLoc) { // Input collections - declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); + //declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); // Output collections - declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); - declareProperty("CaloAssociationCollection", w_CaloAssociationCol, "Handle of CaloAssociation collection"); - declareProperty("CaloMCPAssociationCollection", w_MCPCaloAssociationCol, "Handle of CaloAssociation collection"); + //declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); + //declareProperty("CaloAssociationCollection", w_CaloAssociationCol, "Handle of CaloAssociation collection"); + //declareProperty("CaloMCPAssociationCollection", w_MCPCaloAssociationCol, "Handle of CaloAssociation collection"); } StatusCode EcalDigiAlg::initialize() { + // --- Initialize input and output collections + for(auto& simhit : name_SimCaloHit){ + if(!simhit.empty()) + _inputSimHitCollection.push_back( new SimCaloType(simhit, Gaudi::DataHandle::Reader, this) ); + } + + // --- Geometry service, cellID decoder + m_geosvc = service<IGeomSvc>("GeomSvc"); + if ( !m_geosvc ) throw "EcalDigiAlg :Failed to find GeomSvc ..."; + m_dd4hep = m_geosvc->lcdd(); + if ( !m_dd4hep ) throw "EcalDigiAlg :Failed to get dd4hep::Detector ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + + for(unsigned int i=0; i<name_Readout.size(); i++){ + if(name_Readout[i].empty()) continue; + dd4hep::DDSegmentation::BitFieldCoder* tmp_decoder = m_geosvc->getDecoder(name_Readout[i]); + if (!tmp_decoder) { + error() << "Failed to get the decoder for: " << name_Readout[i] << endmsg; + return StatusCode::FAILURE; + } + map_readout_decoder[name_SimCaloHit[i]] = tmp_decoder; + } + + m_volumeManager = m_dd4hep->volumeManager(); + + // --- Output collection + for(auto& digihit : name_CaloHit){ + if(!digihit.empty()) + _outputHitCollection.push_back( new CaloType(digihit, Gaudi::DataHandle::Writer, this) ); + } + + for(auto& link : name_CaloAsso){ + if(!link.empty()) + _outputCaloSimAssoCol.push_back( new CaloSimAssoType(link, Gaudi::DataHandle::Writer, this) ); + } + + for(auto& link : name_CaloMCPAsso){ + if(!link.empty()) + _outputCaloMCPAssoCol.push_back( new CaloParticleAssoType(link, Gaudi::DataHandle::Writer, this) ); + } + + // --- Ntuple if(_writeNtuple){ std::string s_outfile = _filename; m_wfile = new TFile(s_outfile.c_str(), "recreate"); @@ -68,35 +110,102 @@ StatusCode EcalDigiAlg::initialize() t_SimCont->Branch("step_T2", &m_step_T2); t_SimBar->Branch("totE_Truth", &totE_Truth); t_SimBar->Branch("totE_Digi", &totE_Digi); + t_SimBar->Branch("mean_CT", &mean_CT); + t_SimBar->Branch("ECALTemp", &ECALTemp); t_SimBar->Branch("simBar_x", &m_simBar_x); t_SimBar->Branch("simBar_y", &m_simBar_y); t_SimBar->Branch("simBar_z", &m_simBar_z); t_SimBar->Branch("simBar_T1", &m_simBar_T1); t_SimBar->Branch("simBar_T2", &m_simBar_T2); - t_SimBar->Branch("simBar_Q1_Truth", &m_simBar_Q1_Truth); - t_SimBar->Branch("simBar_Q2_Truth", &m_simBar_Q2_Truth); + t_SimBar->Branch("simBar_E_Truth", &m_simBar_E_Truth); + t_SimBar->Branch("simBar_ChannelTemp", &m_simBar_ChannelTemp); + t_SimBar->Branch("simBar_CryTID", &m_simBar_CryTID); + t_SimBar->Branch("simBar_SiPMNIEL", &m_simBar_SiPMNIEL); + t_SimBar->Branch("simBar_CryIntLY", &m_simBar_CryIntLY); + t_SimBar->Branch("simBar_SiPMGain", &m_simBar_SiPMGain); + t_SimBar->Branch("simBar_SiPMDCR", &m_simBar_SiPMDCR); + t_SimBar->Branch("simBar_ScinGen", &m_simBar_Scint); + t_SimBar->Branch("simBar_LO1", &m_simBar_LO1 ); + t_SimBar->Branch("simBar_NDC1", &m_simBar_NDC1 ); + t_SimBar->Branch("simBar_NDetPE1", &m_simBar_NDetPE1 ); + t_SimBar->Branch("simBar_Pedestal1", &m_simBar_Pedestal1 ); + t_SimBar->Branch("simBar_ADC1", &m_simBar_ADC1 ); + t_SimBar->Branch("simBar_ADCGain1", &m_simBar_ADCGain1 ); + t_SimBar->Branch("simBar_LO2", &m_simBar_LO2 ); + t_SimBar->Branch("simBar_NDC2", &m_simBar_NDC2 ); + t_SimBar->Branch("simBar_NDetPE2", &m_simBar_NDetPE2 ); + t_SimBar->Branch("simBar_Pedestal2", &m_simBar_Pedestal2 ); + t_SimBar->Branch("simBar_ADC2", &m_simBar_ADC2 ); + t_SimBar->Branch("simBar_ADCGain2", &m_simBar_ADCGain2 ); + t_SimBar->Branch("simBar_Q1_Att", &m_simBar_Q1_Att); + t_SimBar->Branch("simBar_Q2_Att", &m_simBar_Q2_Att); t_SimBar->Branch("simBar_Q1_Digi", &m_simBar_Q1_Digi); t_SimBar->Branch("simBar_Q2_Digi", &m_simBar_Q2_Digi); + t_SimBar->Branch("simBar_length", &m_simBar_length); + t_SimBar->Branch("simBar_system", &m_simBar_system); t_SimBar->Branch("simBar_module", &m_simBar_module); t_SimBar->Branch("simBar_stave", &m_simBar_stave); + t_SimBar->Branch("simBar_part", &m_simBar_part); t_SimBar->Branch("simBar_dlayer", &m_simBar_dlayer); t_SimBar->Branch("simBar_slayer", &m_simBar_slayer); + t_SimBar->Branch("simBar_bar", &m_simBar_bar); t_SimBar->Branch("simBar_cellID", &m_simBar_cellID); } - std::cout<<"EcalDigiAlg::m_scale="<<m_scale<<std::endl; - m_geosvc = service<IGeomSvc>("GeomSvc"); - if ( !m_geosvc ) throw "EcalDigiAlg :Failed to find GeomSvc ..."; - m_dd4hep = m_geosvc->lcdd(); - if ( !m_dd4hep ) throw "EcalDigiAlg :Failed to get dd4hep::Detector ..."; - m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); - m_decoder = m_geosvc->getDecoder(_readoutName); - if (!m_decoder) { - error() << "Failed to get the decoder. " << endmsg; - return StatusCode::FAILURE; + std::cout<<"Set Random seed: "<<_seed<<endl; + rndm.SetSeed(_seed); + + // SiPM response function + f_SiPMResponse = new TF1("f_SiPMResponse", "((1-[1])*[0]*(1-exp(-x/[0]))+[1]*x)*([2]+1)/( [2]+x / ([0]*(1-exp(-x/[0]))) )*(1+[3]*exp(-x/[0]))", 0, 1e+9); + f_SiPMResponse->SetParameters(6.19783e+06, 5.08847e-01, 1.27705e+01, fEcalSiPMCT); + f_SiPMSigmaDet = new TF1("f_SiPMSigmaDet", "8.336e-01*sqrt(x+0.2379)", 0, 1e+9); + f_SiPMSigmaRecp = new TF1("f_SiPMSigmaRecp", "f_SiPMResponse+f_SiPMSigmaDet", 0, 1e+9); + f_SiPMSigmaRecm = new TF1("f_SiPMSigmaRecm", "f_SiPMResponse-f_SiPMSigmaDet", 0, 1e+9); + f_AsymGauss = new TF1("AsymGauss", [](double *x, double *par) -> double + { + double val = x[0]; + double mean = par[0]; + double sigma_left = par[1]; + double sigma_right = par[2]; + + if (val < mean) { + return exp(-0.5 * pow((val - mean) / sigma_left, 2)); + } else { + return exp(-0.5 * pow((val - mean) / sigma_right, 2)); + } + }, -10, 10, 3); + + // SiPM noise model: Borel distribution + f_DarkNoise = new TF1("f_DarkNoise", "pow([0]*x, x-1) * exp(-[0]*x) / TMath::Factorial(x)"); + f_DarkNoise->SetParameter(0, fEcalSiPMCT); + + g_CryLYRatio_vs_TID = new TGraph(); + float TID [8] = {50, 230.043, 731.681, 3448.96, 118953, 1.01164e+7, 1.02341e+8, 2.04907e+8}; + float CryLYRatio_TID[8] = {0.99, 0.774091, 0.689545, 0.633636, 0.588636, 0.549091, 0.401818, 0.374545}; + for (int i = 0; i < 8; i++) { + g_CryLYRatio_vs_TID->SetPoint(i, TID[i], CryLYRatio_TID[i]); + } + + g_SiPMDCR_vs_NIEL = new TGraph(); + float NIEL[24] = { 9.9e+6, + 1.00000e+7, 2.49756e+7, 5.25408e+7, 1.10530e+8, 2.11374e+8, + 4.04227e+8, 6.63661e+8, 1.02902e+9, 1.68944e+9, 2.77373e+9, + 4.38351e+9, 6.41879e+9, 9.22154e+9, 1.40281e+10, 2.01534e+10, + 3.12481e+10, 4.48925e+10, 7.09466e+10, 1.33114e+11, 1.91238e+11, + 3.13975e+11, 4.51070e+11, 6.48029e+11 + }; + float DCR_NIEL[24] = { 1e+5, + 105925, 145378, 230409, 354813, 595662, + 1.09018e+6, 1.72783e+6, 2.58523e+6, 4.21697e+6, 6.68344e+6, + 1.02920e+7, 1.58489e+7, 2.44062e+7, 3.98107e+7, 5.95662e+7, + 9.44061e+7, 1.37246e+8, 2.17520e+8, 3.65174e+8, 5.01187e+8, + 7.28618e+8, 9.44061e+8, 1.18850e+9 + }; + for (int i = 0; i < 24; i++) { + DCR_NIEL[i] = DCR_NIEL[i] / 1e+5; // unit: MHz/cm^2 + g_SiPMDCR_vs_NIEL->SetPoint(i, NIEL[i], DCR_NIEL[i]); } - rndm.SetSeed(_seed); std::cout<<"EcalDigiAlg::initialize"<<std::endl; return GaudiAlgorithm::initialize(); } @@ -112,311 +221,434 @@ StatusCode EcalDigiAlg::execute() Clear(); - const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); - edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); - edm4hep::MCRecoCaloAssociationCollection* caloAssoVec = w_CaloAssociationCol.createAndPut(); - edm4hep::MCRecoCaloParticleAssociationCollection* caloMCPAssoVec = w_MCPCaloAssociationCol.createAndPut(); - std::vector<edm4hep::SimCalorimeterHit> m_simhitCol; m_simhitCol.clear(); - std::vector<CaloBar> m_barCol; m_barCol.clear(); - - if(SimHitCol == 0){ - std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; - return StatusCode::SUCCESS; - } - - if(_Debug>=1) std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; - - totE_Truth=0; - totE_Digi=0; - - //Merge input simhit(steps) to real simhit(bar). - MergeHits(*SimHitCol, m_simhitCol); - if(_Debug>=1) std::cout<<"Finish Hit Merge, with Nhit: "<<m_simhitCol.size()<<std::endl; - - // DetElement beamcal = m_dd4hep->detector("CaloDetector"); - // LayeredCalorimeterData* bcExtension = beamcal.extension<LayeredCalorimeterData>(); - // std::vector<LayeredCalorimeterStruct::Layer> layers = bcExtension->layers; - - //Loop in SimHit, digitalize SimHit to DigiBar - for(int i=0;i<m_simhitCol.size();i++){ - - auto SimHit = m_simhitCol.at(i); - - unsigned long long id = SimHit.getCellID(); - CaloBar hitbar; - hitbar.setcellID( id); - hitbar.setcellID( m_decoder->get(id, "system"), - m_decoder->get(id, "module"), - m_decoder->get(id, "stave"), - m_decoder->get(id, "dlayer"), - m_decoder->get(id, "slayer"), - m_decoder->get(id, "bar")); - - double Lbar = GetBarLength(hitbar); //NOTE: Is fixed with geometry LongCrystalBarBarrelCalorimeter32Polygon_v01. - - dd4hep::Position hitpos = m_cellIDConverter->position(id); - TVector3 barpos(10*hitpos.x(), 10*hitpos.y(), 10*hitpos.z()); //cm to mm. - hitbar.setPosition(barpos); - - //printf("in bar #%d: cellID [%d, %d, %d, %d], position (%.3f, %.3f, %.3f), energy %.3f \n", hitbar.getModule(), hitbar.getStave(), hitbar.getDlayer(), hitbar.getSlayer(), hitbar.getBar(), - // 10*hitpos.x(), 10*hitpos.y(), 10*hitpos.z(), SimHit.getEnergy() ); - - MCParticleToEnergyWeightMap MCPEnMap; MCPEnMap.clear(); - std::vector<HitStep> DigiLvec; DigiLvec.clear(); - std::vector<HitStep> DigiRvec; DigiRvec.clear(); - double totQ1_Truth = 0; - double totQ2_Truth = 0; - double totQ1_Digi = 0; - double totQ2_Digi = 0; - double totQ1 = 0; - double totQ2 = 0; - - //Loop in all SimHitContribution(G4Step). - //if(_Debug>=2) std::cout<<"SimHit contribution size: "<<SimHit.contributions_size()<<std::endl; - for(int iCont=0; iCont < SimHit.contributions_size(); ++iCont){ - auto conb = SimHit.getContributions(iCont); - if( !conb.isAvailable() ) { std::cout<<"EcalDigiAlg Can not get SimHitContribution: "<<iCont<<std::endl; continue;} - - double en = conb.getEnergy(); - if(en == 0) continue; - - auto mcp = conb.getParticle(); - MCPEnMap[mcp] += en; - TVector3 steppos(conb.getStepPosition().x, conb.getStepPosition().y, conb.getStepPosition().z); - TVector3 rpos = steppos-hitbar.getPosition(); - float step_time = conb.getTime(); // yyy: step time - - m_step_x.push_back(steppos.x()); - m_step_y.push_back(steppos.y()); - m_step_z.push_back(steppos.z()); - m_step_t.push_back(step_time); // yyy: push back step time - m_step_E.push_back(en); - m_stepBar_x.push_back(hitbar.getPosition().x()); - m_stepBar_y.push_back(hitbar.getPosition().y()); - m_stepBar_z.push_back(hitbar.getPosition().z()); - - if(_Debug>=3){ - cout<<"Cell Pos: "<<hitbar.getPosition().x()<<'\t'<<hitbar.getPosition().y()<<'\t'<<hitbar.getPosition().z()<<endl; - cout<<"step pos: "<<steppos.x()<<'\t'<<steppos.y()<<'\t'<<steppos.z()<<endl; - cout<<"Relative pos: "<<rpos.x()<<'\t'<<rpos.y()<<'\t'<<rpos.z()<<endl; - cout<<"Cell: "<<hitbar.getModule()<<" "<<hitbar.getDlayer()<<" "<<hitbar.getSlayer()<<endl; - } - - //Get digitalized signal(Q1, Q2, T1, T2) from step - //Define: 1 is left, 2 is right, clockwise direction in phi. - - int sign=-999; - if(hitbar.getSlayer()==1) sign = rpos.z()==0 ? 1 : rpos.z()/fabs(rpos.z()); - else{ - int _module = hitbar.getModule(); - if(_module<=7 || _module>=25) sign = rpos.x()==0 ? 1: rpos.x()/fabs(rpos.x()); - if(_module>=9 && _module<=23) sign = rpos.x()==0 ? -1:-rpos.x()/fabs(rpos.x()); - else if(_module==8) sign = rpos.y()==0 ? 1: rpos.y()/fabs(rpos.y()); - else if(_module==24) sign = rpos.y()==0 ? -1:-rpos.y()/fabs(rpos.y()); - - } - if(!fabs(sign)) {std::cout<<"ERROR: Wrong bar direction/position!"<<std::endl; continue;} - - // ####### For Charge Digitization ####### - double Ratio_left = exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt) / (exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt) + exp(-(Lbar/2 - sign*sqrt(rpos.Mag2()))/Latt)); - double Ratio_right = 1 - Ratio_left; - totQ1_Truth += en*Ratio_left; - totQ2_Truth += en*Ratio_right; - - // ####### For Time Digitization ####### - double Qi_left = en*exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt); - double Qi_right = en*exp(-(Lbar/2 - sign*sqrt(rpos.Mag2()))/Latt); - - if(_Debug>=3){ - cout<<Qi_left<<'\t'<<Qi_right<<endl; - cout<<Lbar<<'\t'<<sign*sqrt(rpos.Mag2())<<endl; - } - - double Ti_left = -1; int looptime=0; - while(Ti_left<0){ - // Ti_left = Tinit + rndm.Gaus(nMat*(Lbar/2 + sign*sqrt(rpos.Mag2()))/C, Tres); - Ti_left = Tinit + rndm.Gaus(nMat*(Lbar/2 + sign*sqrt(rpos.Mag2()))/C, Tres) + step_time; // yyy: add step time - looptime++; - if(looptime>500){ std::cout<<"ERROR: Step "<<iCont<<" can not get a positive left-side time!"<<std::endl; break;} - } - if(looptime>500) continue; - double Ti_right = -1; looptime=0; - while(Ti_right<0){ - // Ti_right = Tinit + rndm.Gaus(nMat*(Lbar/2 - sign*sqrt(rpos.Mag2()))/C, Tres); - Ti_right = Tinit + rndm.Gaus(nMat*(Lbar/2 - sign*sqrt(rpos.Mag2()))/C, Tres) + step_time; // yyy: add step time - looptime++; - if(looptime>500){ - std::cout<<"ERROR: Step "<<iCont<<" can not get a positive right-side time!"<<std::endl; - std::cout<<" Initial time "<<Tinit<<", transport time central value "<<nMat*(Lbar/2 - sign*sqrt(rpos.Mag2()))/C<<std::endl; - break; - } - } - if(looptime>500) continue; - - m_step_T1.push_back(Ti_left); - m_step_T2.push_back(Ti_right); - totQ1 += Qi_left; - totQ2 += Qi_right; - - HitStep stepoutL, stepoutR; - stepoutL.setQ(Qi_left); stepoutL.setT(Ti_left); - stepoutR.setQ(Qi_right); stepoutR.setT(Ti_right); - DigiLvec.push_back(stepoutL); - DigiRvec.push_back(stepoutR); - } - - // ####################################### - // ####### Ideal Time Digitization ####### - // ####################################### - - //if(_Debug>=2) std::cout<<"Time Digitalize: time at Q >"<<_Qthfrac<<"*totQ"<<std::endl; - std::sort(DigiLvec.begin(), DigiLvec.end()); - std::sort(DigiRvec.begin(), DigiRvec.end()); - double thQ1=0; - double thQ2=0; - double thT1, thT2; - for(int iCont=0;iCont<DigiLvec.size();iCont++){ - thQ1 += DigiLvec[iCont].getQ(); - if(thQ1>totQ1*_Qthfrac){ - thT1 = DigiLvec[iCont].getT(); - if(_Debug>=3) std::cout<<"Get T1 at index: "<<iCont<<std::endl; - break; - } - } - for(int iCont=0;iCont<DigiRvec.size();iCont++){ - thQ2 += DigiRvec[iCont].getQ(); - if(thQ2>totQ2*_Qthfrac){ - thT2 = DigiRvec[iCont].getT(); - if(_Debug>=3) std::cout<<"Get T2 at index: "<<iCont<<std::endl; - break; - } - } - - if(_UseRelDigi){ - // ############################################# - // ####### Realistic Charge Digitization ####### - // ############################################# - - // double sEcalCryMipLY = gRandom->Gaus(fEcalCryMipLY, 0.1 * fEcalCryMipLY); - double sEcalCryMipLY = fEcalCryMipLY; - - //TODO: fEcalMIPEnergy should depends on crystal size. - int ScinGen; - if(fUseDigiScint) - ScinGen = std::round(gRandom->Poisson((totQ1_Truth+totQ2_Truth)*1000 / fEcalMIPEnergy * sEcalCryMipLY)); - else ScinGen = (totQ1_Truth+totQ2_Truth)*1000 / fEcalMIPEnergy * sEcalCryMipLY; - - totQ1_Digi = EnergyDigi(ScinGen*totQ1_Truth/(totQ1_Truth+totQ2_Truth), sEcalCryMipLY)/1000; - totQ2_Digi = EnergyDigi(ScinGen*totQ2_Truth/(totQ1_Truth+totQ2_Truth), sEcalCryMipLY)/1000; - } - else{ - double totQ1_Digi_tmp = totQ1_Truth; - double totQ2_Digi_tmp = totQ2_Truth; - if( (totQ1_Digi_tmp+totQ2_Digi_tmp)!=0 ){ - totQ1_Digi = totQ1_Digi_tmp/(totQ1_Digi_tmp+totQ2_Digi_tmp); - totQ2_Digi = totQ2_Digi_tmp/(totQ1_Digi_tmp+totQ2_Digi_tmp); + for(int icol=0; icol<_inputSimHitCollection.size(); icol++){ + try{ + SimCaloType* r_SimCaloCol = _inputSimHitCollection[icol]; + CaloType* w_DigiCaloCol = _outputHitCollection[icol]; + CaloSimAssoType* w_CaloAssociationCol = _outputCaloSimAssoCol[icol]; + CaloParticleAssoType* w_MCPCaloAssociationCol = _outputCaloMCPAssoCol[icol]; + + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol->get(); + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol->createAndPut(); + edm4hep::MCRecoCaloAssociationCollection* caloAssoVec = w_CaloAssociationCol->createAndPut(); + edm4hep::MCRecoCaloParticleAssociationCollection* caloMCPAssoVec = w_MCPCaloAssociationCol->createAndPut(); + std::vector<edm4hep::SimCalorimeterHit> m_simhitCol; m_simhitCol.clear(); + std::vector<CaloBar> m_barCol; m_barCol.clear(); + + if(SimHitCol == 0){ + std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; + return StatusCode::SUCCESS; + } + + if(_Debug>=1) std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; + + totE_Truth=0; + totE_Digi=0; + mean_CT = 0; + for (int i = 1; i < 10; i++) + { + mean_CT += (i-1)*f_DarkNoise->Eval(i); + } + float sEcalTempRef = rndm.Uniform(fEcalTempRef - fEcalTempFluc, fEcalTempRef + fEcalTempFluc); + ECALTemp = sEcalTempRef; + + //Merge input simhit(steps) to real simhit(bar). + MergeHits(*SimHitCol, m_simhitCol); + if(_Debug>=1) std::cout<<"Finish Hit Merge, with Nhit: "<<m_simhitCol.size()<<std::endl; + + //Loop in SimHit, digitalize SimHit to DigiBar + for(int i=0;i<m_simhitCol.size();i++) + { + auto SimHit = m_simhitCol.at(i); + if(!SimHit.isAvailable()) {cout<<"Sim hit is not available"<<endl; continue;} + if(SimHit.getEnergy()==0) {cout<<"Sim hit energy is 0"<<endl; continue;} + + totE_Truth += SimHit.getEnergy(); + unsigned long long id = SimHit.getCellID(); + CaloBar hitbar; + hitbar.setcellID( id); + int id_part = -1; + int id_system = map_readout_decoder[name_Readout[icol]]->get(id, "system"); + if(id_system==29) id_part = map_readout_decoder[name_Readout[icol]]->get(id, "part"); //ECAL endcap + hitbar.setcellID( map_readout_decoder[name_Readout[icol]]->get(id, "system"), + map_readout_decoder[name_Readout[icol]]->get(id, "module"), + map_readout_decoder[name_Readout[icol]]->get(id, "stave"), + id_part, + map_readout_decoder[name_Readout[icol]]->get(id, "dlayer"), + map_readout_decoder[name_Readout[icol]]->get(id, "slayer"), + map_readout_decoder[name_Readout[icol]]->get(id, "bar")); + // double Lbar = GetBarLength(hitbar); //NOTE: Is fixed with geometry LongCrystalBarBarrelCalorimeter32Polygon_v01. + double Lbar = GetBarLengthFromGeo(id); + hitbar.setLength(Lbar); + + dd4hep::Position hitpos = m_cellIDConverter->position(id); + TVector3 barpos(10*hitpos.x(), 10*hitpos.y(), 10*hitpos.z()); //cm to mm. + hitbar.setPosition(barpos); + + //printf("in bar #%d: cellID [%d, %d, %d, %d], position (%.3f, %.3f, %.3f), energy %.3f \n", hitbar.getModule(), hitbar.getStave(), hitbar.getDlayer(), hitbar.getSlayer(), hitbar.getBar(), + // 10*hitpos.x(), 10*hitpos.y(), 10*hitpos.z(), SimHit.getEnergy() ); + + MCParticleToEnergyWeightMap MCPEnMap; MCPEnMap.clear(); + std::vector<HitStep> DigiLvec; DigiLvec.clear(); + std::vector<HitStep> DigiRvec; DigiRvec.clear(); + double totQ1_Truth = 0; + double totQ1_Att = 0; + double totQ2_Att = 0; + double totQ1_Digi = 0; + double totQ2_Digi = 0; + double totQ1 = 0; + double totQ2 = 0; + + //Loop in all SimHitContribution(G4Step). + //if(_Debug>=2) std::cout<<"SimHit contribution size: "<<SimHit.contributions_size()<<std::endl; + for(int iCont=0; iCont < SimHit.contributions_size(); ++iCont){ + auto conb = SimHit.getContributions(iCont); + if( !conb.isAvailable() ) { std::cout<<"EcalDigiAlg Can not get SimHitContribution: "<<iCont<<std::endl; continue;} + + double en = conb.getEnergy(); + if(en == 0) continue; + totQ1_Truth += en; + + auto mcp = conb.getParticle(); + MCPEnMap[mcp] += en; + TVector3 steppos(conb.getStepPosition().x, conb.getStepPosition().y, conb.getStepPosition().z); + TVector3 rpos = steppos-hitbar.getPosition(); + float step_time = conb.getTime(); // yyy: step time + + // m_step_x.push_back(steppos.x()); + // m_step_y.push_back(steppos.y()); + // m_step_z.push_back(steppos.z()); + // m_step_t.push_back(step_time); // yyy: push back step time + // m_step_E.push_back(en); + // m_stepBar_x.push_back(hitbar.getPosition().x()); + // m_stepBar_y.push_back(hitbar.getPosition().y()); + // m_stepBar_z.push_back(hitbar.getPosition().z()); + + if(_Debug>=3){ + cout<<"Cell Pos: "<<hitbar.getPosition().x()<<'\t'<<hitbar.getPosition().y()<<'\t'<<hitbar.getPosition().z()<<endl; + cout<<"step pos: "<<steppos.x()<<'\t'<<steppos.y()<<'\t'<<steppos.z()<<endl; + cout<<"Relative pos: "<<rpos.x()<<'\t'<<rpos.y()<<'\t'<<rpos.z()<<endl; + cout<<"Cell: "<<hitbar.getModule()<<" "<<hitbar.getDlayer()<<" "<<hitbar.getSlayer()<<endl; + } + + //Get digitalized signal(Q1, Q2, T1, T2) from step + //Define: 1 is left, 2 is right, clockwise direction in phi. + + int sign=-999; + if(id_system == 20){ //ECAL barrel + if(hitbar.getSlayer()==1) sign = rpos.z()==0 ? 1 : rpos.z()/fabs(rpos.z()); + else{ + int _module = hitbar.getModule(); + if(_module<=7 || _module>=25) sign = rpos.x()==0 ? 1: rpos.x()/fabs(rpos.x()); + if(_module>=9 && _module<=23) sign = rpos.x()==0 ? -1:-rpos.x()/fabs(rpos.x()); + else if(_module==8) sign = rpos.y()==0 ? 1: rpos.y()/fabs(rpos.y()); + else if(_module==24) sign = rpos.y()==0 ? -1:-rpos.y()/fabs(rpos.y()); + } + } + else if(id_system == 29){ //ECAL endcaps + sign = rpos.x()==0 ? 1 : rpos.x()/fabs(rpos.x()); + } + if(!fabs(sign)) {std::cout<<"ERROR: Wrong bar direction/position!"<<std::endl; continue;} + + // ####### For Charge Digitization ####### + // non-uniformity = 0 + // double Ratio_left = exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt) / (exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt) + exp(-(Lbar/2 - sign*sqrt(rpos.Mag2()))/Latt)); + // double Ratio_right = 1 - Ratio_left; + // totQ1_Truth += en*Ratio_left; + // totQ2_Truth += en*Ratio_right; + + // non-uniformity != 0 + double Ratio_left = exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt) / (2 * exp(-(Lbar/2)/Latt)); + double Ratio_right = exp(-(Lbar/2 - sign*sqrt(rpos.Mag2()))/Latt) / (2 * exp(-(Lbar/2)/Latt)); + totQ1_Att += en*Ratio_left; + totQ2_Att += en*Ratio_right; + + // ####### For Time Digitization ####### + double Qi_left = en*exp(-(Lbar/2 + sign*sqrt(rpos.Mag2()))/Latt); + double Qi_right = en*exp(-(Lbar/2 - sign*sqrt(rpos.Mag2()))/Latt); + + if(_Debug>=3){ + cout<<Qi_left<<'\t'<<Qi_right<<endl; + cout<<Lbar<<'\t'<<sign*sqrt(rpos.Mag2())<<endl; + } + + double Ti_left = -1; int looptime=0; + while(Ti_left<0){ + // Ti_left = Tinit + rndm.Gaus(nMat*(Lbar/2 + sign*sqrt(rpos.Mag2()))/C, Tres); + Ti_left = Tinit + rndm.Gaus(nMat*(Lbar/2 + sign*sqrt(rpos.Mag2()))/C, Tres) + step_time; // yyy: add step time + looptime++; + if(looptime>500){ std::cout<<"ERROR: Step "<<iCont<<" can not get a positive left-side time!"<<std::endl; break;} + } + if(looptime>500) continue; + double Ti_right = -1; looptime=0; + while(Ti_right<0){ + // Ti_right = Tinit + rndm.Gaus(nMat*(Lbar/2 - sign*sqrt(rpos.Mag2()))/C, Tres); + Ti_right = Tinit + rndm.Gaus(nMat*(Lbar/2 - sign*sqrt(rpos.Mag2()))/C, Tres) + step_time; // yyy: add step time + looptime++; + if(looptime>500){ + std::cout<<"ERROR: Step "<<iCont<<" can not get a positive right-side time!"<<std::endl; + std::cout<<" Initial time "<<Tinit<<", transport time central value "<<nMat*(Lbar/2 - sign*sqrt(rpos.Mag2()))/C<<std::endl; + break; + } + } + if(looptime>500) continue; + + m_step_T1.push_back(Ti_left); + m_step_T2.push_back(Ti_right); + totQ1 += Qi_left; + totQ2 += Qi_right; + + HitStep stepoutL, stepoutR; + stepoutL.setQ(Qi_left); stepoutL.setT(Ti_left); + stepoutR.setQ(Qi_right); stepoutR.setT(Ti_right); + DigiLvec.push_back(stepoutL); + DigiRvec.push_back(stepoutR); + } + + // ####################################### + // ####### Ideal Time Digitization ####### + // ####################################### + + //if(_Debug>=2) std::cout<<"Time Digitalize: time at Q >"<<_Qthfrac<<"*totQ"<<std::endl; + std::sort(DigiLvec.begin(), DigiLvec.end()); + std::sort(DigiRvec.begin(), DigiRvec.end()); + double thQ1=0; + double thQ2=0; + double thT1, thT2; + for(int iCont=0;iCont<DigiLvec.size();iCont++){ + thQ1 += DigiLvec[iCont].getQ(); + if(thQ1>totQ1*_Qthfrac){ + thT1 = DigiLvec[iCont].getT(); + if(_Debug>=3) std::cout<<"Get T1 at index: "<<iCont<<std::endl; + break; + } + } + for(int iCont=0;iCont<DigiRvec.size();iCont++){ + thQ2 += DigiRvec[iCont].getQ(); + if(thQ2>totQ2*_Qthfrac){ + thT2 = DigiRvec[iCont].getT(); + if(_Debug>=3) std::cout<<"Get T2 at index: "<<iCont<<std::endl; + break; + } + } + + int ScinGen; + int outLO1, outNDC1, outNDetPE1, outLO2, outNDC2, outNDetPE2; + float outADC1, outADCGain1, outPedestal1, outPedestal2, outADC2, outADCGain2; + float ChannelTemp, CryTID, SiPMNIEL, CryIntLY, SiPMGain, SiPMDCR; + if(_UseRelDigi){ + // ############################################# + // ####### Realistic Charge Digitization ####### + // ############################################# + + //TODO: fEcalMIPEnergy should depends on crystal size. + //TODO: Barrel and endcap should use different temperature map. + int layer = (hitbar.getDlayer() - 1) * 2 + hitbar.getSlayer(); + float temp_dif = (27 - layer) * fEcalTempGrad + sEcalTempRef - fEcalTempRef;// compared with fEcalTempRef + ChannelTemp = temp_dif + fEcalTempRef; + CryTID = fEcalCryTID; + SiPMNIEL = fEcalSiPMNIEL; + // float sEcalCryIntLY = rndm.Gaus(fEcalCryIntLY, fEcalCryIntLYFlu * fEcalCryIntLY); + float sEcalCryIntLY = fEcalCryIntLY; + float sEcalSiPMGainMean = fEcalSiPMGainMean; + float sEcalSiPMDCR = fEcalSiPMDCR; + + // Effects on crystal + if(fUseCryTID && fEcalCryTID >= 50){ + sEcalCryIntLY = sEcalCryIntLY * g_CryLYRatio_vs_TID->Eval(fEcalCryTID); + } + if(fUseCryTemp) { + sEcalCryIntLY = sEcalCryIntLY * (1 + temp_dif * fEcalBGOTempCoef); + } + CryIntLY = sEcalCryIntLY; + if(fUseDigiScint){ + ScinGen = std::round(rndm.Poisson((totQ1_Att+totQ2_Att) * 1000 * sEcalCryIntLY)); + } + else{ + ScinGen = (totQ1_Att+totQ2_Att) * 1000 * sEcalCryIntLY; + } + //cout<<endl; + //cout<<"In Hit #"<<i<<": truth energy "<<totQ1_Att+totQ2_Att<<", used intrinsic LY "<<sEcalCryIntLY<<", ph "<<ScinGen; + + // Remove corrections + if(fUseCryTemp && !fUseCryTempCor) { + sEcalCryIntLY = sEcalCryIntLY / (1 + temp_dif * fEcalBGOTempCoef); + } + if((fUseCryTID && fEcalCryTID >= 50) && !fUseCryTIDCor) { + sEcalCryIntLY = sEcalCryIntLY / g_CryLYRatio_vs_TID->Eval(fEcalCryTID); + } + + // Effects on SiPM + if(fUseSiPMNIEL && fEcalSiPMNIEL >= 1e+7) { + sEcalSiPMDCR = sEcalSiPMDCR * g_SiPMDCR_vs_NIEL->Eval(fEcalSiPMNIEL); + } + if(fUseSiPMTemp) { + sEcalSiPMGainMean = sEcalSiPMGainMean * (1 + temp_dif * fEcalSiPMGainTempCoef); + sEcalSiPMDCR = sEcalSiPMDCR * pow(10, fEcalSiPMDCRTempCoef * temp_dif); + } + SiPMGain = sEcalSiPMGainMean; + SiPMDCR = sEcalSiPMDCR; + // Remove corrections + if(fUseSiPMTemp && ! fUseSiPMTempCor) { + sEcalSiPMGainMean = sEcalSiPMGainMean / (1 + temp_dif * fEcalSiPMGainTempCoef); + } + // if((fUseSiPMNIEL && fEcalSiPMNIEL >= 1e+7) && !fUseSiPMNIELCor) { + // } + //cout<<", SiPM gain "<<sEcalSiPMGainMean<<endl; + + totQ1_Digi = EnergyDigi(ScinGen*totQ1_Att/(totQ1_Att+totQ2_Att), sEcalCryIntLY, sEcalSiPMGainMean, sEcalSiPMDCR, + f_SiPMResponse, f_SiPMSigmaDet, f_SiPMSigmaRecp, f_SiPMSigmaRecm, f_AsymGauss, f_DarkNoise, + outLO1, outNDC1, outNDetPE1, outPedestal1, outADC1, outADCGain1)/1000; + totQ2_Digi = EnergyDigi(ScinGen*totQ2_Att/(totQ1_Att+totQ2_Att), sEcalCryIntLY, sEcalSiPMGainMean, sEcalSiPMDCR, + f_SiPMResponse, f_SiPMSigmaDet, f_SiPMSigmaRecp, f_SiPMSigmaRecm, f_AsymGauss, f_DarkNoise, + outLO2, outNDC2, outNDetPE2, outPedestal2, outADC2, outADCGain2)/1000; + } + else{ + if( (totQ1_Att+totQ2_Att)!=0 ){ + totQ1_Digi = totQ1_Att; + totQ2_Digi = totQ2_Att; + } + if( totQ1_Digi*1000./fEcalMIPEnergy < fEcalMIP_Thre ) totQ1_Digi = 0; + if( totQ2_Digi*1000./fEcalMIPEnergy < fEcalMIP_Thre ) totQ2_Digi = 0; + } + + // cout<<"bar truth Q1: "<<totQ1_Att*1000<<",\t bar digi Q1: "<<totQ1_Digi*1000<<endl; + if(totQ1_Digi==0 && totQ2_Digi==0) continue; + + hitbar.setQ(totQ1_Digi, totQ2_Digi); + hitbar.setT(thT1, thT2); + // cout<<"bar thT1: "<<thT1<<",\t bar thT2: "<<thT2<<endl; + + // ################################## + // ####### Some associations ####### + // ################################## + + //2 hits with double-readout time. + edm4hep::Vector3f m_pos(hitbar.getPosition().X(), hitbar.getPosition().Y(), hitbar.getPosition().Z()); + auto digiHit1 = caloVec->create(); + digiHit1.setCellID(hitbar.getcellID()); + digiHit1.setEnergy(hitbar.getQ1()); + digiHit1.setTime(hitbar.getT1()); + digiHit1.setPosition(m_pos); + auto digiHit2 = caloVec->create(); + digiHit2.setCellID(hitbar.getcellID()); + digiHit2.setEnergy(hitbar.getQ2()); + digiHit2.setTime(hitbar.getT2()); + digiHit2.setPosition(m_pos); + + + //SimHit - CaloHit association + auto rel1 = caloAssoVec->create(); + rel1.setRec(digiHit1); + rel1.setSim(SimHit); + rel1.setWeight( hitbar.getQ1()/(hitbar.getQ1()+hitbar.getQ2()) ); + auto rel2 = caloAssoVec->create(); + rel2.setRec(digiHit2); + rel2.setSim(SimHit); + rel2.setWeight( hitbar.getQ2()/(hitbar.getQ1()+hitbar.getQ2()) ); + + + //MCParticle - CaloHit association + //float maxMCE = -99.; + //edm4hep::MCParticle selMCP; + for(auto iter : MCPEnMap){ + //if(iter.second>maxMCE){ + // maxMCE = iter.second; + // selMCP = iter.first; + //} + auto rel_MCP1 = caloMCPAssoVec->create(); + rel_MCP1.setRec(digiHit1); + rel_MCP1.setSim(iter.first); + rel_MCP1.setWeight(iter.second/SimHit.getEnergy()); + auto rel_MCP2 = caloMCPAssoVec->create(); + rel_MCP2.setRec(digiHit2); + rel_MCP2.setSim(iter.first); + rel_MCP2.setWeight(iter.second/SimHit.getEnergy()); + } + + + //if(selMCP.isAvailable()){ + // auto rel_MCP1 = caloMCPAssoVec->create(); + // rel_MCP1.setRec(digiHit1); + // rel_MCP1.setSim(selMCP); + // rel_MCP1.setWeight(1.); + // auto rel_MCP2 = caloMCPAssoVec->create(); + // rel_MCP2.setRec(digiHit2); + // rel_MCP2.setSim(selMCP); + // rel_MCP2.setWeight(1.); + //} + + // ######################################## + // ####### Temp: write into trees. ####### + // ######################################## + + m_barCol.push_back(hitbar); + if(hitbar.getQ1()>=0 && hitbar.getQ2()>=0) totE_Digi += (hitbar.getQ1() + hitbar.getQ2()); + //if(totQ1_Att>(fEcalMIPEnergy*fEcalMIP_Thre/1000.) && totQ2_Att>(fEcalMIPEnergy*fEcalMIP_Thre/1000.)){ + // // cout<<"Truth Energy:"<<totQ1_Att<<" "<<totQ2_Att<<endl; + // totE_Truth+=(totQ1_Att+totQ2_Att); + //} + + + if(_writeNtuple){ + m_simBar_x.push_back(hitbar.getPosition().x()); + m_simBar_y.push_back(hitbar.getPosition().y()); + m_simBar_z.push_back(hitbar.getPosition().z()); + m_simBar_E_Truth.push_back(totQ1_Truth); + m_simBar_Scint.push_back(ScinGen); + m_simBar_ChannelTemp.push_back(ChannelTemp); + m_simBar_CryTID.push_back(CryTID); + m_simBar_SiPMNIEL.push_back(SiPMNIEL); + m_simBar_CryIntLY.push_back(CryIntLY); + m_simBar_SiPMGain.push_back(SiPMGain); + m_simBar_SiPMDCR.push_back(SiPMDCR); + m_simBar_LO1.push_back(outLO1); + m_simBar_LO2.push_back(outLO2); + m_simBar_NDC1.push_back(outNDC1); + m_simBar_NDC2.push_back(outNDC2); + m_simBar_NDetPE1.push_back(outNDetPE1); + m_simBar_NDetPE2.push_back(outNDetPE2); + m_simBar_Pedestal1.push_back(outPedestal1); + m_simBar_Pedestal2.push_back(outPedestal2); + m_simBar_ADC1.push_back(outADC1); + m_simBar_ADC2.push_back(outADC2); + m_simBar_ADCGain1.push_back(outADCGain1); + m_simBar_ADCGain2.push_back(outADCGain2); + m_simBar_Q1_Att.push_back(totQ1_Att); + m_simBar_Q2_Att.push_back(totQ2_Att); + m_simBar_Q1_Digi.push_back(hitbar.getQ1()); + m_simBar_Q2_Digi.push_back(hitbar.getQ2()); + m_simBar_T1.push_back(hitbar.getT1()); + m_simBar_T2.push_back(hitbar.getT2()); + m_simBar_length.push_back(hitbar.getLength()); + m_simBar_system.push_back(hitbar.getSystem()); + m_simBar_module.push_back(hitbar.getModule()); + m_simBar_stave.push_back(hitbar.getStave()); + m_simBar_part.push_back(hitbar.getPart()); + m_simBar_dlayer.push_back(hitbar.getDlayer()); + m_simBar_slayer.push_back(hitbar.getSlayer()); + m_simBar_bar.push_back(hitbar.getBar()); + m_simBar_cellID.push_back(hitbar.getcellID()); + } } - if( totQ1_Digi/fEcalMIPEnergy < fEcalMIP_Thre ) totQ1_Digi = 0; - if( totQ2_Digi/fEcalMIPEnergy < fEcalMIP_Thre ) totQ2_Digi = 0; - } - if(totQ1_Digi==0 && totQ2_Digi==0) continue; - - hitbar.setQ(totQ1_Digi, totQ2_Digi); - hitbar.setT(thT1, thT2); - - // ################################## - // ####### Some associations ####### - // ################################## - - //2 hits with double-readout time. - edm4hep::Vector3f m_pos(hitbar.getPosition().X(), hitbar.getPosition().Y(), hitbar.getPosition().Z()); - auto digiHit1 = caloVec->create(); - digiHit1.setCellID(hitbar.getcellID()); - digiHit1.setEnergy(hitbar.getQ1()); - digiHit1.setTime(hitbar.getT1()); - digiHit1.setPosition(m_pos); - auto digiHit2 = caloVec->create(); - digiHit2.setCellID(hitbar.getcellID()); - digiHit2.setEnergy(hitbar.getQ2()); - digiHit2.setTime(hitbar.getT2()); - digiHit2.setPosition(m_pos); - - //SimHit - CaloHit association - auto rel1 = caloAssoVec->create(); - rel1.setRec(digiHit1); - rel1.setSim(SimHit); - rel1.setWeight( hitbar.getQ1()/(hitbar.getQ1()+hitbar.getQ2()) ); - auto rel2 = caloAssoVec->create(); - rel2.setRec(digiHit2); - rel2.setSim(SimHit); - rel2.setWeight( hitbar.getQ2()/(hitbar.getQ1()+hitbar.getQ2()) ); - - //MCParticle - CaloHit association - //float maxMCE = -99.; - //edm4hep::MCParticle selMCP; - for(auto iter : MCPEnMap){ - //if(iter.second>maxMCE){ - // maxMCE = iter.second; - // selMCP = iter.first; - //} - auto rel_MCP1 = caloMCPAssoVec->create(); - rel_MCP1.setRec(digiHit1); - rel_MCP1.setSim(iter.first); - rel_MCP1.setWeight(iter.second/SimHit.getEnergy()); - auto rel_MCP2 = caloMCPAssoVec->create(); - rel_MCP2.setRec(digiHit2); - rel_MCP2.setSim(iter.first); - rel_MCP2.setWeight(iter.second/SimHit.getEnergy()); - } - - //if(selMCP.isAvailable()){ - // auto rel_MCP1 = caloMCPAssoVec->create(); - // rel_MCP1.setRec(digiHit1); - // rel_MCP1.setSim(selMCP); - // rel_MCP1.setWeight(1.); - // auto rel_MCP2 = caloMCPAssoVec->create(); - // rel_MCP2.setRec(digiHit2); - // rel_MCP2.setSim(selMCP); - // rel_MCP2.setWeight(1.); - //} - - // ######################################## - // ####### Temp: write into trees. ####### - // ######################################## - - m_barCol.push_back(hitbar); - if(hitbar.getQ1()>0 && hitbar.getQ2()>0) totE_Digi+=(hitbar.getQ1()+hitbar.getQ2()); - if(totQ1_Truth>(fEcalMIPEnergy*fEcalMIP_Thre/1000.) && totQ2_Truth>(fEcalMIPEnergy*fEcalMIP_Thre/1000.)){ - // cout<<"Truth Energy:"<<totQ1_Truth<<" "<<totQ2_Truth<<endl; - totE_Truth+=(totQ1_Truth+totQ2_Truth); - } - if(_writeNtuple){ - m_simBar_x.push_back(hitbar.getPosition().x()); - m_simBar_y.push_back(hitbar.getPosition().y()); - m_simBar_z.push_back(hitbar.getPosition().z()); - m_simBar_Q1_Truth.push_back(totQ1_Truth); - m_simBar_Q2_Truth.push_back(totQ2_Truth); - m_simBar_Q1_Digi.push_back(hitbar.getQ1()); - m_simBar_Q2_Digi.push_back(hitbar.getQ2()); - m_simBar_T1.push_back(hitbar.getT1()); - m_simBar_T2.push_back(hitbar.getT2()); - m_simBar_module.push_back(hitbar.getModule()); - m_simBar_stave.push_back(hitbar.getStave()); - m_simBar_dlayer.push_back(hitbar.getDlayer()); - m_simBar_slayer.push_back(hitbar.getSlayer()); - m_simBar_cellID.push_back(hitbar.getcellID()); - } - } + m_simhitCol.clear(); + }catch(GaudiException &e){ + info()<<"SimCaloHit collection "<<name_SimCaloHit[icol]<<" is not available "<<endmsg; + } + } if(_writeNtuple){ - t_SimCont->Fill(); + // t_SimCont->Fill(); t_SimBar->Fill(); } - if(_Debug>=1) std::cout<<"End Loop: Bar Digitalization!"<<std::endl; - std::cout<<"Total Truth Energy: "<<totE_Truth<<std::endl; - std::cout<<"Total Digi Energy: "<<totE_Digi<<std::endl; + if(_Debug>=1) + { + std::cout<<"End Loop: Bar Digitalization!"<<std::endl; + std::cout<<"Total Truth Energy: "<<totE_Truth<<std::endl; + std::cout<<"Total Digi Energy: "<<totE_Digi<<std::endl; + } // yyy_enddigi = clock(); // double duration_digi = double(yyy_enddigi - yyy_start) / CLOCKS_PER_SEC; @@ -427,7 +659,6 @@ StatusCode EcalDigiAlg::execute() _nEvt ++ ; //delete SimHitCol, caloVec, caloAssoVec; - m_simhitCol.clear(); return StatusCode::SUCCESS; } @@ -435,76 +666,219 @@ StatusCode EcalDigiAlg::finalize() { if(_writeNtuple){ m_wfile->cd(); - t_SimCont->Write(); + //t_SimCont->Write(); t_SimBar->Write(); m_wfile->Close(); delete m_wfile, t_SimCont, t_SimBar; } info() << "Processed " << _nEvt << " events " << endmsg; - delete m_cellIDConverter, m_decoder, m_geosvc; + map_readout_decoder.clear(); + delete m_cellIDConverter, m_geosvc; + delete f_SiPMResponse, f_SiPMSigmaDet, f_SiPMSigmaRecp, f_SiPMSigmaRecm, f_AsymGauss, f_DarkNoise, g_SiPMDCR_vs_NIEL, g_CryLYRatio_vs_TID; return GaudiAlgorithm::finalize(); } -double EcalDigiAlg::EnergyDigi(double ScinGen, double sEcalCryMipLY){ +float EcalDigiAlg::EnergyDigi(float ScinGen, float sEcalCryIntLY, float sEcalSiPMGainMean, float sEcalSiPMDCR, + TF1* f_SiPMResponse, TF1* f_SiPMSigmaDet, TF1* f_SiPMSigmaRecp, TF1* f_SiPMSigmaRecm, TF1* f_AsymGauss, TF1* f_DarkNoise, + int& outLO, int& outNDC, int& outNDetPE, float& outPedestal, float& outADC, float& outADCGain) +{ + // float sEcalSiPMPDE = rndm.Gaus(fEcalSiPMPDE, fEcalSiPMPDEFlu * fEcalSiPMPDE); + float sEcalSiPMPDE = fEcalSiPMPDE; + float fEcalCryAtt = fEcalCryMipLY/(fEcalCryIntLY*fEcalSiPMPDE*fEcalMIPEnergy); + int sEcalCryAttLO = std::round(ScinGen * fEcalCryAtt * sEcalSiPMPDE); + if (sEcalCryAttLO < 0) sEcalCryAttLO = 0; + float sEcalCaliMIPLY = sEcalCryIntLY * fEcalCryAtt * sEcalSiPMPDE * fEcalMIPEnergy; + // sEcalCaliMIPLY = rndm.Gaus(sEcalCaliMIPLY, fEcalCryLYUn * sEcalCaliMIPLY); + outLO = sEcalCryAttLO; +//cout<<" Real Digi: output Light "<<sEcalCryAttLO<<" = round ("<<ScinGen<<" * "<<fEcalCryAtt<<" * "<<sEcalSiPMPDE<<")"; + + int sNLin = sEcalCryAttLO; + int sNDet = 0; + float sNDetMean = 0; + float sNDetSigma = 0; + if(fSiPMDigiVerbose==0 || sNLin<100) + { + sNDetMean = sNLin; + //sNDetSigma = f_SiPMSigmaDet->Eval(sNDetMean); + sNDetSigma = 0; + sNDet = std::round(rndm.Gaus(sNDetMean, sNDetSigma)); + } + else + { + sNDetMean = f_SiPMResponse->Eval(sNLin); + sNDetSigma = f_SiPMSigmaDet->Eval(sNDetMean); + sNDet = std::round(rndm.Gaus(sNDetMean, sNDetSigma)); + } + //SiPM dark noise: dark counts and acossiated crosstalks, the crossstalk follows the Borel distribution + int darkcounts_mean = rndm.Poisson(sEcalSiPMDCR * fEcalTimeInterval); + int darkcounts_CT = 0; + for(int i=0;i<darkcounts_mean;i++) + { + double darkcounts_rdm = rndm.Uniform(0, 1); + int sum_darkcounts = 1; + if(! (darkcounts_rdm <= f_DarkNoise->Eval(sum_darkcounts))) + { + float prob = f_DarkNoise->Eval(sum_darkcounts); + while(darkcounts_rdm > prob) + { + sum_darkcounts++; + prob += f_DarkNoise->Eval(sum_darkcounts); + } + } + darkcounts_CT += sum_darkcounts; + } + outNDC = darkcounts_CT; + sNDet += darkcounts_CT; + if (sNDet < 0) sNDet = 0; + outNDetPE = sNDet; + +//cout<<", SiPM pixel "<<sNDet<<", dark count + Xtalk "<<darkcounts_CT; + + Bool_t Use_G1 = kFALSE; + Bool_t Use_G2 = kFALSE; + Bool_t Use_G3 = kFALSE; + // sEcalSiPMGainMean = rndm.Gaus(sEcalSiPMGainMean, sEcalSiPMGainMean * fEcalSiPMGainMeanFlu); + float sEcalSiPMGainSigma = sEcalSiPMGainMean * fEcalSiPMGainSigma; + float sPedestal = fPedestal; + float sEcalFEENoiseSigma = fEcalFEENoiseSigma; + float sEcalASICNoiseSigma = fEcalASICNoiseSigma; + float sADCMean = sNDet * sEcalSiPMGainMean + sPedestal; + float sADCSigma = std::sqrt(sNDet * sEcalSiPMGainSigma * sEcalSiPMGainSigma + sEcalFEENoiseSigma * sEcalFEENoiseSigma + fEcalASICNoiseSigma * fEcalASICNoiseSigma); + float sADC = -1; + sADC = std::round(rndm.Gaus(sADCMean, sADCSigma)); + if(sADC < 0) sADC = 0; + outPedestal = sPedestal; + outADC = sADC; + +//cout<<", raw ADC "<<sADC<<" = Gaus ( "<<sADCMean<<" +- "<<sADCSigma<<" )"<<endl; +//cout<<" ADC mean = "<<sNDet<<" * "<<sEcalSiPMGainMean<<" + "<<sPedestal; +//cout<<", ADC sigma = sqrt("<<sNDet<<" * "<<sEcalSiPMGainSigma<<"^2 + "<<sEcalFEENoiseSigma<<"^2 + "<<fEcalASICNoiseSigma.value()<<"^2 )"<<endl; + + if(sADC <= fADCSwitch) + { + Use_G1 = kTRUE; + + if(fSiPMDigiVerbose==2 && sNDet>=100) + { + float sNRecMean = f_SiPMResponse->GetX((sADC-sPedestal)/sEcalSiPMGainMean); + float sNRecSigma = sNDetSigma; + float NRec = rndm.Gaus(sNRecMean, sNRecSigma); + sADC = NRec * sEcalSiPMGainMean + sPedestal; + } + else if(fSiPMDigiVerbose==3 && sNDet>=100) + { + float sNADCDet = (sADC - sPedestal) / sEcalSiPMGainMean; + float sNRecMean = f_SiPMResponse->GetX(sNADCDet); + float sNRecSigmap = sNRecMean - f_SiPMSigmaRecp->GetX(sNADCDet); + float sNRecSigmam = f_SiPMSigmaRecm->GetX(sNADCDet) - sNRecMean; + f_AsymGauss->SetRange(sNRecMean-3*sNRecSigmap, sNRecMean+3*sNRecSigmam); + f_AsymGauss->SetParameters(sNRecMean, sNRecSigmap, sNRecSigmam); + float NRec = f_AsymGauss->GetRandom(); + sADC = NRec * sEcalSiPMGainMean + sPedestal; + } + outPedestal = sPedestal; + outADCGain = sADC; + sPedestal = fPedestal + sEcalSiPMDCR * fEcalTimeInterval * (1 + mean_CT) * sEcalSiPMGainMean; + + // float sEcalCaliGainMean = rndm.Gaus(sEcalSiPMGainMean, fEcalSiPMGainUn * sEcalSiPMGainMean); + // float sMIP = (sADC - sPedestal) / sEcalCaliGainMean / sEcalCaliMIPLY; + float sMIP = (sADC - sPedestal) / sEcalSiPMGainMean / sEcalCaliMIPLY; - Int_t sPix; +//cout<<", after gain "<<sADC<<", Nmip "<<sMIP<<" = ("<<sADC<<" - "<<sPedestal<<") / "<<sEcalSiPMGainMean<<" / "<<sEcalCaliMIPLY<<endl; - // ####### SiPM Saturation ####### - if(fUseDigiSaturation) - sPix = std::round(fEcalSiPMPixels * (1 - TMath::Exp(-sPix / fEcalSiPMPixels))); - else sPix = int(ScinGen); + if(sMIP < fEcalMIP_Thre) return 0; + return sMIP * fEcalMIPEnergy; + } + else if(sADC > fADCSwitch && int(sADC/fGainRatio_12) <= fADCSwitch) + { + Use_G2 = kTRUE; + sEcalSiPMGainMean = sEcalSiPMGainMean / fGainRatio_12; + sPedestal = fPedestal; + sEcalSiPMGainSigma = sEcalSiPMGainMean * fEcalSiPMGainSigma; + sEcalFEENoiseSigma = fEcalFEENoiseSigma / fGainRatio_12; + + sADCMean = sNDet * sEcalSiPMGainMean + sPedestal; + sADCSigma = std::sqrt(sNDet * sEcalSiPMGainSigma * sEcalSiPMGainSigma + fEcalASICNoiseSigma * fEcalASICNoiseSigma + sEcalFEENoiseSigma * sEcalFEENoiseSigma); + sADC = std::round(rndm.Gaus(sADCMean, sADCSigma)); + if(sADC < 0) sADC = 0; + + if(fSiPMDigiVerbose==2) + { + float sNRecMean = f_SiPMResponse->GetX((sADC-sPedestal)/sEcalSiPMGainMean); + float sNRecSigma = sNDetSigma; + float NRec = rndm.Gaus(sNRecMean, sNRecSigma); + sADC = NRec * sEcalSiPMGainMean + sPedestal; + } + else if(fSiPMDigiVerbose==3) + { + float sNADCDet = (sADC - sPedestal) / sEcalSiPMGainMean; + float sNRecMean = f_SiPMResponse->GetX(sNADCDet); + float sNRecSigmap = sNRecMean - f_SiPMSigmaRecp->GetX(sNADCDet); + float sNRecSigmam = f_SiPMSigmaRecm->GetX(sNADCDet) - sNRecMean; + f_AsymGauss->SetRange(sNRecMean-3*sNRecSigmap, sNRecMean+3*sNRecSigmam); + f_AsymGauss->SetParameters(sNRecMean, sNRecSigmap, sNRecSigmam); + float NRec = f_AsymGauss->GetRandom(); + sADC = NRec * sEcalSiPMGainMean + sPedestal; + } + outPedestal = sPedestal; + outADCGain = sADC; + sPedestal = fPedestal + sEcalSiPMDCR * fEcalTimeInterval * (1 + mean_CT) * sEcalSiPMGainMean; - - // ################################ - // ####### ADC Digitization ####### - // ################################ - - Bool_t Use_G1 = kFALSE; - Bool_t Use_G2 = kFALSE; - Bool_t Use_G3 = kFALSE; - - Double_t sADCMean = sPix * fEcalChargeADCMean; - Double_t sADCSigma = std::sqrt(sPix * fEcalChargeADCSigma * fEcalChargeADCSigma + fEcalNoiseADCSigma * fEcalNoiseADCSigma); - Int_t sADC = -1; - if(fUseDigiADC){ - sADC = std::round(gRandom->Gaus(sADCMean, sADCSigma)); - - if(sADC <= fADCSwitch){ - Use_G1 = kTRUE; - sADC = std::round(gRandom->Gaus(sADC, fEcalADCError * sADC)); - Double_t sMIP = sADC / fEcalChargeADCMean / sEcalCryMipLY; - if(sMIP < fEcalMIP_Thre) return 0; - return sMIP * fEcalMIPEnergy; - } - else if(sADC > fADCSwitch && int(sADC/fGainRatio_12) <= fADCSwitch){ - Use_G2 = kTRUE; - sADCMean = sPix * fEcalChargeADCMean / fGainRatio_12; - sADCSigma = std::sqrt(sPix * fEcalChargeADCSigma / fGainRatio_12 * fEcalChargeADCSigma / fGainRatio_12 + fEcalNoiseADCSigma * fEcalNoiseADCSigma); - sADC = std::round(gRandom->Gaus(sADCMean, sADCSigma)); - sADC = std::round(gRandom->Gaus(sADC, fEcalADCError * sADC)); - Double_t sMIP = sADC / fEcalChargeADCMean * fGainRatio_12 / sEcalCryMipLY; - if(sMIP < fEcalMIP_Thre) return 0; - return sMIP * fEcalMIPEnergy; - } - else if(int(sADC/fGainRatio_12) > fADCSwitch){ - Use_G3 = kTRUE; - sADCMean = sPix * fEcalChargeADCMean / fGainRatio_12 / fGainRatio_23; - sADCSigma = std::sqrt(sPix * fEcalChargeADCSigma / fGainRatio_12 / fGainRatio_23 * fEcalChargeADCSigma / fGainRatio_12 / fGainRatio_23 + fEcalNoiseADCSigma * fEcalNoiseADCSigma); - sADC = std::round(gRandom->Gaus(sADCMean, sADCSigma)); - sADC = std::round(gRandom->Gaus(sADC, fEcalADCError * sADC)); - if (sADC > fADC-1) sADC = fADC-1; - Double_t sMIP = sADC / fEcalChargeADCMean * fGainRatio_12 * fGainRatio_23 / sEcalCryMipLY; - if(sMIP < fEcalMIP_Thre) return 0; - return sMIP * fEcalMIPEnergy; - } + // float sEcalCaliGainMean = rndm.Gaus(sEcalSiPMGainMean, fEcalSiPMGainUn * sEcalSiPMGainMean); + // float sMIP = (sADC - sPedestal) / sEcalCaliGainMean / sEcalCaliMIPLY; + float sMIP = (sADC - sPedestal) / sEcalSiPMGainMean / sEcalCaliMIPLY; +//cout<<", after gain "<<sADC<<", Nmip "<<sMIP<<endl; - } - else{ - sADC = sADCMean; - Double_t sMIP = sADC / fEcalChargeADCMean / sEcalCryMipLY; - if(sMIP < fEcalMIP_Thre) return 0; - return sMIP * fEcalMIPEnergy; - } + if(sMIP < fEcalMIP_Thre) return 0; + return sMIP * fEcalMIPEnergy; + } + else if(int(sADC/fGainRatio_12) > fADCSwitch) + { + Use_G3 = kTRUE; + sEcalSiPMGainMean = sEcalSiPMGainMean / fGainRatio_12 / fGainRatio_23; + sPedestal = fPedestal; + sEcalSiPMGainSigma = sEcalSiPMGainMean * fEcalSiPMGainSigma; + sEcalFEENoiseSigma = fEcalFEENoiseSigma / fGainRatio_12 / fGainRatio_23; + + sADCMean = sNDet * sEcalSiPMGainMean + sPedestal; + sADCSigma = std::sqrt(sNDet * sEcalSiPMGainSigma * sEcalSiPMGainSigma + fEcalASICNoiseSigma * fEcalASICNoiseSigma + sEcalFEENoiseSigma * sEcalFEENoiseSigma); + sADC = std::round(rndm.Gaus(sADCMean, sADCSigma)); + if(sADC < 0) sADC = 0; + + if (sADC > fADC-1) + { + sADC = fADC-1; + } + + if(fSiPMDigiVerbose==2) + { + float sNRecMean = f_SiPMResponse->GetX((sADC-sPedestal)/sEcalSiPMGainMean); + float sNRecSigma = sNDetSigma; + float NRec = rndm.Gaus(sNRecMean, sNRecSigma); + sADC = NRec * sEcalSiPMGainMean + sPedestal; + } + else if(fSiPMDigiVerbose==3) + { + float sNADCDet = (sADC - sPedestal) / sEcalSiPMGainMean; + float sNRecMean = f_SiPMResponse->GetX(sNADCDet); + float sNRecSigmap = sNRecMean - f_SiPMSigmaRecp->GetX(sNADCDet); + float sNRecSigmam = f_SiPMSigmaRecm->GetX(sNADCDet) - sNRecMean; + f_AsymGauss->SetRange(sNRecMean-3*sNRecSigmap, sNRecMean+3*sNRecSigmam); + f_AsymGauss->SetParameters(sNRecMean, sNRecSigmap, sNRecSigmam); + float NRec = f_AsymGauss->GetRandom(); + sADC = NRec * sEcalSiPMGainMean + sPedestal; + } + outPedestal = sPedestal; + outADCGain = sADC; + sPedestal = fPedestal + sEcalSiPMDCR * fEcalTimeInterval * (1 + mean_CT) * sEcalSiPMGainMean; + + // float sEcalCaliGainMean = rndm.Gaus(sEcalSiPMGainMean, fEcalSiPMGainUn * sEcalSiPMGainMean); + // float sMIP = (sADC - sPedestal) / sEcalCaliGainMean / sEcalCaliMIPLY; + float sMIP = (sADC - sPedestal) / sEcalSiPMGainMean / sEcalCaliMIPLY; +//cout<<", after gain "<<sADC<<", Nmip "<<sMIP<<endl; + if(sMIP < fEcalMIP_Thre) return 0; + return sMIP * fEcalMIPEnergy; + } } StatusCode EcalDigiAlg::MergeHits( const edm4hep::SimCalorimeterHitCollection& m_col, std::vector<edm4hep::SimCalorimeterHit>& m_hits ){ @@ -524,7 +898,7 @@ StatusCode EcalDigiAlg::MergeHits( const edm4hep::SimCalorimeterHitCollection& m edm4hep::MutableCaloHitContribution conb; conb.setEnergy(m_step.getEnergy()); conb.setStepPosition(m_step.getPosition()); - conb.setParticle( m_step.getContributions(0).getParticle() ); + conb.setParticle( m_step.getContributions(0).getParticle() ); conb.setTime(m_step.getContributions(0).getTime()); edm4hep::MutableSimCalorimeterHit m_hit = find(m_mergedhit, cellid); @@ -558,6 +932,17 @@ double EcalDigiAlg::GetBarLength(CaloBar& bar){ } } +double EcalDigiAlg::GetBarLengthFromGeo(unsigned long long id){ + + dd4hep::PlacedVolume ipv = m_volumeManager.lookupVolumePlacement(id); + dd4hep::Volume ivol = ipv.volume(); + std::vector< double > iVolParam = ivol.solid().dimensions(); + // cout<<"iVolParam: "<<iVolParam.size()<<" "<<iVolParam[0]<<" "<<iVolParam[1]<<" "<<iVolParam[2]<<endl; + auto maxElement = std::max_element(iVolParam.begin(), iVolParam.end()); + // std::cout << "bar length: " << *maxElement * 20 << std::endl; + iVolParam.clear(); + return *maxElement * 20; // mm +} /* dd4hep::Position EcalDigiAlg::GetCellPos(dd4hep::Position& pos, CaloBar& bar){ @@ -609,6 +994,8 @@ edm4hep::MutableSimCalorimeterHit EcalDigiAlg::find(const std::vector<edm4hep::M void EcalDigiAlg::Clear(){ totE_Truth = -99; totE_Digi = -99; + mean_CT = -99; + ECALTemp = -99; m_step_x.clear(); m_step_y.clear(); m_step_z.clear(); @@ -624,13 +1011,37 @@ void EcalDigiAlg::Clear(){ m_simBar_z.clear(); m_simBar_T1.clear(); m_simBar_T2.clear(); - m_simBar_Q1_Truth.clear(); - m_simBar_Q2_Truth.clear(); + m_simBar_E_Truth.clear(); + m_simBar_Scint.clear(); + m_simBar_ChannelTemp.clear(); + m_simBar_CryTID.clear(); + m_simBar_SiPMNIEL.clear(); + m_simBar_CryIntLY.clear(); + m_simBar_SiPMGain.clear(); + m_simBar_SiPMDCR.clear(); + m_simBar_LO1.clear(); + m_simBar_LO2.clear(); + m_simBar_NDC1.clear(); + m_simBar_NDC2.clear(); + m_simBar_NDetPE1.clear(); + m_simBar_NDetPE2.clear(); + m_simBar_Pedestal1.clear(); + m_simBar_Pedestal2.clear(); + m_simBar_ADC1.clear(); + m_simBar_ADC2.clear(); + m_simBar_ADCGain1.clear(); + m_simBar_ADCGain2.clear(); + m_simBar_Q1_Att.clear(); + m_simBar_Q2_Att.clear(); m_simBar_Q1_Digi.clear(); m_simBar_Q2_Digi.clear(); + m_simBar_length.clear(); + m_simBar_system.clear(); m_simBar_module.clear(); m_simBar_stave.clear(); + m_simBar_part.clear(); m_simBar_dlayer.clear(); m_simBar_slayer.clear(); - m_simBar_cellID.clear(); + m_simBar_bar.clear(); + m_simBar_cellID.clear(); } diff --git a/Digitization/DigiCalo/src/EcalDigiAlg.h b/Digitization/DigiCalo/src/EcalDigiAlg.h index 684ad726..6977e799 100644 --- a/Digitization/DigiCalo/src/EcalDigiAlg.h +++ b/Digitization/DigiCalo/src/EcalDigiAlg.h @@ -24,6 +24,8 @@ #include "TString.h" #include "TH3.h" #include "TH1.h" +#include "TF1.h" +#include "TGraph.h" #include <cstdlib> #include "time.h" @@ -57,9 +59,12 @@ public: StatusCode MergeHits(const edm4hep::SimCalorimeterHitCollection& m_col, std::vector<edm4hep::SimCalorimeterHit>& m_hits); double GetBarLength(CaloBar& bar); //TODO: should read from geom file! + double GetBarLengthFromGeo(unsigned long long id); edm4hep::MutableSimCalorimeterHit find(const std::vector<edm4hep::MutableSimCalorimeterHit>& m_col, unsigned long long& cellid) const; // double Digitization(double edepCry, double fCrosstalkChannel); - double EnergyDigi(double ScinGen, double sEcalCryMipLY); + float EnergyDigi(float ScinGen, float sEcalCryMipLY, float sEcalSiPMGainMean, float sEcalSiPMDCR, + TF1* f_SiPMResponse, TF1* f_SiPMSigmaDet, TF1* f_SiPMSigmaRecp, TF1* f_SiPMSigmaRecm, TF1* f_AsymGauss, TF1* f_DarkNoise, + int& outLO, int& outNDC, int& outNDetPE, float& outPedestal, float& outADC, float& outADCGain); void Clear(); @@ -75,23 +80,58 @@ protected: TFile* m_wfile; TTree* t_SimCont; TTree* t_SimBar; - + double totE_Truth, totE_Digi; + double mean_CT, ECALTemp; FloatVec m_step_t; // yyy: time of each step FloatVec m_step_x, m_step_y, m_step_z, m_step_E, m_step_T1, m_step_T2, m_stepBar_x, m_stepBar_y, m_stepBar_z; - FloatVec m_simBar_x, m_simBar_y, m_simBar_z, m_simBar_T1, m_simBar_T2, m_simBar_Q1_Truth, m_simBar_Q2_Truth, m_simBar_Q1_Digi, m_simBar_Q2_Digi, m_simBar_dlayer, m_simBar_stave, m_simBar_slayer, m_simBar_module; + FloatVec m_simBar_x, m_simBar_y, m_simBar_z, + m_simBar_E_Truth, m_simBar_Scint, + m_simBar_ChannelTemp, m_simBar_CryTID, m_simBar_SiPMNIEL, m_simBar_CryIntLY, m_simBar_SiPMGain, m_simBar_SiPMDCR, + m_simBar_LO1, m_simBar_LO2, m_simBar_NDC1, m_simBar_NDC2, m_simBar_NDetPE1, m_simBar_NDetPE2, + m_simBar_Pedestal1, m_simBar_Pedestal2, m_simBar_ADC1, m_simBar_ADC2, m_simBar_ADCGain1, m_simBar_ADCGain2, + m_simBar_T1, m_simBar_T2, + m_simBar_Q1_Att, m_simBar_Q2_Att, m_simBar_Q1_Digi, m_simBar_Q2_Digi, + m_simBar_length, + m_simBar_bar, m_simBar_dlayer, m_simBar_slayer, m_simBar_stave, m_simBar_part, m_simBar_module, m_simBar_system; std::vector<unsigned long long> m_simBar_cellID; - dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; - dd4hep::DDSegmentation::BitFieldCoder* m_decoder; dd4hep::Detector* m_dd4hep; - - Gaudi::Property<float> m_scale{ this, "Scale", 1 }; - - // Input collections - DataHandle<edm4hep::SimCalorimeterHitCollection> r_SimCaloCol{"SimCaloCol", Gaudi::DataHandle::Reader, this}; - mutable Gaudi::Property<std::string> _readoutName{this, "ReadOutName", "CaloHitsCollection", "Readout name"}; + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + //dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + std::map<std::string, dd4hep::DDSegmentation::BitFieldCoder*> map_readout_decoder; + dd4hep::VolumeManager m_volumeManager; + + TF1* f_SiPMResponse = nullptr; + TF1* f_SiPMSigmaDet = nullptr; + TF1* f_SiPMSigmaRecp = nullptr; + TF1* f_SiPMSigmaRecm = nullptr; + TF1* f_AsymGauss = nullptr; + TF1* f_DarkNoise = nullptr; + TGraph* g_SiPMDCR_vs_NIEL = nullptr; + TGraph* g_CryLYRatio_vs_TID = nullptr; + + // Input and collections + typedef DataHandle<edm4hep::SimCalorimeterHitCollection> SimCaloType; + typedef DataHandle<edm4hep::CalorimeterHitCollection> CaloType; + typedef DataHandle<edm4hep::MCRecoCaloAssociationCollection> CaloSimAssoType; //Calorimeter - SimCalorimeter + typedef DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection> CaloParticleAssoType; //Calorimeter - MCParticle + + Gaudi::Property< std::vector<std::string> > name_SimCaloHit{ this, "SimCaloHitCollection", {"EcalBarrelCollection"} }; + Gaudi::Property< std::vector<std::string> > name_Readout{ this, "ReadOutName", {"EcalBarrelCollection"} }; + Gaudi::Property< std::vector<std::string> > name_CaloHit{ this, "CaloHitCollection", {"ECALBarrel"} }; + Gaudi::Property< std::vector<std::string> > name_CaloAsso{ this, "CaloAssociationCollection", {"ECALBarrelAssoCol"} }; + Gaudi::Property< std::vector<std::string> > name_CaloMCPAsso{ this, "CaloMCPAssociationCollection", {"ECALBarrelParticleAssoCol"} }; + + std::vector<SimCaloType*> _inputSimHitCollection; + std::vector<CaloType*> _outputHitCollection; + std::vector<CaloSimAssoType*> _outputCaloSimAssoCol; + std::vector<CaloParticleAssoType*> _outputCaloMCPAssoCol; + + //DataHandle<edm4hep::SimCalorimeterHitCollection> r_SimCaloCol{"SimCaloCol", Gaudi::DataHandle::Reader, this}; + + //mutable Gaudi::Property<std::string> _readoutName{this, "ReadOutName", "CaloHitsCollection", "Readout name"}; mutable Gaudi::Property<std::string> _filename{this, "OutFileName", "testout.root", "Output file name"}; mutable Gaudi::Property<int> _UseRelDigi{this, "UseRealisticDigi", 1, "If use the realistic model"}; @@ -100,37 +140,66 @@ protected: mutable Gaudi::Property<int> _Nskip{this, "SkipEvt", 0, "Skip event"}; mutable Gaudi::Property<float> _seed{this, "Seed", 2131, "Random Seed"}; mutable Gaudi::Property<int> _Debug{this, "Debug", 0, "Debug level"}; - mutable Gaudi::Property<float> _Eth {this, "EnergyThreshold", 0.001, "Energy Threshold (/GeV)"}; - mutable Gaudi::Property<float> r_cali{this, "CalibrECAL", 1, "Calibration coefficients for ECAL"}; - mutable Gaudi::Property<float> Latt{this, "AttenuationLength", 7000, "Crystal Attenuation Length(mm)"}; + mutable Gaudi::Property<float> Latt{this, "AttenuationLength", 8000, "Crystal Attenuation Length(mm)"}; mutable Gaudi::Property<float> Tres{this, "TimeResolution", 0.1, "Crystal time resolution in one side (ns)"}; mutable Gaudi::Property<float> nMat{this, "MatRefractive", 2.15, "Material refractive index of crystal"}; mutable Gaudi::Property<float> Tinit{this, "InitalTime", 2, "Start time (ns)"}; - mutable Gaudi::Property<float> _Qthfrac {this, "ChargeThresholdFrac", 0.05, "Charge threshold fraction"}; mutable Gaudi::Property<int> fUseDigiScint{this, "UseDigiScint", 1, "Add scintillation effect in digitization"}; - mutable Gaudi::Property<int> fUseDigiSaturation{this, "UseDigiSaturation", 0, "Add SiPM saturation effect in digitization"}; - mutable Gaudi::Property<int> fUseDigiADC{this, "UseDigiADC", 1, "Add ADC precision effect in digitization"}; - - mutable Gaudi::Property<int> fADC{this, "ADC", 4096, "Total ADC conuts"}; + mutable Gaudi::Property<int> fUseCryTemp{this, "UseCryTemp", 1, "Add crystal temperature effect in digitization"}; + mutable Gaudi::Property<int> fUseCryTempCor{this, "UseCryTempCor", 1, "Add correction on crystal temperature effect in digitization"}; + mutable Gaudi::Property<int> fUseSiPMTemp{this, "UseSiPMTemp", 1, "Add SiPM temperature effect in digitization"}; + mutable Gaudi::Property<int> fUseSiPMTempCor{this, "UseSiPMTempCor", 1, "Add correction on SiPM temperature effect in digitization"}; + mutable Gaudi::Property<int> fUseCryTID{this, "UseCryTID", 0, "Add TID effect on crystal"}; + mutable Gaudi::Property<int> fUseCryTIDCor{this, "UseCryTIDCor", 0, "Add correction on TID effect on crystal"}; + mutable Gaudi::Property<int> fUseSiPMNIEL{this, "UseSiPMNIEL", 1, "Add NIEL effect on SiPM"}; + mutable Gaudi::Property<int> fUseSiPMNIELCor{this, "UseSiPMNIELCor", 0, "Add NIEL effect on SiPM"}; + + mutable Gaudi::Property<int> fADC{this, "ADC", 8192, "Total ADC conuts"}; mutable Gaudi::Property<int> fNofGain{this, "NofGain", 3, "Number of gain modes"}; - mutable Gaudi::Property<int> fADCSwitch{this, "ADCSwitch", 4000, "switching point of different gain mode"}; - mutable Gaudi::Property<float> fGainRatio_12{this, "GainRatio_12", 15, "Gain-1 over Gain-2"}; - mutable Gaudi::Property<float> fGainRatio_23{this, "GainRatio_23", 10, "Gain-2 over Gain-3"}; - mutable Gaudi::Property<float> fEcalCryMipLY{this, "EcalCryMipLY", 100, "Crystal light yield (p.e./MIP)"}; - mutable Gaudi::Property<float> fEcalMIPEnergy{this, "EcalMIPEnergy", 8.9, "MIP Energy deposit in 1cm BGO (MeV/MIP)"}; - mutable Gaudi::Property<int> fEcalSiPMPixels{this, "EcalSiPMPixels", 250000, "Pixels number of SiPM"}; - mutable Gaudi::Property<float> fEcalChargeADCMean{this, "EcalChargeADCMean", 5, "ADC per p.e. for Gain-1 (ADC)"}; - mutable Gaudi::Property<float> fEcalChargeADCSigma{this, "EcalChargeADCSigma", 2.5, "Sigma of ADC per p.e. for Gain-1 (ADC)"}; - mutable Gaudi::Property<float> fEcalADCError{this, "EcalADCError", 0.002, "ADC precision"}; - mutable Gaudi::Property<float> fEcalNoiseADCSigma{this, "EcalNoiseADCSigma", 3, "Sigma of electronic noise (ADC)"}; - mutable Gaudi::Property<float> fEcalMIP_Thre{this, "EcalMIP_Thre", 0.1, "Energy threshold for single readout end (MIP)"}; + mutable Gaudi::Property<int> fADCSwitch{this, "ADCSwitch", 8000, "switching point of different gain mode"}; + mutable Gaudi::Property<float> fPedestal{this, "Pedestal", 50, "ADC value of pedestal"}; + mutable Gaudi::Property<int> fSiPMDigiVerbose{this, "SiPMDigiVerbose", 1, "SiPM Digitization verbose. 0:w/o response, w/o correction; 1:w/ response, w/o correction; 2:w/ response, w/ simple correction; 3:w/ response, w/ full correction;"}; + mutable Gaudi::Property<float> fGainRatio_12{this, "GainRatio_12", 50, "Gain-1 over Gain-2"}; + mutable Gaudi::Property<float> fGainRatio_23{this, "GainRatio_23", 60, "Gain-2 over Gain-3"}; + mutable Gaudi::Property<float> fEcalMIPEnergy{this, "EcalMIPEnergy", 8.9, "MIP energy deposit in 1cm BGO (MeV/MIP)"}; + mutable Gaudi::Property<float> fEcalCryMipLY{this, "EcalCryMipLY", 200, "Detected light yield (p.e./MIP)"}; + mutable Gaudi::Property<float> fEcalCryIntLY{this, "EcalCryIntLY", 8200, "Intrinsic light yield (ph/MeV)"}; + mutable Gaudi::Property<float> fEcalSiPMPDE{this, "EcalSiPMPDE", 0.25, "SiPM PDE"}; + mutable Gaudi::Property<float> fEcalSiPMDCR{this, "EcalSiPMDCR", 2500000, "SiPM Dark Count Rate (Hz)"}; + mutable Gaudi::Property<float> fEcalSiPMCT{this, "EcalSiPMCT", 0.12, "SiPM crosstalk Probability"}; + mutable Gaudi::Property<float> fEcalTimeInterval{this, "EcalTimeInterval", 0.00000015, "Time interval for one readout (s)"}; + //mutable Gaudi::Property<float> fEcalCryAtt{this, "EcalCryAtt", fEcalCryMipLY/(fEcalCryIntLY*fEcalSiPMPDE*fEcalMIPEnergy), "Ratio of light attenuation, changed with SiPM PDE to achieve the assigned MIP light yield"}; + + mutable Gaudi::Property<float> fEcalSiPMGainMean{this, "EcalSiPMGainMean", 50, "SiPM gain: ADC per p.e. for Gain-1 (ADC)"}; + mutable Gaudi::Property<float> fEcalSiPMGainSigma{this, "EcalSiPMGainSigma", 0.08, "Fluctuation of single photoelctron ADC around the mean value for single device (%)"}; + mutable Gaudi::Property<float> fEcalASICNoiseSigma{this, "EcalASICNoiseSigma", 4, "Sigma of ASIC noise (ADC), which does not depend on gain"}; + mutable Gaudi::Property<float> fEcalFEENoiseSigma{this, "EcalFEENoiseSigma", 0, "Sigma of front-end-electronics noise (ADC), which depends on gain"}; + mutable Gaudi::Property<float> fEcalMIP_Thre{this, "EcalMIP_Thre", 0.05, "Energy threshold for single readout channel (MIP)"}; + + mutable Gaudi::Property<float> fEcalTempRef{this, "EcalTempRef", 298.15, "Reference temperature, top layer (K)"}; + mutable Gaudi::Property<float> fEcalTempFluc{this, "EcalTempFluc", 3, "ECAL temperature fluctuation around 25 degrees (K)"}; + mutable Gaudi::Property<float> fEcalTempGrad{this, "EcalTempGrad", 3./27, "The radial temperature gradient in the ECAL (K/crystal)"}; + mutable Gaudi::Property<float> fEcalBGOTempCoef{this, "EcalBGOTempCoef", -0.0138, "Temperature dependence of BGO light yield (%/K)"}; // doi:10.1007/s11433-014-5548-4 + mutable Gaudi::Property<float> fEcalSiPMGainTempCoef{this, "EcalSiPMGainTempCoef", -0.03, "Temperature dependence of SiPM gain (%/K)"}; // doi:10.1016/j.nima.2016.09.053 + mutable Gaudi::Property<float> fEcalSiPMDCRTempCoef{this, "EcalSiPMDCRTempCoef", 3.34/80, "Temperature dependence of SiPM DCR (10^{k*deltaT})"}; // doi:10.1016/j.nima.2016.09.053 + + mutable Gaudi::Property<float> fEcalCryTID{this, "EcalCryTID", 10, "Total ionizing dose in crystal (rad})"}; + mutable Gaudi::Property<float> fEcalSiPMNIEL{this, "EcalSiPMNIEL", 10, "Non-ionizing energy loss in SiPM, expressed as the equivalent 1 MeV neutron flux (cm-2s-1})"}; + + // mutable Gaudi::Property<float> fEcalCryIntLYFlu{this, "EcalCryIntLYFlu", 0.1, "Fluctuation of crystal intrinsic light yield"}; + // mutable Gaudi::Property<float> fEcalSiPMPDEFlu{this, "EcalSiPMPDEFlu", 0.10, "Fluctuation of SiPM PDE"}; + // mutable Gaudi::Property<float> fEcalCryLYUn{this, "EcalCryLYUn", 0.00, "Uncertainty of light yield calibration"}; + // mutable Gaudi::Property<float> fEcalSiPMGainUn{this, "EcalSiPMGainUn", 0.00, "Uncertainty of SiPM gain calibration"}; + // mutable Gaudi::Property<float> fEcalSiPMGainMeanFlu{this, "EcalSiPMGainMeanFlu", 0.15, "Fluctuation of SiPM gain"}; + // mutable Gaudi::Property<float> fEcalADCError{this, "EcalADCError", 0.0, "ADC precision"}; + // Output collections - DataHandle<edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; - DataHandle<edm4hep::MCRecoCaloAssociationCollection> w_CaloAssociationCol{"ECALBarrelAssoCol", Gaudi::DataHandle::Writer, this}; - DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection> w_MCPCaloAssociationCol{"ECALBarrelParticleAssoCol", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::MCRecoCaloAssociationCollection> w_CaloAssociationCol{"ECALBarrelAssoCol", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection> w_MCPCaloAssociationCol{"ECALBarrelParticleAssoCol", Gaudi::DataHandle::Writer, this}; }; #endif diff --git a/Digitization/DigiCalo/src/EcalDigiAlgShort.cpp b/Digitization/DigiCalo/src/EcalDigiAlgShort.cpp new file mode 100644 index 00000000..d112d369 --- /dev/null +++ b/Digitization/DigiCalo/src/EcalDigiAlgShort.cpp @@ -0,0 +1,535 @@ +// Units by default: mm, ns. +// NOTE: This digitisation highly matches detector geometry CRDEcal_Short. +// TODO: read geometry information automatically. +#include "EcalDigiAlgShort.h" + +using namespace std; +using namespace dd4hep; + +DECLARE_COMPONENT( EcalDigiAlgShort ) + +EcalDigiAlgShort::EcalDigiAlgShort(const 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"); + declareProperty("CaloAssociationCollection", w_CaloAssociationCol, "Handle of CaloAssociation collection"); + declareProperty("CaloMCPAssociationCollection", w_MCPCaloAssociationCol, "Handle of CaloAssociation collection"); + + algname = name; + transform(algname.begin(), algname.end(), algname.begin(), ::tolower); +} + +StatusCode EcalDigiAlgShort::initialize() +{ + if (algname.find("barrel") != string::npos) + dettype = 1; + else if (algname.find("endcap") != string::npos) + dettype = 2; + else + throw "Incorrect detector type! Make sure that the name of the instance contains 'barrel' or 'endcap'!"; + + if (_writeNtuple) + { + string s_outfile = _filename; + m_wfile = new TFile(s_outfile.c_str(), "recreate"); + t_SimCont = new TTree("SimStep", "SimStep"); + t_SimHit = new TTree("SimHit", "SimHit"); + t_SimCont->Branch("step_x", &m_step_x); + t_SimCont->Branch("step_y", &m_step_y); + t_SimCont->Branch("step_z", &m_step_z); + t_SimCont->Branch("step_t", &m_step_t); + t_SimCont->Branch("stepHit_x", &m_stepHit_x); + t_SimCont->Branch("stepHit_y", &m_stepHit_y); + t_SimCont->Branch("stepHit_z", &m_stepHit_z); + t_SimCont->Branch("step_E", &m_step_E); + t_SimCont->Branch("step_T", &m_step_T); + t_SimHit->Branch("totE_Truth", &totE_Truth); + t_SimHit->Branch("totE_Digi", &totE_Digi); + t_SimHit->Branch("simHit_x", &m_simHit_x); + t_SimHit->Branch("simHit_y", &m_simHit_y); + t_SimHit->Branch("simHit_z", &m_simHit_z); + t_SimHit->Branch("simHit_T", &m_simHit_T); + t_SimHit->Branch("simHit_Q_Truth", &m_simHit_Q_Truth); + t_SimHit->Branch("simHit_Q_Digi", &m_simHit_Q_Digi); + t_SimHit->Branch("simHit_module", &m_simHit_module); + t_SimHit->Branch("simHit_stave", &m_simHit_stave); + t_SimHit->Branch("simHit_layer", &m_simHit_layer); + if (dettype == 1) + { + t_SimHit->Branch("simHit_phi", &m_simHit_phi_x); + t_SimHit->Branch("simHit_iz", &m_simHit_z_y); + } + else if (dettype == 2) + { + t_SimHit->Branch("simHit_ix", &m_simHit_phi_x); + t_SimHit->Branch("simHit_iy", &m_simHit_z_y); + } + t_SimHit->Branch("simHit_cellID", &m_simHit_cellID); + } + + cout << "EcalDigiAlgShort::m_scale=" << m_scale << endl; + m_geosvc = service<IGeomSvc>("GeomSvc"); + + if (!m_geosvc) + throw "EcalDigiAlgShort: Failed to find GeomSvc ..."; + + m_dd4hep = m_geosvc->lcdd(); + + if (!m_dd4hep) + throw "EcalDigiAlgShort: Failed to get dd4hep::Detector ..."; + + m_cellIDConverter = new rec::CellIDPositionConverter(*m_dd4hep); + m_decoder = m_geosvc->getDecoder(_readoutName); + + if (!m_decoder) + { + error() << "Failed to get the decoder. " << endmsg; + return StatusCode::FAILURE; + } + + rndm.SetSeed(_seed); + cout << "EcalDigiAlgShort::initialize" << endl; + return GaudiAlgorithm::initialize(); +} + +StatusCode EcalDigiAlgShort::execute() +{ + if (_nEvt == 0) + cout << "EcalDigiAlgShort::execute begins..." << endl; + + if (dettype == 1) + cout << "Barrel, processing event " << _nEvt << endl; + else if (dettype == 2) + cout << "End-cap, processing event " << _nEvt << endl; + + if (_nEvt < _Nskip) + { + ++_nEvt; + return StatusCode::SUCCESS; + } + + Clear(); + + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); + edm4hep::MCRecoCaloAssociationCollection* caloAssoVec = w_CaloAssociationCol.createAndPut(); + edm4hep::MCRecoCaloParticleAssociationCollection* caloMCPAssoVec = w_MCPCaloAssociationCol.createAndPut(); + vector<edm4hep::SimCalorimeterHit> m_simhitCol; + m_simhitCol.clear(); + vector<CaloCrystalShort> m_hitCol; + m_hitCol.clear(); + + if (SimHitCol == 0) + { + cout << "SimCalorimeterHitCollection not found" << endl; + return StatusCode::SUCCESS; + } + + if (_Debug >= 1) + cout << "Digitisation, input sim hit size = " << SimHitCol->size() << endl; + + totE_Truth = 0; + totE_Digi = 0; + + // Merge input simhit (steps) to real simhit (crystal). + MergeHits(*SimHitCol, m_simhitCol); + if (_Debug >= 1) + cout << "Hit merging finished, Nhit = " << m_simhitCol.size() << endl; + + // Loop in SimHit, digitise SimHit to DigiHit + for (int i = 0; i < m_simhitCol.size(); ++i) + { + auto SimHit = m_simhitCol.at(i); + + const unsigned long long id = SimHit.getCellID(); + CaloCrystalShort hitcrystal; + hitcrystal.setcellID(id); + if (dettype == 1) + hitcrystal.setcellID(m_decoder->get(id, "system"), + m_decoder->get(id, "module"), + m_decoder->get(id, "stave"), + m_decoder->get(id, "layer"), + m_decoder->get(id, "phi"), + m_decoder->get(id, "z")); + else if (dettype == 2) + hitcrystal.setcellID(m_decoder->get(id, "system"), + m_decoder->get(id, "module"), + m_decoder->get(id, "stave"), + m_decoder->get(id, "layer"), + m_decoder->get(id, "x"), + m_decoder->get(id, "y")); + + Position hitpos = m_cellIDConverter->position(id); + TVector3 pos(10 * hitpos.x(), 10 * hitpos.y(), 10 * hitpos.z()); // cm to mm. + hitcrystal.setPosition(pos); + const double distcrystal = pos.Mag(); + + MCParticleToEnergyWeightMap MCPEnMap; + MCPEnMap.clear(); + vector<HitStep> Digivec; + Digivec.clear(); + double totQ_Truth = 0; + double totQ_Digi = 0; + double totQ = 0; + + // Loop in all SimHitContribution (G4Step). + for (int iCont = 0; iCont < SimHit.contributions_size(); ++iCont) + { + auto conb = SimHit.getContributions(iCont); + if (!conb.isAvailable()) + { + cout << "EcalDigiAlgShort cannot get SimHitContribution: " << iCont << endl; + continue; + } + + const double en = conb.getEnergy(); + if (en == 0) + continue; + + auto mcp = conb.getParticle(); + MCPEnMap[mcp] += en; + TVector3 steppos(conb.getStepPosition().x, conb.getStepPosition().y, conb.getStepPosition().z); + TVector3 rpos = steppos - hitcrystal.getPosition(); + const double disthit = steppos.Mag(); + const float step_time = conb.getTime(); + + m_step_x.emplace_back(steppos.x()); + m_step_y.emplace_back(steppos.y()); + m_step_z.emplace_back(steppos.z()); + m_step_t.emplace_back(step_time); + m_step_E.emplace_back(en); + m_stepHit_x.emplace_back(hitcrystal.getPosition().x()); + m_stepHit_y.emplace_back(hitcrystal.getPosition().y()); + m_stepHit_z.emplace_back(hitcrystal.getPosition().z()); + + if (_Debug >= 3) + { + cout << "Cell: " << hitcrystal.getModule() << " " << hitcrystal.getStave() << " " << hitcrystal.getLayer() << " " << hitcrystal.getPhiX() << " " << hitcrystal.getZY() << endl; + cout << "Cell position: " << hitcrystal.getPosition().x() << '\t' << hitcrystal.getPosition().y() << '\t' << hitcrystal.getPosition().z() << endl; + cout << "Step position: " << steppos.x() << '\t' << steppos.y() << '\t' << steppos.z() << endl; + cout << "Relative position: " << rpos.x() << '\t' << rpos.y() << '\t' << rpos.z() << endl; + } + + // ####### For Charge Digitisation ####### + const int sign = (distcrystal >= disthit) ? 1 : -1; + const double Ratio = exp(-(0.5 * fEcalCryLen + sign * rpos.Mag()) / Latt); + const double Qi = en * Ratio; + + if (_Debug >= 3) + { + cout << Qi << endl; + cout << sign * rpos.Mag() << endl; + } + + totQ_Truth += Qi; + + // ####### For Time Digitisation ####### + double Ti = -1; + int looptime = 0; + while (Ti < 0) + { + Ti = Tinit + rndm.Gaus(nMat * (0.5 * fEcalCryLen + sign * rpos.Mag()) / C, Tres) + step_time; + ++looptime; + if (looptime > 500) + { + cout << "ERROR: Time for step " << iCont << " is not positive!" << endl; + break; + } + } + if (looptime > 500) + continue; + + m_step_T.emplace_back(Ti); + totQ += Qi; + + HitStep stepout; + stepout.setQ(Qi); + stepout.setT(Ti); + Digivec.emplace_back(stepout); + } + + // ####################################### + // ####### Ideal Time Digitisation ####### + // ####################################### + + sort(Digivec.begin(), Digivec.end()); + double thQ = 0; + double thT; + for (int iCont = 0; iCont < Digivec.size(); ++iCont) + { + thQ += Digivec[iCont].getQ(); + if (thQ > totQ * _Qthfrac) + { + thT = Digivec[iCont].getT(); + if (_Debug >= 3) + cout << "T at index " << iCont << ": " << thT << endl; + break; + } + } + + if (_UseRelDigi) + { + // ############################################# + // ####### Realistic Charge Digitisation ####### + // ############################################# + +// const double sEcalCryMipLY = rndm.Gaus(fEcalCryMipLY, 0.1 * fEcalCryMipLY); + const double sEcalCryMipLY = fEcalCryMipLY; + + // TODO: fEcalMIPEnergy should depend on crystal size. + const int ScinGen = round(rndm.Poisson(totQ_Truth * 1000 / fEcalMIPEnergy * sEcalCryMipLY)); + + totQ_Digi = 0.001 * EnergyDigi(ScinGen, sEcalCryMipLY); + } + else + { + if (totQ_Truth != 0) + totQ_Digi = totQ_Truth; + if (totQ_Digi / fEcalMIPEnergy < fEcalMIP_Thre) + totQ_Digi = 0; + } + + if (totQ_Digi == 0) + continue; + + hitcrystal.setQ(totQ_Digi); + hitcrystal.setT(thT); + + // ################################## + // ####### Some associations ####### + // ################################## + + // 2 hits with double-readout time. + edm4hep::Vector3f m_pos(hitcrystal.getPosition().X(), hitcrystal.getPosition().Y(), hitcrystal.getPosition().Z()); + auto digiHit = caloVec->create(); + digiHit.setCellID(hitcrystal.getcellID()); + digiHit.setEnergy(hitcrystal.getQ()); + digiHit.setTime(hitcrystal.getT()); + digiHit.setPosition(m_pos); + + // SimHit - CaloHit association + auto rel = caloAssoVec->create(); + rel.setRec(digiHit); + rel.setSim(SimHit); + rel.setWeight(1.0); + + // MCParticle - CaloHit association +// float maxMCE = -99.; +// edm4hep::MCParticle selMCP; + for (auto iter: MCPEnMap) + { +// if (iter.second > maxMCE) +// { +// maxMCE = iter.second; +// selMCP = iter.first; +// } + auto rel_MCP = caloMCPAssoVec->create(); + rel_MCP.setRec(digiHit); + rel_MCP.setSim(iter.first); + rel_MCP.setWeight(iter.second / SimHit.getEnergy()); + } + +// if (selMCP.isAvailable()) +// { +// auto rel_MCP = caloMCPAssoVec->create(); +// rel_MCP.setRec(digiHit); +// rel_MCP.setSim(selMCP); +// rel_MCP.setWeight(1.0); +// } + + // ################################## + // ####### Writing into trees ####### + // ################################## + + m_hitCol.emplace_back(hitcrystal); + if (hitcrystal.getQ() > 0) + totE_Digi += hitcrystal.getQ(); + if (totQ_Truth > 0.001 * fEcalMIPEnergy * fEcalMIP_Thre) + totE_Truth += totQ_Truth; + + if (_writeNtuple) + { + m_simHit_x.emplace_back(hitcrystal.getPosition().x()); + m_simHit_y.emplace_back(hitcrystal.getPosition().y()); + m_simHit_z.emplace_back(hitcrystal.getPosition().z()); + m_simHit_Q_Truth.emplace_back(totQ_Truth); + m_simHit_Q_Digi.emplace_back(hitcrystal.getQ()); + m_simHit_T.emplace_back(hitcrystal.getT()); + m_simHit_module.emplace_back(hitcrystal.getModule()); + m_simHit_stave.emplace_back(hitcrystal.getStave()); + m_simHit_layer.emplace_back(hitcrystal.getLayer()); + m_simHit_phi_x.emplace_back(hitcrystal.getPhiX()); + m_simHit_z_y.emplace_back(hitcrystal.getZY()); + m_simHit_cellID.emplace_back(hitcrystal.getcellID()); + } + } + + if (_writeNtuple) + { + t_SimCont->Fill(); + t_SimHit->Fill(); + } + + if (_Debug >= 1) + cout << "End Loop: Hit Digitisation" << endl; + + cout << "Total Truth Energy: " << totE_Truth << endl; + cout << "Total Digitised Energy: " << totE_Digi << endl; + + ++_nEvt; + m_simhitCol.clear(); + return StatusCode::SUCCESS; +} + +StatusCode EcalDigiAlgShort::finalize() +{ + if (_writeNtuple) + { + m_wfile->cd(); + t_SimCont->Write(); + t_SimHit->Write(); + m_wfile->Close(); + delete m_wfile; + } + + info() << "Processed " << _nEvt << " events " << endmsg; + delete m_cellIDConverter; + return GaudiAlgorithm::finalize(); +} + +StatusCode EcalDigiAlgShort::MergeHits(const edm4hep::SimCalorimeterHitCollection& m_col, vector<edm4hep::SimCalorimeterHit>& m_hits) +{ + m_hits.clear(); + vector<edm4hep::MutableSimCalorimeterHit> m_mergedhit; + m_mergedhit.clear(); + + for (int iter = 0; iter < m_col.size(); ++iter) + { + edm4hep::SimCalorimeterHit m_step = m_col[iter]; + if (!m_step.isAvailable()) + { + cout << "ERROR HIT!" << endl; + continue; + } + if (m_step.getEnergy() == 0 || m_step.contributions_size() < 1) + continue; + unsigned long long cellid = m_step.getCellID(); + Position hitpos = m_cellIDConverter->position(cellid); + edm4hep::Vector3f pos(10 * hitpos.x(), 10 * hitpos.y(), 10 * hitpos.z()); + + edm4hep::MutableCaloHitContribution conb; + conb.setEnergy(m_step.getEnergy()); + conb.setStepPosition(m_step.getPosition()); + conb.setParticle(m_step.getContributions(0).getParticle()); + conb.setTime(m_step.getContributions(0).getTime()); + + edm4hep::MutableSimCalorimeterHit m_hit = find(m_mergedhit, cellid); + if (m_hit.getCellID() == 0) + { + m_hit.setCellID(cellid); + m_hit.setPosition(pos); + m_mergedhit.emplace_back(m_hit); + } + m_hit.addToContributions(conb); + m_hit.setEnergy(m_hit.getEnergy() + m_step.getEnergy()); + } + + for (auto iter = m_mergedhit.begin(); iter != m_mergedhit.end(); ++iter) + { + edm4hep::SimCalorimeterHit constsimhit = *iter; + m_hits.emplace_back(constsimhit); + } + + return StatusCode::SUCCESS; +} + +const double EcalDigiAlgShort::EnergyDigi(const double& ScinGen, const double& sEcalCryMipLY) +{ + const Int_t sPix = int(ScinGen); + +// if (sPix / sEcalCryMipLY < fEcalMIP_Thre) +// return 0; +// return sPix / sEcalCryMipLY * fEcalMIPEnergy; + + // ####### SiPM Saturation ####### +// sPix = round(fEcalSiPMPixels * (1 - TMath::Exp(-sPix / fEcalSiPMPixels))); + + // ################################ + // ####### ADC Digitisation ####### + // ################################ + + Double_t sADCMean = sPix * fEcalChargeADCMean; + Double_t sADCSigma = TMath::Sqrt(sPix * fEcalChargeADCSigma * fEcalChargeADCSigma + fEcalNoiseADCSigma * fEcalNoiseADCSigma); + Int_t sADC = round(rndm.Gaus(sADCMean, sADCSigma)); + Double_t sMIP; + + if (sADC <= fADCSwitch) + { + sADC = round(rndm.Gaus(sADC, fEcalADCError * sADC)); + sMIP = sADC / fEcalChargeADCMean / sEcalCryMipLY; + } + else if (sADC > fADCSwitch && int(sADC / fGainRatio_12) <= fADCSwitch) + { + sADCMean = sPix * fEcalChargeADCMean / fGainRatio_12; + sADCSigma = TMath::Sqrt(sPix * fEcalChargeADCSigma / fGainRatio_12 * fEcalChargeADCSigma / fGainRatio_12 + fEcalNoiseADCSigma * fEcalNoiseADCSigma); + sADC = round(rndm.Gaus(sADCMean, sADCSigma)); + sADC = round(rndm.Gaus(sADC, fEcalADCError * sADC)); + sMIP = sADC / fEcalChargeADCMean * fGainRatio_12 / sEcalCryMipLY; + } + else + { + sADCMean = sPix * fEcalChargeADCMean / fGainRatio_12 / fGainRatio_23; + sADCSigma = TMath::Sqrt(sPix * fEcalChargeADCSigma / fGainRatio_12 / fGainRatio_23 * fEcalChargeADCSigma / fGainRatio_12 / fGainRatio_23 + fEcalNoiseADCSigma * fEcalNoiseADCSigma); + sADC = round(rndm.Gaus(sADCMean, sADCSigma)); + sADC = round(rndm.Gaus(sADC, fEcalADCError * sADC)); + if (sADC > fADC - 1) + sADC = fADC - 1; + sMIP = sADC / fEcalChargeADCMean * fGainRatio_12 * fGainRatio_23 / sEcalCryMipLY; + } + + return (sMIP < fEcalMIP_Thre) ? 0 : sMIP * fEcalMIPEnergy; +} + +edm4hep::MutableSimCalorimeterHit EcalDigiAlgShort::find(const vector<edm4hep::MutableSimCalorimeterHit>& m_col, unsigned long long& cellid) const +{ + for (int i = 0; i < m_col.size(); ++i) + { + edm4hep::MutableSimCalorimeterHit hit = m_col.at(i); + if (hit.getCellID() == cellid) + return hit; + } + edm4hep::MutableSimCalorimeterHit hit; + hit.setCellID(0); + return hit; +} + +void EcalDigiAlgShort::Clear() +{ + totE_Truth = -99; + totE_Digi = -99; + m_step_x.clear(); + m_step_y.clear(); + m_step_z.clear(); + m_step_t.clear(); + m_step_E.clear(); + m_stepHit_x.clear(); + m_stepHit_y.clear(); + m_stepHit_z.clear(); + m_step_T.clear(); + m_simHit_x.clear(); + m_simHit_y.clear(); + m_simHit_z.clear(); + m_simHit_T.clear(); + m_simHit_Q_Truth.clear(); + m_simHit_Q_Digi.clear(); + m_simHit_module.clear(); + m_simHit_stave.clear(); + m_simHit_layer.clear(); + m_simHit_phi_x.clear(); + m_simHit_z_y.clear(); + m_simHit_cellID.clear(); +} diff --git a/Digitization/DigiCalo/src/EcalDigiAlgShort.h b/Digitization/DigiCalo/src/EcalDigiAlgShort.h new file mode 100644 index 00000000..8e4effd5 --- /dev/null +++ b/Digitization/DigiCalo/src/EcalDigiAlgShort.h @@ -0,0 +1,137 @@ +#ifndef _ECAL_DIGI_ALG_SHORT_H +#define _ECAL_DIGI_ALG_SHORT_H + +#include "k4FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/MutableCaloHitContribution.h" +#include "edm4hep/MutableSimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/Cluster.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/MCRecoCaloAssociationCollection.h" +#include "edm4hep/MCRecoCaloParticleAssociationCollection.h" +#include "edm4hep/Vector3f.h" + +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include <DD4hep/Detector.h> +#include <DD4hep/Objects.h> +#include <DD4hep/Segmentations.h> +#include "DetInterface/IGeomSvc.h" + +#include "TVector3.h" +#include "TRandom3.h" +#include "TFile.h" +#include "TTree.h" +#include "TString.h" +#include "TMath.h" +#include "TH3.h" +#include "TH1.h" + +#include <iostream> +#include <algorithm> +#include <map> +#include <random> +#include <math.h> +#include <cmath> +#include <cstdlib> +#include <TTimeStamp.h> +#include <ctime> +#include "time.h" + +#include "HitStep.h" +#include "CaloCrystalShort.h" + +const double C = 299.79; // In mm/ns +const double PI = 3.141592653; + +class EcalDigiAlgShort : public GaudiAlgorithm +{ +public: + EcalDigiAlgShort(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize(); + + virtual StatusCode execute(); + + virtual StatusCode finalize(); + + StatusCode MergeHits(const edm4hep::SimCalorimeterHitCollection& m_col, std::vector<edm4hep::SimCalorimeterHit>& m_hits); + + edm4hep::MutableSimCalorimeterHit find(const std::vector<edm4hep::MutableSimCalorimeterHit>& m_col, unsigned long long& cellid) const; + + const double EnergyDigi(const double& ScinGen, const double& sEcalCryMipLY); + + void Clear(); + +protected: + std::string algname; + int dettype; // 1 for barrel, 2 for end-cap. + SmartIF <IGeomSvc> m_geosvc; + typedef std::vector<float> FloatVec; + typedef std::map<const edm4hep::MCParticle, float> MCParticleToEnergyWeightMap; + + int _nEvt; + float m_length; + TRandom3 rndm; + TFile* m_wfile; + TTree* t_SimCont; + TTree* t_SimHit; + + double totE_Truth, totE_Digi; + FloatVec m_step_t; + FloatVec m_step_x, m_step_y, m_step_z, m_step_E, m_step_T, m_stepHit_x, m_stepHit_y, m_stepHit_z; + FloatVec m_simHit_x, m_simHit_y, m_simHit_z, m_simHit_T, m_simHit_Q_Truth, m_simHit_Q_Digi, m_simHit_module, m_simHit_stave, m_simHit_layer; + FloatVec m_simHit_phi_x, m_simHit_z_y; // Phi and z for barrel, x and y for end-cap + std::vector<unsigned long long> m_simHit_cellID; + + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + dd4hep::Detector* m_dd4hep; + + Gaudi::Property<float> m_scale{this, "Scale", 1}; + + // Input collections + DataHandle <edm4hep::SimCalorimeterHitCollection> r_SimCaloCol{"SimCaloCol", Gaudi::DataHandle::Reader, this}; + mutable Gaudi::Property <std::string> _readoutName{this, "ReadOutName", "CaloHitsCollection", "Readout name"}; + mutable Gaudi::Property <std::string> _filename{this, "OutFileName", "testout.root", "Output file name"}; + mutable Gaudi::Property<int> _UseRelDigi{this, "UseRealisticDigi", 1, "If use the realistic model"}; + + // Input parameters + mutable Gaudi::Property<int> _writeNtuple{this, "WriteNtuple", 1, "Write ntuple"}; + mutable Gaudi::Property<int> _Nskip{this, "SkipEvt", 0, "Skip event"}; + mutable Gaudi::Property<int> _seed{this, "Seed", 2024, "Random Seed"}; + mutable Gaudi::Property<int> _Debug{this, "Debug", 0, "Debug level"}; + mutable Gaudi::Property<float> _Eth{this, "EnergyThreshold", 0.001, "Energy Threshold (/GeV)"}; + mutable Gaudi::Property<float> r_cali{this, "CalibrECAL", 1, "Calibration coefficients for ECAL"}; + mutable Gaudi::Property<float> Latt{this, "AttenuationLength", 7000, "Crystal Attenuation Length(mm)"}; + mutable Gaudi::Property<float> Tres{this, "TimeResolution", 0.1, "Crystal time resolution in one side (ns)"}; + mutable Gaudi::Property<float> nMat{this, "MatRefractive", 2.15, "Material refractive index of crystal"}; + mutable Gaudi::Property<float> Tinit{this, "InitalTime", 2, "Start time (ns)"}; + + mutable Gaudi::Property<float> _Qthfrac{this, "ChargeThresholdFrac", 0.05, "Charge threshold fraction"}; + + mutable Gaudi::Property<int> fADC{this, "ADC", 4096, "Total ADC counts"}; + mutable Gaudi::Property<int> fNofGain{this, "NofGain", 3, "Number of gain modes"}; + mutable Gaudi::Property<int> fADCSwitch{this, "ADCSwitch", 4000, "switching point of different gain mode"}; + mutable Gaudi::Property<float> fGainRatio_12{this, "GainRatio_12", 15, "Gain-1 over Gain-2"}; + mutable Gaudi::Property<float> fGainRatio_23{this, "GainRatio_23", 10, "Gain-2 over Gain-3"}; + mutable Gaudi::Property<float> fEcalCryLen{this, "EcalCryLen", 41, "Crystal length (mm)"}; + mutable Gaudi::Property<float> fEcalCryMipLY{this, "EcalCryMipLY", 200, "Crystal light yield (p.e./MIP)"}; + mutable Gaudi::Property<float> fEcalMIPEnergy{this, "EcalMIPEnergy", 8.9, "MIP Energy deposit in 1cm BGO (MeV/MIP)"}; + mutable Gaudi::Property<int> fEcalSiPMPixels{this, "EcalSiPMPixels", 250000, "Pixels number of SiPM"}; + mutable Gaudi::Property<float> fEcalChargeADCMean{this, "EcalChargeADCMean", 5, "ADC per pe for Gain-1 (ADC)"}; + mutable Gaudi::Property<float> fEcalChargeADCSigma{this, "EcalChargeADCSigma", 2.5, "Sigma of ADC per pe for Gain-1 (ADC)"}; + mutable Gaudi::Property<float> fEcalADCError{this, "EcalADCError", 0.002, "ADC precision"}; + mutable Gaudi::Property<float> fEcalNoiseADCSigma{this, "EcalNoiseADCSigma", 3, "Sigma of electronic noise (ADC)"}; + mutable Gaudi::Property<float> fEcalMIP_Thre{this, "EcalMIP_Thre", 0.1, "Energy threshold for single readout end (MIP)"}; + + // Output collections + DataHandle <edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; + DataHandle <edm4hep::MCRecoCaloAssociationCollection> w_CaloAssociationCol{"ECALBarrelAssoCol", Gaudi::DataHandle::Writer, this}; + DataHandle <edm4hep::MCRecoCaloParticleAssociationCollection> w_MCPCaloAssociationCol{"ECALBarrelParticleAssoCol", Gaudi::DataHandle::Writer, this}; +}; + +#endif diff --git a/Digitization/DigiCalo/src/HcalDigiAlg.cpp b/Digitization/DigiCalo/src/HcalDigiAlg.cpp index d0d65cac..4650ebe5 100644 --- a/Digitization/DigiCalo/src/HcalDigiAlg.cpp +++ b/Digitization/DigiCalo/src/HcalDigiAlg.cpp @@ -35,23 +35,68 @@ HcalDigiAlg::HcalDigiAlg(const std::string& name, ISvcLocator* svcLoc) { // Input collections - declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); + declareProperty("MCParticle", m_MCParticleCol, "MCParticle collection (input)"); + //declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); // Output collections - declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); - declareProperty("CaloAssociationCollection", w_CaloAssociationCol, "Handle of CaloAssociation collection"); - declareProperty("CaloMCPAssociationCollection", w_MCPCaloAssociationCol, "Handle of CaloAssociation collection"); + //declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); + //declareProperty("CaloAssociationCollection", w_CaloAssociationCol, "Handle of CaloAssociation collection"); + //declareProperty("CaloMCPAssociationCollection", w_MCPCaloAssociationCol, "Handle of CaloAssociation collection"); } StatusCode HcalDigiAlg::initialize() { + // --- Initialize input and output collections + for(auto& simhit : name_SimCaloHit){ + if(!simhit.empty()) + _inputSimHitCollection.push_back( new SimCaloType(simhit, Gaudi::DataHandle::Reader, this) ); + } + + // --- Geometry service, cellID decoder + m_geosvc = service<IGeomSvc>("GeomSvc"); + if ( !m_geosvc ) throw "HcalDigiAlg :Failed to find GeomSvc ..."; + m_dd4hep = m_geosvc->lcdd(); + if ( !m_dd4hep ) throw "HcalDigiAlg :Failed to get dd4hep::Detector ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + + for(unsigned int i=0; i<name_Readout.size(); i++){ + if(name_Readout[i].empty()) continue; + dd4hep::DDSegmentation::BitFieldCoder* tmp_decoder = m_geosvc->getDecoder(name_Readout[i]); + if (!tmp_decoder) { + error() << "Failed to get the decoder for: " << name_Readout[i] << endmsg; + return StatusCode::FAILURE; + } + map_readout_decoder[name_SimCaloHit[i]] = tmp_decoder; + } + + // --- Output collection + for(auto& digihit : name_CaloHit){ + if(!digihit.empty()) + _outputHitCollection.push_back( new CaloType(digihit, Gaudi::DataHandle::Writer, this) ); + } + + for(auto& link : name_CaloAsso){ + if(!link.empty()) + _outputCaloSimAssoCol.push_back( new CaloSimAssoType(link, Gaudi::DataHandle::Writer, this) ); + } + + for(auto& link : name_CaloMCPAsso){ + if(!link.empty()) + _outputCaloMCPAssoCol.push_back( new CaloParticleAssoType(link, Gaudi::DataHandle::Writer, this) ); + } + + if(_writeNtuple){ std::string s_outfile = _filename; m_wfile = new TFile(s_outfile.c_str(), "recreate"); t_simHit = new TTree("simHit", "simHit"); + t_simHit->Branch("MC_EPx", &m_MC_EPx); + t_simHit->Branch("MC_EPy", &m_MC_EPy); + t_simHit->Branch("MC_EPz", &m_MC_EPz); t_simHit->Branch("totE", &m_totE); + t_simHit->Branch("totE_truth", &m_totE_truth); t_simHit->Branch("simHit_x", &m_simHit_x); t_simHit->Branch("simHit_y", &m_simHit_y); t_simHit->Branch("simHit_z", &m_simHit_z); @@ -64,26 +109,44 @@ StatusCode HcalDigiAlg::initialize() t_simHit->Branch("simHit_HG", &m_simHit_HG); t_simHit->Branch("simHit_LG", &m_simHit_LG); t_simHit->Branch("simHit_steps", &m_simHit_steps); + t_simHit->Branch("step_x", &m_step_x); + t_simHit->Branch("step_y", &m_step_y); + t_simHit->Branch("step_LY", &m_step_LY); - t_simHit->Branch("simHit_module", &m_simHit_module); + t_simHit->Branch("simHit_system", &m_simHit_system); t_simHit->Branch("simHit_stave", &m_simHit_stave); t_simHit->Branch("simHit_layer", &m_simHit_layer); - t_simHit->Branch("simHit_tower", &m_simHit_tower); - t_simHit->Branch("simHit_slice", &m_simHit_slice); + t_simHit->Branch("simHit_tile", &m_simHit_tile); + t_simHit->Branch("simHit_idx", &m_simHit_idx); + t_simHit->Branch("simHit_idy", &m_simHit_idy); + t_simHit->Branch("simHit_row", &m_simHit_row); + t_simHit->Branch("simHit_phi", &m_simHit_phi); t_simHit->Branch("simHit_cellID", &m_simHit_cellID); } - std::cout<<"HcalDigiAlg::m_scale="<<m_scale<<std::endl; - m_geosvc = service<IGeomSvc>("GeomSvc"); - if ( !m_geosvc ) throw "HcalDigiAlg :Failed to find GeomSvc ..."; - dd4hep::Detector* m_dd4hep = m_geosvc->lcdd(); - if ( !m_dd4hep ) throw "HcalDigiAlg :Failed to get dd4hep::Detector ..."; - m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); - m_decoder = m_geosvc->getDecoder(_readoutName); - if (!m_decoder) { - error() << "Failed to get the decoder. " << endmsg; - return StatusCode::FAILURE; - } + //Glass tile non-uniformity map (due to attenuation length) + TFile* map_file = new TFile(_TileLYMapFile.value().c_str(), "read"); + TString s_hitmap = TString("hitmap_") + TString(_EffAttenLength.value().c_str()); + GSTileResMap = (TH2D*)map_file->Get(s_hitmap); + if(!GSTileResMap || !_UseTileLYMap ){ + error() << "HcalDigiAlg: Failed to get the GS tile response map. Create a uniform one" << endmsg; + GSTileResMap = new TH2D("hitmap", "", 80, -20, 20, 80, -20, 20); + for(int i=0; i<80; i++){ + for(int j=0; j<80; j++){ + GSTileResMap->SetBinContent(i+1, j+1, _MIPLY ); + }} + } + else{ + //Scale map to light yield + TString s_h_Npe = TString("h_Npe_") + TString(_EffAttenLength.value().c_str()); + TH1D *h_Npe = (TH1D*)map_file->Get(s_h_Npe); + h_Npe->Fit("landau","Q"); + GSTileResMap->Scale( _MIPLY / h_Npe->GetFunction("landau")->GetParameter(1) ); + } + + //SiPM dark noise cross talk model: Borel distribution. + f_DarkNoise = new TF1("f_DarkNoise", "pow([0]*x, x-1) * exp(-[0]*x) / TMath::Factorial(x)"); + f_DarkNoise->SetParameter(0, _SiPMXTalk); rndm.SetSeed(_seed); std::cout<<"HcalDigiAlg::initialize"<<std::endl; @@ -101,147 +164,287 @@ StatusCode HcalDigiAlg::execute() Clear(); m_totE = 0.; - const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); - std::vector<edm4hep::SimCalorimeterHit> m_simhitCol; m_simhitCol.clear(); - - edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); - edm4hep::MCRecoCaloAssociationCollection* caloAssoVec = w_CaloAssociationCol.createAndPut(); - edm4hep::MCRecoCaloParticleAssociationCollection* caloMCPAssoVec = w_MCPCaloAssociationCol.createAndPut(); - - if(SimHitCol == 0) - { - std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; - return StatusCode::SUCCESS; - } - if(_Debug>=1) std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; - - MergeHits(*SimHitCol, m_simhitCol); - - for(int isim=0; isim<m_simhitCol.size(); isim++){ - - auto simhit = m_simhitCol.at(isim); - if(!simhit.isAvailable()) continue; - if(simhit.getEnergy()==0) continue; - - unsigned long long id = simhit.getCellID(); - edm4hep::Vector3f hitpos = simhit.getPosition(); - TVector3 tilepos(hitpos.x, hitpos.y, hitpos.z); //cm to mm. - - //Loop G4 steps to get the attenuated light yield. - double Ehit_truth = 0.; - double Ehit = 0.; - for(int iCont=0; iCont < simhit.contributions_size(); ++iCont){ - auto conb = simhit.getContributions(iCont); - if( !conb.isAvailable() ) { std::cout<<" Can not get SimHitContribution: "<<iCont<<std::endl; continue;} - TVector3 steppos(conb.getStepPosition().x, conb.getStepPosition().y, conb.getStepPosition().z); - - double _distance = (tilepos-steppos).Mag(); //Simplified: use R(step-center) not R(step-SiPM) as distance. - Ehit_truth += conb.getEnergy(); - Ehit += conb.getEnergy()*exp(-1.*_distance/_EffAttenLength); - } - double Ehit_att = Ehit; - - double sChargeOut = 0; - double sChargeOutHG = 0; - double sChargeOutLG = 0; - double Npe_scint = 0; - double Npe_SiPM = 0; - //Digitization - if(_UseRelDigi){ - // -- Scintillation (Energy -> MIP -> Np.e.) - int sPix = gRandom->Poisson(Ehit / _MIPCali * (_MIPADC / _PeADCMean)); - Npe_scint = sPix; - // -- Tile non-uniformity - sPix = sPix * (1.0 + gRandom->Uniform(-_TileRes, _TileRes)); - // -- SiPM Saturation (Np.e. -> Npixel) - sPix = std::round(_Pixel * (1.0 - TMath::Exp(-sPix * 1.0 / _Pixel))); - Npe_SiPM = sPix; - // -- ADC response (Npixel -> ADC) - double sChargeMean = sPix * _PeADCMean; - double sChargeSigma = sqrt(sPix * _PeADCSigma * _PeADCSigma); - sChargeOut = gRandom->Gaus(sChargeMean, sChargeSigma); - // -- (ADC->MIP) - sChargeOutHG = sChargeOut + gRandom->Gaus(_BaselineHG, _BaselineSigmaHG); - sChargeOutLG = sChargeOut / _HLRatio + gRandom->Gaus(_BaselineLG, _BaselineSigmaLG); - sChargeOutHG = std::round(gRandom->Gaus(sChargeOutHG, sChargeOutHG * _ADCError)); - sChargeOutLG = std::round(gRandom->Gaus(sChargeOutLG, sChargeOutLG * _ADCError)); - if (sChargeOutLG > _ADCLimit) - sChargeOutLG = _ADCLimit; - Double_t sMIP = 0; - if (sChargeOutHG > _ADCSwitch) + m_totE_truth = 0.; + for(int icol=0; icol<_inputSimHitCollection.size(); icol++){ + try{ + SimCaloType* r_SimCaloCol = _inputSimHitCollection[icol]; + CaloType* w_DigiCaloCol = _outputHitCollection[icol]; + CaloSimAssoType* w_CaloAssociationCol = _outputCaloSimAssoCol[icol]; + CaloParticleAssoType* w_MCPCaloAssociationCol = _outputCaloMCPAssoCol[icol]; + + const edm4hep::MCParticleCollection* const_MCPCol = m_MCParticleCol.get(); + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol->get(); + std::vector<edm4hep::SimCalorimeterHit> m_simhitCol; m_simhitCol.clear(); + + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol->createAndPut(); + edm4hep::MCRecoCaloAssociationCollection* caloAssoVec = w_CaloAssociationCol->createAndPut(); + edm4hep::MCRecoCaloParticleAssociationCollection* caloMCPAssoVec = w_MCPCaloAssociationCol->createAndPut(); + + if(const_MCPCol){ + int N_MCP = const_MCPCol->size(); + if(N_MCP==1){ + m_MC_EPx = const_MCPCol->at(0).getEndpoint().x; + m_MC_EPy = const_MCPCol->at(0).getEndpoint().y; + m_MC_EPz = const_MCPCol->at(0).getEndpoint().z; + } + } + + + if(SimHitCol == 0) { - sMIP = (sChargeOutLG - _BaselineLG) * _HLRatio / _MIPADC; - sChargeOutHG = _ADCSwitch; + std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; + return StatusCode::SUCCESS; } - else + + //Mean cross talk probability in this event + double mean_CT = 0; + for (int i = 1; i < 10; i++) { - sMIP = (sChargeOutHG - _BaselineHG) / _MIPADC; + mean_CT += (i-1)*f_DarkNoise->Eval(i); } - Ehit = sMIP * _MIPCali; - } - if(Ehit<_MIPCali*_Eth_Mip) continue; - - //Global calibration. - //TODO: add more digitization terms here. - double Ehit_cali = Ehit*r_cali; - - //Loop contributions to get hit time and MCParticle. - double Thit_ave = 0.; - double Ehit_raw = 0.; - MCParticleToEnergyWeightMap MCPEnMap; MCPEnMap.clear(); - for(int iConb=0; iConb<simhit.contributions_size(); ++iConb){ - auto conb = simhit.getContributions(iConb); - if(!conb.isAvailable()) continue; - if(conb.getEnergy()==0) continue; - - Thit_ave += conb.getTime(); - auto mcp = conb.getParticle(); - MCPEnMap[mcp] += conb.getEnergy(); - Ehit_raw += conb.getEnergy(); - } - Thit_ave = Thit_ave/simhit.contributions_size(); - //Create DigiHit - auto digiHit = caloVec->create(); - digiHit.setCellID(id); - digiHit.setEnergy(Ehit_cali); - digiHit.setTime(Thit_ave); - digiHit.setPosition(simhit.getPosition()); - - //Create SimHit-DigiHit association. - auto rel = caloAssoVec->create(); - rel.setRec(digiHit); - rel.setSim(simhit); - rel.setWeight(1.); - - //Create DigiHit-MCParticle association. - for(auto iter : MCPEnMap){ - auto rel_MC = caloMCPAssoVec->create(); - rel_MC.setRec(digiHit); - rel_MC.setSim(iter.first); - rel_MC.setWeight(iter.second/Ehit_raw); - } - - if(_writeNtuple){ - m_totE += digiHit.getEnergy(); - m_simHit_x.push_back(digiHit.getPosition().x); - m_simHit_y.push_back(digiHit.getPosition().y); - m_simHit_z.push_back(digiHit.getPosition().z); - m_simHit_E.push_back(digiHit.getEnergy()); - m_simHit_Etruth.push_back(Ehit_truth); - m_simHit_Eatt.push_back(Ehit_att); - m_simHit_rawQ.push_back(sChargeOut); - m_simHit_HG.push_back(sChargeOutHG); - m_simHit_LG.push_back(sChargeOutLG); - m_simHit_Npe_scint.push_back(Npe_scint); - m_simHit_Npe_sipm.push_back(Npe_SiPM); - m_simHit_steps.push_back(simhit.contributions_size()); - //m_simHit_module.push_back(m_decoder->get(id, "stave")); - //m_simHit_stave.push_back(m_decoder->get(id, "layer")); - //m_simHit_layer.push_back(m_decoder->get(id, "tile")); - //m_simHit_slice.push_back(m_decoder->get(id, "x")); - //m_simHit_tower.push_back(m_decoder->get(id, "y")); - m_simHit_cellID.push_back(id); + MergeHits(*SimHitCol, m_simhitCol); +//cout<<"Merged simhit size: "<<m_simhitCol.size()<<endl; + for(int isim=0; isim<m_simhitCol.size(); isim++){ + + auto simhit = m_simhitCol.at(isim); + if(!simhit.isAvailable()) {cout<<"Sim hit is not available"<<endl; continue;} + if(simhit.getEnergy()==0) {cout<<"Sim hit energy is 0"<<endl; continue;} + m_totE_truth += simhit.getEnergy(); + + unsigned long long id = simhit.getCellID(); + int hit_system = map_readout_decoder[name_Readout[icol]]->get(id, "system"); + edm4hep::Vector3f hitpos = simhit.getPosition(); + TVector3 tilepos(hitpos.x, hitpos.y, hitpos.z); //cm to mm. + double rotPhi = 0; + if(hit_system==22){ + int hit_stave = map_readout_decoder[name_Readout[icol]]->get(id, "stave"); + rotPhi = (hit_stave-5)*TMath::TwoPi()/16.; + if(rotPhi<0) rotPhi += TMath::TwoPi(); + } +//cout<<" Sim hit #"<<isim<<": system "<<hit_system<<", energy "<<simhit.getEnergy(); + //printf("Hit #%d: stave %d, pos (%.2f, %.2f, %.2f), Energy %.2f, step size %d \n", isim, hit_stave, hitpos.x, hitpos.y, hitpos.z, simhit.getEnergy(), simhit.contributions_size()); + //Loop G4 steps to get the attenuated light yield. + double Ehit = 0; + double Ehit_truth = 0.; + double Npe_att = 0; + float tempVar = gRandom->Gaus(0, _TempVariation); + float fLY_tempScale = (1 + tempVar * _TempCoef); + for(int iCont=0; iCont < simhit.contributions_size(); ++iCont){ + auto conb = simhit.getContributions(iCont); + if( !conb.isAvailable() ) { std::cout<<" Can not get SimHitContribution: "<<iCont<<std::endl; continue;} + Ehit_truth += conb.getEnergy(); + TVector3 steppos(conb.getStepPosition().x, conb.getStepPosition().y, conb.getStepPosition().z); + + //double _distance = (tilepos-steppos).Mag(); //Simplified: use R(step-center) not R(step-SiPM) as distance. + //m_step_R.push_back(_distance); + int ibinx = 0; + int ibiny = 0; + if(hit_system==22){ + TVector3 rot_tilepos = tilepos; rot_tilepos.RotateZ(rotPhi); + TVector3 rot_steppos = steppos; rot_steppos.RotateZ(rotPhi); + ibinx = ((rot_steppos-rot_tilepos).z()+20.)*2; + ibiny = ((rot_steppos-rot_tilepos).y()+20.)*2; + if(ibinx<0) ibinx = 0; + if(ibiny<0) ibiny = 0; + if(ibinx>79) ibinx = 79; + if(ibiny>79) ibiny = 79; + m_step_x.push_back((rot_steppos-rot_tilepos).z()); + m_step_y.push_back((rot_steppos-rot_tilepos).y()); + } + else if(hit_system==30){ + if(ibinx<0) ibinx = 0; + if(ibiny<0) ibiny = 0; + if(ibinx>79) ibinx = 79; + if(ibiny>79) ibiny = 79; + ibinx = ((steppos-tilepos).x()+20.)*2; + ibiny = ((steppos-tilepos).y()+20.)*2; + m_step_x.push_back((steppos-tilepos).x()); + m_step_y.push_back((steppos-tilepos).y()); + } + else error() << "Wrong cellID system: " << hit_system << endmsg; + //printf(" Step #%d: En %.2f, rotate angle %.2f, tile pos after rotation (%.2f, %.2f, %.2f), ", iCont, conb.getEnergy(), rotPhi, rot_tilepos.x(), rot_tilepos.y(), rot_tilepos.z()); + //printf("rel pos after rotation (%.2f, %.2f, %.2f) \n", (rot_steppos-rot_tilepos).x(), (rot_steppos-rot_tilepos).y(), (rot_steppos-rot_tilepos).z()); + //printf(" Project to bin (%d, %d), LY %.3f \n", ibinx, ibiny, GSTileResMap->GetBinContent( ibinx, ibiny )); + + m_step_LY.push_back(GSTileResMap->GetBinContent( ibinx, ibiny )); + } + Ehit = Npe_att / _MIPLY / fLY_tempScale * _MIPCali; + + double sChargeOut = 0; + double sChargeOutHG = 0; + double sChargeOutLG = 0; + double Npe_scint = 0; + double Npe_SiPM = 0; + //Digitization + if(_UseRelDigi){ + // -- Scintillation (Energy -> MIP -> Np.e.) + float fSiPMGainMean = _SiPMGainMean * (1 + tempVar * _SiPMGainTempCoef); + float fSiPMDCR = _SiPMDCR * pow(10, _SiPMDCRTempCoef * tempVar); + + // -- Scintillation (Energy -> MIP -> Np.e.) + int sPix = gRandom->Poisson(Npe_att); + Npe_scint = sPix; + // -- SiPM dark noise and cross talk + int darkcounts_mean = gRandom->Poisson(_SiPMDCR * _TimeInterval); + int darkcounts_CT = 0; + for(int i=0;i<darkcounts_mean;i++) + { + double darkcounts_rdm = gRandom->Uniform(0, 1); + int sum_darkcounts = 1; + if(! (darkcounts_rdm <= f_DarkNoise->Eval(sum_darkcounts))) + { + float prob = f_DarkNoise->Eval(sum_darkcounts); + while(darkcounts_rdm > prob) + { + sum_darkcounts++; + prob += f_DarkNoise->Eval(sum_darkcounts); + } + } + darkcounts_CT += sum_darkcounts; + } + sPix += darkcounts_CT; + + // -- SiPM Saturation (Np.e. -> Npixel) + sPix = std::round(_Pixel * (1.0 - TMath::Exp(-sPix * 1.0 / _Pixel))); + Npe_SiPM = sPix; + // -- ADC response (Npixel -> ADC) + float sSiPMGainMean = fSiPMGainMean; + float sSiPMGainSigma = sSiPMGainMean * _SiPMGainSigma; + float sSiPMNoiseSigma = _SiPMNoiseSigma; + + float sADCMean = sPix * sSiPMGainMean + _Pedestal; + float sADCSigma = std::sqrt(sPix * sSiPMGainSigma * sSiPMGainSigma + sSiPMNoiseSigma * sSiPMNoiseSigma + _PedestalNoiseSigma * _PedestalNoiseSigma); + float sADC = -1; + sADC = std::round(gRandom->Gaus(sADCMean, sADCSigma)); + if(sADC < 0) sADC = 0; + sChargeOut = sADC; + if(sADC <= _ADCSwitch) //Gain 1 + { + + float sMIP = (sADC - _Pedestal) / _SiPMGainMean / _MIPLY / fLY_tempScale; + if(sMIP < _Eth_Mip) Ehit = 0; + Ehit = sMIP * _MIPCali; + } + else if(sADC > _ADCSwitch && int(sADC/_GainRatio_12) <= _ADCSwitch) + { + //Use_G2 = kTRUE; + sSiPMGainMean = fSiPMGainMean / _GainRatio_12; + sSiPMGainSigma = sSiPMGainMean * _SiPMGainSigma; + sSiPMNoiseSigma = _SiPMNoiseSigma / _GainRatio_12; + + sADCMean = sPix * sSiPMGainMean + _Pedestal; + sADCSigma = std::sqrt(sPix * sSiPMGainSigma * sSiPMGainSigma + sSiPMNoiseSigma * sSiPMNoiseSigma + _PedestalNoiseSigma * _PedestalNoiseSigma); + sADC = std::round(gRandom->Gaus(sADCMean, sADCSigma)); + if(sADC < 0) sADC = 0; + sChargeOutHG = sADC; + + // float sCaliGainMean = gRandom->Gaus(_SiPMGainMean, fSiPMGainUn * _SiPMGainMean); + // float sMIP = (sADC - _Pedestal) / sCaliGainMean / _MIPLY; + float sMIP = (sADC - _Pedestal) / _SiPMGainMean / _MIPLY / fLY_tempScale * _GainRatio_12; + if(sMIP < _Eth_Mip) Ehit = 0; + else Ehit = sMIP * _MIPCali; + } + else if(int(sADC/_GainRatio_12) > _ADCSwitch) + { + sSiPMGainMean = fSiPMGainMean / _GainRatio_12 / _GainRatio_23; + sSiPMGainSigma = sSiPMGainMean * _SiPMGainSigma; + sSiPMNoiseSigma = _SiPMNoiseSigma / _GainRatio_12 / _GainRatio_23; + + sADCMean = sPix * sSiPMGainMean + _Pedestal; + sADCSigma = std::sqrt(sPix * sSiPMGainSigma * sSiPMGainSigma + sSiPMNoiseSigma * sSiPMNoiseSigma + _PedestalNoiseSigma * _PedestalNoiseSigma); + sADC = std::round(gRandom->Gaus(sADCMean, sADCSigma)); + if(sADC < 0) sADC = 0; + sChargeOutLG = sADC; + + // float sCaliGainMean = gRandom->Gaus(_SiPMGainMean, fSiPMGainUn * _SiPMGainMean); + // float sMIP = (sADC - _Pedestal) / sCaliGainMean / _MIPLY; + float sMIP = (sADC - _Pedestal) / _SiPMGainMean / _MIPLY / fLY_tempScale * _GainRatio_12 * _GainRatio_23; + if(sMIP < _Eth_Mip) Ehit = 0; + else Ehit = sMIP * _MIPCali; + } + + } + if(Ehit<_MIPCali*_Eth_Mip) continue; + + //Global calibration. + //TODO: add more digitization terms here. + double Ehit_cali = Ehit*r_cali; + + //Loop contributions to get hit time and MCParticle. + double Thit_ave = 0.; + double Ehit_raw = 0.; + MCParticleToEnergyWeightMap MCPEnMap; MCPEnMap.clear(); + for(int iConb=0; iConb<simhit.contributions_size(); ++iConb){ + auto conb = simhit.getContributions(iConb); + if(!conb.isAvailable()) continue; + if(conb.getEnergy()==0) continue; + + Thit_ave += conb.getTime(); + + auto mcp = conb.getParticle(); + MCPEnMap[mcp] += conb.getEnergy(); + Ehit_raw += conb.getEnergy(); + } + Thit_ave = Thit_ave/simhit.contributions_size(); + //Create DigiHit + auto digiHit = caloVec->create(); + digiHit.setCellID(id); + digiHit.setEnergy(Ehit_cali); + digiHit.setTime(Thit_ave); + digiHit.setPosition(simhit.getPosition()); + + //Create SimHit-DigiHit association. + auto rel = caloAssoVec->create(); + rel.setRec(digiHit); + rel.setSim(simhit); + rel.setWeight(1.); + + //Create DigiHit-MCParticle association. + for(auto iter : MCPEnMap){ + auto rel_MC = caloMCPAssoVec->create(); + rel_MC.setRec(digiHit); + rel_MC.setSim(iter.first); + rel_MC.setWeight(iter.second/Ehit_raw); + } + + if(_writeNtuple){ + m_totE += digiHit.getEnergy(); + m_simHit_x.push_back(digiHit.getPosition().x); + m_simHit_y.push_back(digiHit.getPosition().y); + m_simHit_z.push_back(digiHit.getPosition().z); + m_simHit_E.push_back(digiHit.getEnergy()); + m_simHit_Etruth.push_back(Ehit_truth); + m_simHit_Eatt.push_back(Npe_att); + m_simHit_rawQ.push_back(sChargeOut); + m_simHit_HG.push_back(sChargeOutHG); + m_simHit_LG.push_back(sChargeOutLG); + m_simHit_Npe_scint.push_back(Npe_scint); + m_simHit_Npe_sipm.push_back(Npe_SiPM); + m_simHit_steps.push_back(simhit.contributions_size()); + m_simHit_system.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "system")); + m_simHit_stave.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "stave")); + m_simHit_layer.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "layer")); + if(hit_system==22){ + m_simHit_tile.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "tile")); + m_simHit_idx.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "x")); + m_simHit_idy.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "y")); + m_simHit_row.push_back(-1); + m_simHit_phi.push_back(-1); + } + if(hit_system==30){ + m_simHit_tile.push_back(-1); + m_simHit_idx.push_back(-1); + m_simHit_idy.push_back(-1); + m_simHit_row.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "row")); + m_simHit_phi.push_back(map_readout_decoder[name_Readout[icol]]->get(id, "phi")); + } + m_simHit_cellID.push_back(id); + } + } + m_simhitCol.clear(); + }catch(GaudiException &e){ + info()<<"SimCaloHit collection "<<name_SimCaloHit[icol]<<" is not available "<<endmsg; } } @@ -261,7 +464,9 @@ StatusCode HcalDigiAlg::finalize() } info() << "Processed " << _nEvt << " events " << endmsg; - delete m_cellIDConverter, m_decoder, m_geosvc; + map_readout_decoder.clear(); + delete m_cellIDConverter, m_geosvc; + delete f_DarkNoise, GSTileResMap; return GaudiAlgorithm::finalize(); } @@ -317,7 +522,11 @@ edm4hep::MutableSimCalorimeterHit HcalDigiAlg::find(const std::vector<edm4hep::M } void HcalDigiAlg::Clear(){ + m_MC_EPx = 0; + m_MC_EPy = 0; + m_MC_EPz = 0; m_totE = -99; + m_totE_truth = -99; m_simHit_x.clear(); m_simHit_y.clear(); m_simHit_z.clear(); @@ -330,11 +539,17 @@ void HcalDigiAlg::Clear(){ m_simHit_Npe_scint.clear(); m_simHit_Npe_sipm.clear(); m_simHit_steps.clear(); - m_simHit_module.clear(); + m_simHit_system.clear(); m_simHit_stave.clear(); m_simHit_layer.clear(); - m_simHit_slice.clear(); - m_simHit_tower.clear(); + m_simHit_tile.clear(); + m_simHit_idx.clear(); + m_simHit_idy.clear(); + m_simHit_row.clear(); + m_simHit_phi.clear(); m_simHit_cellID.clear(); + m_step_x.clear(); + m_step_y.clear(); + m_step_LY.clear(); } diff --git a/Digitization/DigiCalo/src/HcalDigiAlg.h b/Digitization/DigiCalo/src/HcalDigiAlg.h index 5043488e..4acc9a39 100644 --- a/Digitization/DigiCalo/src/HcalDigiAlg.h +++ b/Digitization/DigiCalo/src/HcalDigiAlg.h @@ -3,6 +3,7 @@ #include "k4FWCore/DataHandle.h" #include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/MCParticleCollection.h" #include "edm4hep/MutableCaloHitContribution.h" #include "edm4hep/MutableSimCalorimeterHit.h" #include "edm4hep/SimCalorimeterHit.h" @@ -22,7 +23,9 @@ #include "TFile.h" #include "TString.h" #include "TH3.h" +#include "TH2.h" #include "TH1.h" +#include "TF1.h" #include <cstdlib> #include "time.h" @@ -67,53 +70,91 @@ protected: TRandom3 rndm; TFile* m_wfile; TTree* t_simHit; - - double m_totE; - FloatVec m_simHit_x, m_simHit_y, m_simHit_z, m_simHit_E, m_simHit_Etruth, m_simHit_Eatt, m_simHit_slice, m_simHit_layer, m_simHit_tower, m_simHit_stave, m_simHit_module, m_simHit_HG, m_simHit_LG, m_simHit_rawQ, m_simHit_Npe_scint, m_simHit_Npe_sipm; + TH2D* GSTileResMap; + + double m_totE, m_totE_truth; + double m_MC_EPx, m_MC_EPy, m_MC_EPz; + FloatVec m_simHit_x, m_simHit_y, m_simHit_z, m_simHit_E, m_simHit_Etruth, m_simHit_Eatt, + m_simHit_system, m_simHit_stave, m_simHit_layer, m_simHit_tile, m_simHit_idx, m_simHit_idy, m_simHit_row, m_simHit_phi, + m_simHit_HG, m_simHit_LG, m_simHit_rawQ, m_simHit_Npe_scint, m_simHit_Npe_sipm; + FloatVec m_step_x, m_step_y, m_step_LY; std::vector<unsigned long long> m_simHit_cellID; std::vector<int> m_simHit_steps; - + dd4hep::Detector* m_dd4hep; dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; - dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + //dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + std::map<std::string, dd4hep::DDSegmentation::BitFieldCoder*> map_readout_decoder; + + TF1* f_DarkNoise = nullptr; Gaudi::Property<float> m_scale{ this, "Scale", 1 }; // Input collections - DataHandle<edm4hep::SimCalorimeterHitCollection> r_SimCaloCol{"SimCaloCol", Gaudi::DataHandle::Reader, this}; - mutable Gaudi::Property<std::string> _readoutName{this, "ReadOutName", "CaloHitsCollection", "Readout name"}; + typedef DataHandle<edm4hep::SimCalorimeterHitCollection> SimCaloType; + typedef DataHandle<edm4hep::CalorimeterHitCollection> CaloType; + typedef DataHandle<edm4hep::MCRecoCaloAssociationCollection> CaloSimAssoType; //Calorimeter - SimCalorimeter + typedef DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection> CaloParticleAssoType; //Calorimeter - MCParticle + + Gaudi::Property< std::vector<std::string> > name_SimCaloHit{ this, "SimCaloHitCollection", {"HcalBarrelCollection"} }; + Gaudi::Property< std::vector<std::string> > name_Readout{ this, "ReadOutName", {"HcalBarrelCollection"} }; + Gaudi::Property< std::vector<std::string> > name_CaloHit{ this, "CaloHitCollection", {"HCALBarrel"} }; + Gaudi::Property< std::vector<std::string> > name_CaloAsso{ this, "CaloAssociationCollection", {"HCALBarrelAssoCol"} }; + Gaudi::Property< std::vector<std::string> > name_CaloMCPAsso{ this, "CaloMCPAssociationCollection", {"HCALBarrelParticleAssoCol"} }; + + std::vector<SimCaloType*> _inputSimHitCollection; + std::vector<CaloType*> _outputHitCollection; + std::vector<CaloSimAssoType*> _outputCaloSimAssoCol; + std::vector<CaloParticleAssoType*> _outputCaloMCPAssoCol; + + DataHandle<edm4hep::MCParticleCollection> m_MCParticleCol{"MCParticle", Gaudi::DataHandle::Reader, this}; mutable Gaudi::Property<std::string> _filename{this, "OutFileName", "testout.root", "Output file name"}; //Input parameters mutable Gaudi::Property<int> _writeNtuple{this, "WriteNtuple", 1, "Write ntuple"}; mutable Gaudi::Property<int> _Nskip{this, "SkipEvt", 0, "Skip event"}; mutable Gaudi::Property<float> _seed{this, "Seed", 2131, "Random Seed"}; - mutable Gaudi::Property<int> _Debug{this, "Debug", 0, "Debug level"}; mutable Gaudi::Property<float> r_cali{this, "CalibrHCAL", 1, "Global calibration coefficients for HCAL"}; mutable Gaudi::Property<int> _UseRelDigi{this, "UseRealisticDigi", 1, "If use the realistic model"}; //add digitization parameters from AHCAL prototype - mutable Gaudi::Property<float> _MIPCali{this, "MIPResponse", 0.000461, "MIP response (/GeV)"}; - mutable Gaudi::Property<float> _Eth_Mip{this, "MIPThreshold", 0.5, "Energy Threshold (/MIP)"}; - mutable Gaudi::Property<int> _Pixel{this, "SiPMPixel", 7284, "number of SiPM pixels"}; - mutable Gaudi::Property<float> _ADCError{this, "ADCError", 0.0002, "ADC Error (/ADC)"}; - mutable Gaudi::Property<float> _MIPADC{this, "MIPADCMean", 345.7, "Mean value of MIP response adc (/ADC)"}; - mutable Gaudi::Property<float> _TileRes{this, "TileNonUniformity", 0.05, "Non-uniformity level of one tile response"}; - mutable Gaudi::Property<float> _EffAttenLength{this, "EffAttenLength", 20., "Effictive attenuation length (mm)"}; - mutable Gaudi::Property<float> _PeADCMean{this, "PeADCMean", 30.0, "Mean value of single photons adc (/ADC)"}; - mutable Gaudi::Property<float> _PeADCSigma{this, "PeADCSigma", 3.5, "Sigma of single photons adc (/ADC)"}; - mutable Gaudi::Property<float> _BaselineHG{this, "ADCBaselineHG", 377.4, "Mean value of HG baseline adc (/ADC)"}; - mutable Gaudi::Property<float> _BaselineSigmaHG{this, "ADCBaselineSigmaHG", 3.3, "Sigma of HG baseline adc (/ADC)"}; - mutable Gaudi::Property<float> _BaselineLG{this, "ADCBaselineLG", 373.9, "Mean value of LG baseline adc (/ADC)"}; - mutable Gaudi::Property<float> _BaselineSigmaLG{this, "ADCBaselineSigmaLG", 2.2, "Sigma of LG baseline adc (/ADC)"}; - mutable Gaudi::Property<float> _HLRatio{this, "ADCHLRatio", 29.9, "The ratio of HG to LG"}; - mutable Gaudi::Property<float> _ADCSwitch{this, "ADCSwitch", 2930, "transition point from HG to LG (/ADC)"}; - mutable Gaudi::Property<float> _ADCLimit{this, "ADCLimit", 3000, "ADC saturation of LG (/ADC)"}; + //Scintillation and general + mutable Gaudi::Property<float> _MIPCali{this, "MIPResponse", 0.007126, "MIP response (/GeV)"}; + mutable Gaudi::Property<float> _MIPLY{this, "MIPLY", 80, "Detected light yield (p.e./MIP)"}; + mutable Gaudi::Property<float> _Eth_Mip{this, "MIPThreshold", 0.1, "Energy Threshold (/MIP)"}; + mutable Gaudi::Property<float> _TileRes{this, "TileNonUniformity", 0., "Non-uniformity level of one tile response"}; + + mutable Gaudi::Property<int> _UseTileLYMap{this, "UseTileLYMap", 1., "Use the tile light yield map"}; + mutable Gaudi::Property<std::string> _TileLYMapFile{this, "TileLYMapFile", "", "Use the tile light yield map"}; + mutable Gaudi::Property<std::string> _EffAttenLength{this, "EffAttenLength", "23mm", "Effictive attenuation length (mm)"}; + mutable Gaudi::Property<float> _TempCoef{this, "LYTempCoef", 0, "Temperature dependence of light yield (%/K)"}; + + //Temperature + mutable Gaudi::Property<float> _TempVariation{this, "TemperatureVariation", 1., "Temperature control variation (K)"}; + + //SiPM + mutable Gaudi::Property<int> _Pixel{this, "SiPMPixel", 57600, "number of SiPM pixels"}; + mutable Gaudi::Property<float> _SiPMDCR{this, "SiPMDCR", 1600, "SiPM Dark Count Rate (Hz)"}; + mutable Gaudi::Property<float> _SiPMXTalk{this, "SiPMCT", 0.12, "SiPM crosstalk Probability"}; + mutable Gaudi::Property<float> _TimeInterval{this, "TimeInterval", 0.000002, "Time interval for one readout (s)"}; + mutable Gaudi::Property<float> _SiPMGainTempCoef{this, "SiPMGainTempCoef", -0.03, "Temperature dependence of SiPM gain (%/K)"}; // doi:10.1016/j.nima.2016.09.053 + mutable Gaudi::Property<float> _SiPMDCRTempCoef{this, "SiPMDCRTempCoef", 3.34/80, "Temperature dependence of SiPM DCR (10^{k*deltaT})"}; // doi:10.1016/j.nima.2016.09.053 + + //ADC + mutable Gaudi::Property<int> _ADC{this, "ADC", 8192, "Total ADC conuts"}; + mutable Gaudi::Property<int> _ADCSwitch{this, "ADCSwitch", 8000, "switching point of different gain mode"}; + mutable Gaudi::Property<float> _GainRatio_12{this, "GainRatio_12", 50, "Gain-1 over Gain-2"}; + mutable Gaudi::Property<float> _GainRatio_23{this, "GainRatio_23", 60, "Gain-2 over Gain-3"}; + mutable Gaudi::Property<float> _SiPMGainMean{this, "SiPMGainMean", 2, "SiPM gain: ADC per p.e. for HG (ADC)"}; + mutable Gaudi::Property<float> _SiPMGainSigma{this, "SiPMGainSigma", 0.08, "Fluctuation of single photoelctron ADC around the mean value for single device (%)"}; + mutable Gaudi::Property<float> _SiPMNoiseSigma{this, "SiPMNoiseSigma", 0, "Sigma of SiPM noise (ADC)"}; + mutable Gaudi::Property<float> _Pedestal{this, "Pedestal", 50, "ADC value of pedestal"}; + mutable Gaudi::Property<float> _PedestalNoiseSigma{this, "PedestalSigma", 4, "Sigma of electronic noise (ADC)"}; // Output collections - DataHandle<edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; - DataHandle<edm4hep::MCRecoCaloAssociationCollection> w_CaloAssociationCol{"HCALBarrelAssoCol", Gaudi::DataHandle::Writer, this}; - DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection> w_MCPCaloAssociationCol{"HCALBarrelParticleAssoCol", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::MCRecoCaloAssociationCollection> w_CaloAssociationCol{"HCALBarrelAssoCol", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection> w_MCPCaloAssociationCol{"HCALBarrelParticleAssoCol", Gaudi::DataHandle::Writer, this}; }; #endif diff --git a/Reconstruction/RecPFACyber/CMakeLists.txt b/Reconstruction/RecPFACyber/CMakeLists.txt index 47a099e9..e448bd16 100644 --- a/Reconstruction/RecPFACyber/CMakeLists.txt +++ b/Reconstruction/RecPFACyber/CMakeLists.txt @@ -11,6 +11,7 @@ gaudi_add_library(CrystalCaloRecLib src/Objects/HoughObject.cc src/Objects/PFObject.cc LINK k4FWCore::k4FWCore + ROOT::TMVA GearSvc CrystalEcalSvcLib DetInterface @@ -21,6 +22,7 @@ gaudi_add_library(CrystalCaloRecLib ${GSL_LIBRARIES} ${LCIO_LIBRARIES} ${ROOT_LIBRARIES} + ${TMVA_LIBRARIES} EDM4HEP::edm4hep EDM4HEP::edm4hepDict ) diff --git a/Reconstruction/RecPFACyber/include/CyberPFAlg.h b/Reconstruction/RecPFACyber/include/CyberPFAlg.h index 4406f848..83f1c256 100644 --- a/Reconstruction/RecPFACyber/include/CyberPFAlg.h +++ b/Reconstruction/RecPFACyber/include/CyberPFAlg.h @@ -83,6 +83,9 @@ protected: SmartIF<IGeomSvc> m_geosvc; SmartIF<ICrystalEcalSvc> m_energycorsvc; std::map<std::string, dd4hep::DDSegmentation::BitFieldCoder*> map_readout_decoder; + dd4hep::Detector* m_dd4hep; + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + dd4hep::VolumeManager m_volumeManager; //DataCollection: moved into execute() to ensure everything can be cleand after one event. //CyberDataCol m_DataCol; @@ -138,9 +141,15 @@ protected: Gaudi::Property<int> m_Debug{this, "Debug", 0, "Debug level"}; Gaudi::Property<int> m_Nskip{this, "SkipEvt", 0, "Skip event"}; Gaudi::Property<std::string> m_EcalType{this, "EcalType", "BarEcal", "ECAL type"}; - Gaudi::Property<bool> m_useTruthTrk{this, "UseTruthTrack", 1, "Use truth track or reconstructed track"}; - Gaudi::Property<float> m_EcalCalib{this, "EcalGlobalCalib", 1.02, "ECAL global calibration"}; - Gaudi::Property<float> m_HcalCalib{this, "HcalGlobalCalib", 65., "HCAL global calibration"}; + Gaudi::Property<bool> m_useMCPTrk{this, "UseMCPTrack", 1, "Use track from MCParticle extrapolation"}; + Gaudi::Property<bool> m_useTruthMatchTrk{this, "UseTruthMatchTrack", 1, "Use track from MCParticle extrapolation"}; + Gaudi::Property<bool> m_doCleanTrack{this, "DoCleanTrack", 1, "Do clean tracks"}; + Gaudi::Property<std::string> m_trackIDFile{this, "TrackIDFile", "", "BDT weight file for track ID"}; + Gaudi::Property<std::string> m_trackIDMethod{this, "TrackIDMethod", "BDTG", "BDT weight file for track ID"}; + Gaudi::Property<float> m_EcalChargedCalib{this, "EcalChargedCalib", 1.26, "ECAL global calibration"}; + Gaudi::Property<float> m_HcalChargedCalib{this, "HcalChargedCalib", 4., "HCAL global calibration"}; + Gaudi::Property<float> m_EcalNeutralCalib{this, "EcalNeutralCalib", 1., "ECAL global calibration"}; + Gaudi::Property<float> m_HcalNeutralCalib{this, "HcalNeutralCalib", 4., "HCAL global calibration"}; //Algorithms: typedef std::vector<std::string> StringVector; @@ -176,7 +185,8 @@ protected: TTree *t_MCParticle; int m_Nmc; IntVec m_mcPdgid, m_mcStatus; - FloatVec m_mcPx, m_mcPy, m_mcPz, m_mcEn, m_mcMass, m_mcCharge, m_mcEPx, m_mcEPy, m_mcEPz, m_depEn_ecal, m_depEn_hcal; + FloatVec m_mcPx, m_mcPy, m_mcPz, m_mcEn, m_mcMass, m_mcCharge; + FloatVec m_mcVTXx, m_mcVTXy, m_mcVTXz, m_mcEPx, m_mcEPy, m_mcEPz, m_depEn_ecal, m_depEn_hcal; //Raw bars and hits TTree* t_SimBar; @@ -290,7 +300,7 @@ protected: int m_Ntrk; FloatVec m_trkstate_d0, m_trkstate_z0, m_trkstate_phi, m_trkstate_tanL, m_trkstate_omega, m_trkstate_kappa; FloatVec m_trkstate_refx, m_trkstate_refy, m_trkstate_refz; - IntVec m_trkstate_tag, m_trkstate_location, m_type; + IntVec m_trkstate_tag, m_trkstate_location, m_type, m_Nhit; FloatVec m_trkstate_x_ECAL, m_trkstate_y_ECAL, m_trkstate_z_ECAL, m_trkstate_x_HCAL, m_trkstate_y_HCAL, m_trkstate_z_HCAL; IntVec m_trkstate_tag_ECAL, m_trkstate_tag_HCAL; diff --git a/Reconstruction/RecPFACyber/include/Objects/Calo2DCluster.h b/Reconstruction/RecPFACyber/include/Objects/Calo2DCluster.h index 796bb274..e73719e1 100644 --- a/Reconstruction/RecPFACyber/include/Objects/Calo2DCluster.h +++ b/Reconstruction/RecPFACyber/include/Objects/Calo2DCluster.h @@ -10,7 +10,7 @@ namespace Cyber { class CaloHit; class Calo2DCluster { public: - Calo2DCluster() {}; + Calo2DCluster() { pos.SetXYZ(0., 0., 0.); }; ~Calo2DCluster() { Clear(); }; void Clear(); @@ -49,10 +49,13 @@ namespace Cyber { void addTowerID(int _m, int _p, int _s) { std::vector<int> id(3); id[0] = _m; id[1] = _p; id[2] = _s; towerID.push_back(id); } void addTowerID(std::vector<int> id) { towerID.push_back(id); } void setTowerID(std::vector<int> id) { towerID.clear(); towerID.push_back(id); } + void setPos( TVector3 _vec ) { pos = _vec; } + void setPos( double _x, double _y, double _z ) { pos.SetXYZ(_x, _y, _z); } private: std::vector< std::vector<int> > towerID; //[module, stave] + TVector3 pos = TVector3(0.,0.,0.); std::vector<const CaloHit*> hits; std::vector<const CaloUnit*> barUCol; //slayer == 0. std::vector<const CaloUnit*> barVCol; //slayer == 1. diff --git a/Reconstruction/RecPFACyber/include/Objects/Calo3DCluster.h b/Reconstruction/RecPFACyber/include/Objects/Calo3DCluster.h index 57483abc..98443e2b 100644 --- a/Reconstruction/RecPFACyber/include/Objects/Calo3DCluster.h +++ b/Reconstruction/RecPFACyber/include/Objects/Calo3DCluster.h @@ -56,6 +56,7 @@ namespace Cyber { int getEndDlayer() const; double getDepthToECALSurface() const; int getType() const { return type; } + double getEnergyScale() const { return Escale; } void setCaloHits( std::vector<const Cyber::CaloHit*> _hits ) { hits = _hits; } void setCaloHitsFrom2DCluster(); @@ -69,6 +70,7 @@ namespace Cyber { { map_localMaxU[name1]=_colU; map_localMaxV[name2]=_colV; } void setClusters(std::vector<const Calo2DCluster*> _2dcol) { m_2dclusters = _2dcol; } void setType(int _type) { type = _type; } + void setEnergyScale(double _scale) { Escale = _scale; } void addTowerID(int _m, int _p, int _s) { std::vector<int> id(3); id[0] = _m; id[1] = _p; id[2] = _s; towerID.push_back(id); } void addTowerID( std::vector<int> id ) { towerID.push_back(id); } @@ -103,6 +105,7 @@ namespace Cyber { std::vector< std::pair<edm4hep::MCParticle, float> > MCParticleWeight; std::vector< std::vector<int> > towerID; //[module, part, stave] + double Escale = 1.; TVector3 axis; double chi2; double alpha; diff --git a/Reconstruction/RecPFACyber/include/Objects/CaloUnit.h b/Reconstruction/RecPFACyber/include/Objects/CaloUnit.h index 0ed6d775..0530e65a 100644 --- a/Reconstruction/RecPFACyber/include/Objects/CaloUnit.h +++ b/Reconstruction/RecPFACyber/include/Objects/CaloUnit.h @@ -62,7 +62,7 @@ namespace Cyber{ void addLinkedMCP( std::pair<edm4hep::MCParticle, float> _pair ) { MCParticleWeight.push_back(_pair); } void setLinkedMCP( std::vector<std::pair<edm4hep::MCParticle, float>> _pairVec ) { MCParticleWeight.clear(); MCParticleWeight = _pairVec; } void setcellID(unsigned long long _cellid) { cellID = _cellid; } - void setcellID(int _system, int _module, int _stave, int _dlayer, int _slayer, int _bar) { system=_system; module=_module; stave=_stave; dlayer=_dlayer; slayer=_slayer; bar=_bar; } + void setcellID(int _system, int _module, int _stave, int _part, int _dlayer, int _slayer, int _bar) { system=_system; module=_module; stave=_stave; part=_part; dlayer=_dlayer; slayer=_slayer; bar=_bar; } void setPosition( TVector3 posv3) { position.SetXYZ( posv3.x(), posv3.y(), posv3.z() ); } void setQ(double _q1, double _q2) { Q1=_q1; Q2=_q2; } void setT(double _t1, double _t2) { T1=_t1; T2=_t2; } @@ -82,6 +82,7 @@ namespace Cyber{ unsigned long long cellID; int system; int module; + int part; int stave; int dlayer; int slayer; diff --git a/Reconstruction/RecPFACyber/include/Objects/HoughObject.h b/Reconstruction/RecPFACyber/include/Objects/HoughObject.h index dba958db..ea56a814 100644 --- a/Reconstruction/RecPFACyber/include/Objects/HoughObject.h +++ b/Reconstruction/RecPFACyber/include/Objects/HoughObject.h @@ -16,8 +16,8 @@ namespace Cyber { TVector2 getCenterPoint() const { return m_center_point; } - TVector2 getUpperPoint() const { return m_center_point + TVector2( m_cell_size*cos(m_center_point.Phi() + TMath::PiOver2()), m_cell_size*sin(m_center_point.Phi() + TMath::PiOver2()) ); } - TVector2 getLowerPoint() const { return m_center_point + TVector2( m_cell_size*cos(m_center_point.Phi() + 3*TMath::PiOver2()), m_cell_size*sin(m_center_point.Phi() + 3*TMath::PiOver2()) ); } + TVector2 getUpperPoint() const { return m_center_point + TVector2( 0.7*m_cell_size*cos(m_center_point.Phi() + TMath::PiOver2()), 0.7*m_cell_size*sin(m_center_point.Phi() + TMath::PiOver2()) ); } + TVector2 getLowerPoint() const { return m_center_point + TVector2( 0.7*m_cell_size*cos(m_center_point.Phi() + 3*TMath::PiOver2()), 0.7*m_cell_size*sin(m_center_point.Phi() + 3*TMath::PiOver2()) ); } //TVector2 getPointU() const { return m_center_point + TVector2(0, m_cell_size/TMath::Sqrt(2)); } //TVector2 getPointD() const { return m_center_point + TVector2(0, -m_cell_size/TMath::Sqrt(2)); } //TVector2 getPointL() const { return m_center_point + TVector2(-m_cell_size/TMath::Sqrt(2), 0); } diff --git a/Reconstruction/RecPFACyber/include/Tools/CaloHitsCreator.h b/Reconstruction/RecPFACyber/include/Tools/CaloHitsCreator.h index 6069aa5c..ea07735f 100644 --- a/Reconstruction/RecPFACyber/include/Tools/CaloHitsCreator.h +++ b/Reconstruction/RecPFACyber/include/Tools/CaloHitsCreator.h @@ -20,7 +20,8 @@ namespace Cyber{ StatusCode CreateCaloHits( CyberDataCol& m_DataCol, std::vector<DataHandle<edm4hep::CalorimeterHitCollection>*>& r_CaloHitCols, std::map<std::string, dd4hep::DDSegmentation::BitFieldCoder*>& map_decoder, - std::map<std::string, DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection>*>& map_CaloParticleAssoCol ); + std::map<std::string, DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection>*>& map_CaloParticleAssoCol, + const dd4hep::VolumeManager& m_volumeManager ); //StatusCode CreateMCParticleCaloHitsAsso( std::vector<DataHandle<edm4hep::CalorimeterHitCollection>*>& r_CaloHitCols, // DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection>* r_MCParticleRecoCaloCol ); diff --git a/Reconstruction/RecPFACyber/include/Tools/TrackCreator.h b/Reconstruction/RecPFACyber/include/Tools/TrackCreator.h index 16c48c81..b4f46841 100644 --- a/Reconstruction/RecPFACyber/include/Tools/TrackCreator.h +++ b/Reconstruction/RecPFACyber/include/Tools/TrackCreator.h @@ -6,6 +6,11 @@ #include "Algorithm/TrackExtrapolatingAlg.h" #include "TVector3.h" +#include "TMVA/Tools.h" +#include "TMVA/Reader.h" + +#include <fstream> + namespace Cyber{ class TrackCreator{ @@ -40,6 +45,8 @@ namespace Cyber{ return trk1->getMomentum() > trk2->getMomentum(); } + TMVA::Reader *mva_rdr = new TMVA::Reader("Silent"); + }; }; #endif diff --git a/Reconstruction/RecPFACyber/script/ana.py b/Reconstruction/RecPFACyber/script/ana.py new file mode 100644 index 00000000..e5706e97 --- /dev/null +++ b/Reconstruction/RecPFACyber/script/ana.py @@ -0,0 +1,43 @@ +import os, sys +from Gaudi.Configuration import * + +########### k4DataSvc #################### +from Configurables import k4DataSvc +podioevent = k4DataSvc("EventDataSvc", input="Rec_TDR_o1_v01.root") +########################################## + +########## CEPCSWData ################# +cepcswdatatop ="/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/data/latest" +####################################### + + +########## Podio Input ################### +from Configurables import PodioInput +inp = PodioInput("InputReader") +inp.collections = [ "CyberPFO", "MCParticle" ] +########################################## + + + +from Configurables import GenMatch +genmatch = GenMatch("GenMatch") +genmatch.nJets = 2 +genmatch.R = 0.6 +genmatch.OutputFile = "Jets_TDR_o1_v01.root" +#genmatch.OutputFile = "./FullSim_samples/RecJets_TDR_o1_v01_E240_nnh_gg_CalHits.root" + +############################################################################## +# POD I/O +############################################################################## + + +######################################## + +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg=[inp, genmatch ], + EvtSel="NONE", + EvtMax=10, + ExtSvc=[podioevent], + #OutputLevel=DEBUG +) diff --git a/Reconstruction/RecPFACyber/script/digi.py b/Reconstruction/RecPFACyber/script/digi.py index c3ea459f..c8ab8e68 100644 --- a/Reconstruction/RecPFACyber/script/digi.py +++ b/Reconstruction/RecPFACyber/script/digi.py @@ -49,9 +49,13 @@ podioinput = PodioInput("PodioReader", collections=[ # "EventHeader", "MCParticle", "EcalBarrelCollection", - "EcalBarrelContributionCollection", + "EcalBarrelContributionCollection", + "EcalEndcapsCollection", + "EcalEndcapsContributionCollection", "HcalBarrelCollection", "HcalBarrelContributionCollection", + "HcalEndcapsCollection", + "HcalEndcapsContributionCollection" ]) ########## Digitalization ################ @@ -59,55 +63,90 @@ podioinput = PodioInput("PodioReader", collections=[ ##ECAL## from Configurables import EcalDigiAlg EcalDigi = EcalDigiAlg("EcalDigiAlg") -EcalDigi.ReadOutName = "EcalBarrelCollection" -EcalDigi.SimCaloHitCollection = "EcalBarrelCollection" -EcalDigi.CaloHitCollection = "ECALBarrel" -EcalDigi.CaloAssociationCollection = "ECALBarrelAssoCol" -EcalDigi.CaloMCPAssociationCollection = "ECALBarrelParticleAssoCol" +EcalDigi.SimCaloHitCollection = ["EcalBarrelCollection", "EcalEndcapsCollection"] +EcalDigi.ReadOutName = ["EcalBarrelCollection", "EcalEndcapsCollection"] +EcalDigi.CaloHitCollection = ["ECALBarrel", "ECALEndcaps"] +EcalDigi.CaloAssociationCollection = ["ECALBarrelAssoCol", "ECALEndcapsAssoCol"] +EcalDigi.CaloMCPAssociationCollection = ["ECALBarrelParticleAssoCol", "ECALEndcapsParticleAssoCol"] EcalDigi.SkipEvt = 0 EcalDigi.Seed = 2079 #Digitalization parameters -EcalDigi.CalibrECAL = 1. -EcalDigi.AttenuationLength = 7e10 -EcalDigi.TimeResolution = 0.5 #unit: ns -EcalDigi.ChargeThresholdFrac = 0.05 -EcalDigi.EcalMIP_Thre = 0.05 -EcalDigi.Debug=1 -EcalDigi.WriteNtuple = 0 -EcalDigi.OutFileName = "Digi_ECAL.root" +EcalDigi.TimeResolution = 0.7 # 0.7 ns +EcalDigi.EcalMIPEnergy = 8.9 # MIP energy 8.9 MeV for 1 cm BGO +EcalDigi.EcalMIP_Thre = 0.05 # 0.05 mip at each side, 0.1 mip for one bar +EcalDigi.UseRealisticDigi = 1 +# scintillation +EcalDigi.UseDigiScint = 1 +EcalDigi.EcalCryIntLY = 8200 #intrinsic LY 8200 [p.e./MIP] +EcalDigi.EcalCryMipLY = 200 #Detected effective LY 200 [p.e./MIP] +EcalDigi.AttenuationLength = 1e8 # 8000 mm for 5% non-uniformity +# SiPM +EcalDigi.SiPMDigiVerbose = 2 # 0:w/o response, w/o correction; 1:w/ response, w/o correction; 2:w/ response, w/ simple correction; 3:w/ response, w/ full correction +EcalDigi.EcalSiPMPDE = 0.25 # NDL-EQR06, PDE 0.25 +EcalDigi.EcalSiPMDCR = 0 # NDL-EQR06, dark count rate 2500000 [Hz] +EcalDigi.EcalTimeInterval = 0. # Time interval 0.000002 [s]. DCR*TimeInterval = dark count noise +EcalDigi.EcalSiPMCT = 0. # SiPM crosstalk Probability 12% +EcalDigi.EcalSiPMGainMean = 50 # 50 [ADC/p.e.] +EcalDigi.EcalSiPMGainSigma = 0.08 # 0.08 +#EcalDigi.EcalSiPMNoiseSigma = 0 # 0 +# ADC +EcalDigi.ADC = 8192 # 13-bit, 8192 +EcalDigi.ADCSwitch = 8000 # 8000 +EcalDigi.Pedestal = 50 # Pedestal 50 ADC +EcalDigi.GainRatio_12 = 50 # Gain ratio 50 +EcalDigi.GainRatio_23 = 60 # Gain ratio 60 +#EcalDigi.EcalNoiseADCSigma = 4 # 4 +# temperature control +EcalDigi.UseCryTemp = 0 +EcalDigi.UseCryTempCor = 0 +EcalDigi.UseSiPMTemp = 0 +EcalDigi.UseSiPMTempCor = 0 +EcalDigi.EcalTempGrad = 3./27 # 3./27 = 3K from 0 to 27 layer +EcalDigi.EcalBGOTempCoef = -0.0138 # -0.0138 [%/K] +EcalDigi.EcalSiPMGainTempCoef = -0.03 # -0.03 [%/K] +EcalDigi.EcalSiPMDCRTempCoef = 3.34/80 # 3.34/80 [10^{k*deltaT}] ######################################### +EcalDigi.WriteNtuple = 0 ##HCAL## from Configurables import HcalDigiAlg HcalDigi = HcalDigiAlg("HcalDigiAlg") -HcalDigi.ReadOutName = "HcalBarrelCollection" -HcalDigi.SimCaloHitCollection = "HcalBarrelCollection" -HcalDigi.CaloHitCollection = "HCALBarrel" -HcalDigi.CaloAssociationCollection = "HCALBarrelAssoCol" -HcalDigi.CaloMCPAssociationCollection = "HCALBarrelParticleAssoCol" +HcalDigi.SimCaloHitCollection = ["HcalBarrelCollection", "HcalEndcapsCollection"] +HcalDigi.ReadOutName = ["HcalBarrelCollection", "HcalEndcapsCollection"] +HcalDigi.CaloHitCollection = ["HCALBarrel", "HCALEndcaps"] +HcalDigi.CaloAssociationCollection = ["HCALBarrelAssoCol", "HCALEndcapsAssoCol"] +HcalDigi.CaloMCPAssociationCollection = ["HCALBarrelParticleAssoCol", "HCALEndcapsParticleAssoCol"] HcalDigi.SkipEvt = 0 HcalDigi.Seed = 2079 -#Digitalization parameters -HcalDigi.MIPResponse = 0.007126 # MeV / MIP -HcalDigi.MIPThreshold = 0.1 # Unit: MIP HcalDigi.CalibrHCAL = 1. -HcalDigi.UseRealisticDigi = 1 # Flag to use digitization model. -HcalDigi.SiPMPixel = 57600 # 57600 for 6025PE (6*6 mm, 25 um pixel pitch) +#Digitalization parameters +HcalDigi.UseRealisticDigi = 0 #---------Flag to use digitization model. +HcalDigi.MIPResponse = 0.007126 # 0.007.126 GeV / MIP +HcalDigi.MIPThreshold = 0.1 # ----------Unit: MIP +HcalDigi.TemperatureVariation = 0 # Temperature variation 1K +# Scintillation +HcalDigi.UseTileLYMap = 0 +HcalDigi.MIPLY = 80 # Glass LY +HcalDigi.LYTempCoef = 0 # Glass LY with temperature HcalDigi.TileNonUniformity = 0.0 -HcalDigi.EffAttenLength = 1e7 -HcalDigi.ADCError = 0.0 -HcalDigi.MIPADCMean = 80.*30.0 # Light yield 80 pe/mip -HcalDigi.PeADCMean = 30.0 -HcalDigi.PeADCSigma = 0. -HcalDigi.ADCBaselineHG = 0 -HcalDigi.ADCBaselineSigmaHG = 0. -HcalDigi.ADCBaselineLG = 0 -HcalDigi.ADCBaselineSigmaLG = 0. -HcalDigi.ADCHLRatio = 1 -HcalDigi.ADCSwitch = 1e7 -HcalDigi.ADCLimit = 1e7 +# SiPM +HcalDigi.SiPMPixel = 57600 #---------57600 for 6025PE (6*6 mm, 25 um pixel pitch) +HcalDigi.SiPMDCR = 1600 #---------1600 for 6025PE (6*6 mm, 25 um pixel pitch), 3200 for 6015PS () +HcalDigi.SiPMCT = 0.0 #---------SiPM crosstalk Probability 0.12 +HcalDigi.TimeInterval = 0. #---------Shaping time 2 us +HcalDigi.SiPMGainTempCoef = 0 #---------Temperature dependence of SiPM gain (-3%/K) +HcalDigi.SiPMDCRTempCoef = 0 #---------Temperature dependence of SiPM DCR (10^{k*deltaT}, k=3.34/80) +# ADC +HcalDigi.ADC = 8192 +HcalDigi.ADCSwitch = 1e7 # Switch at 8000 +HcalDigi.GainRatio_12 = 50 +HcalDigi.GainRatio_23 = 60 +HcalDigi.SiPMGainMean = 20 # SiPM gain: 2 ADC / p.e. +HcalDigi.SiPMGainSigma = 0.08 # Fluctuation of ADC / p.e. +HcalDigi.SiPMNoiseSigma = 0 # SiPM noise sigma +HcalDigi.Pedestal = 50 # Pedestal 50 ADC +HcalDigi.PedestalSigma = 4 # Sigma of electronic noise (4 ADC) HcalDigi.WriteNtuple = 0 -HcalDigi.OutFileName = "Digi_HCAL.root" # output @@ -121,10 +160,16 @@ out.outputCommands = ["drop *", "keep TPCCollection", "keep OTKBarrelCollection", "keep FTDCollection", + "keep MuonBarrelCollection", + "keep MuonEndcapCollection", "keep ECALBarrel", "keep HCALBarrel", "keep ECALBarrelParticleAssoCol", - "keep HCALBarrelParticleAssoCol" ] + "keep HCALBarrelParticleAssoCol", + "keep ECALEndcaps", + "keep HCALEndcaps", + "keep ECALEndcapsParticleAssoCol", + "keep HCALEndcapsParticleAssoCol" ] # ApplicationMgr diff --git a/Reconstruction/RecPFACyber/script/rec.py b/Reconstruction/RecPFACyber/script/rec.py index e844f945..e61b0843 100644 --- a/Reconstruction/RecPFACyber/script/rec.py +++ b/Reconstruction/RecPFACyber/script/rec.py @@ -36,10 +36,15 @@ crystalecalcorr.CorrectionFile = os.path.join(cepcswdatatop, "CEPCSWData/offline ########## Podio Input ################### from Configurables import PodioInput inp = PodioInput("InputReader") -inp.collections = [ "ECALBarrel", +inp.collections = [ + "ECALBarrel", "ECALBarrelParticleAssoCol", +# "ECALEndcaps", +# "ECALEndcapsParticleAssoCol", "HCALBarrel", "HCALBarrelParticleAssoCol", +# "HCALEndcaps", +# "HCALEndcapsParticleAssoCol", "MCParticle", "CompleteTracks", "CompleteTracksParticleAssociation"] @@ -54,14 +59,26 @@ CyberPFAlg.BField = 3. CyberPFAlg.Debug = 0 CyberPFAlg.SkipEvt = 0 CyberPFAlg.WriteAna = 1 -CyberPFAlg.AnaFileName = "RecAnaTuple_TDR_o1_v01_mu.root" -CyberPFAlg.UseTruthTrack = 0 -CyberPFAlg.EcalGlobalCalib = 1.05 -CyberPFAlg.HcalGlobalCalib = 4.5 +CyberPFAlg.AnaFileName = "RecAnaTuple_TDR_o1_v01.root" +CyberPFAlg.UseMCPTrack = 0 +CyberPFAlg.UseTruthMatchTrack = 0 +CyberPFAlg.DoCleanTrack = 1 +CyberPFAlg.TrackIDFile = "/cvmfs/cepcsw.ihep.ac.cn/prototype/releases/data/latest/CEPCSWData/offline-data/Reconstruction/CyberPFA_trackID/TrkID_BDT_BDTG.weights.xml" +CyberPFAlg.TrackIDMethod = "BDTG" +CyberPFAlg.EcalChargedCalib = 1.26 +CyberPFAlg.HcalChargedCalib = 4.0 +CyberPFAlg.EcalNeutralCalib = 1.0 +CyberPFAlg.HcalNeutralCalib = 4.0 ##----Readin collections---- CyberPFAlg.MCParticleCollection = "MCParticle" CyberPFAlg.TrackCollections = ["CompleteTracks"] CyberPFAlg.MCRecoTrackParticleAssociationCollection = "CompleteTracksParticleAssociation" +#CyberPFAlg.ECalCaloHitCollections = ["ECALBarrel","ECALEndcaps"] +#CyberPFAlg.ECalReadOutNames = ["EcalBarrelCollection","EcalEndcapsCollection"] +#CyberPFAlg.ECalMCPAssociationName = ["ECALBarrelParticleAssoCol", "ECALEndcapsParticleAssoCol"] +#CyberPFAlg.HCalCaloHitCollections = ["HCALBarrel", "HCALEndcaps"] +#CyberPFAlg.HCalReadOutNames = ["HcalBarrelCollection", "HcalEndcapsCollection"] +#CyberPFAlg.HCalMCPAssociationName = ["HCALBarrelParticleAssoCol", "HCALEndcapsParticleAssoCol"] CyberPFAlg.ECalCaloHitCollections = ["ECALBarrel"] CyberPFAlg.ECalReadOutNames = ["EcalBarrelCollection"] CyberPFAlg.ECalMCPAssociationName = ["ECALBarrelParticleAssoCol"] @@ -97,7 +114,7 @@ CyberPFAlg.AlgParNames = [ ["InputECALBars","OutputECAL1DClusters","OutputECALHa ["InputHCALHits", "OutputHCALClusters"], #12 ["DoECALClustering","DoHCALClustering","InputHCALHits","OutputHCALClusters"], #15 ["ReadinECALClusterName", "ReadinHCALClusterName", "OutputCombPFO"], #16 - ["ECALCalib", "HCALCalib", "MinAngleForNeuMerge"] ]#17 + ["ECALChargedCalib", "HCALChargedCalib", "ECALNeutralCalib", "HCALNeutralCalib"] ]#17 CyberPFAlg.AlgParTypes = [ ["string","string","string"],#1 ["string"],#2 ["string","string"],#3 @@ -109,7 +126,7 @@ CyberPFAlg.AlgParTypes = [ ["string","string","string"],#1 ["string", "string"], #12 ["bool","bool","string","string"], #15 ["string","string","string"], #16 - ["double","double","double"] ]#17 + ["double","double", "double","double"] ]#17 CyberPFAlg.AlgParValues = [ ["BarCol","Cluster1DCol","HalfClusterCol"],#1 ["AllLocalMax"],#2 ["AllLocalMax","TrackAxis"],#3 @@ -121,7 +138,7 @@ CyberPFAlg.AlgParValues = [ ["BarCol","Cluster1DCol","HalfClusterCol"],#1 ["HCALBarrel", "SimpleHCALCluster"], #12 ["0","1","HCALBarrel","HCALCluster"], #15 ["EcalCluster", "SimpleHCALCluster", "outputPFO"], #16 - ["1.05","4.5","0.12"] ]#17 + ["1.26","4.", "1.", "4."] ]#17 ############################################################################## diff --git a/Reconstruction/RecPFACyber/script/roofit_jets.cpp b/Reconstruction/RecPFACyber/script/roofit_jets.cpp new file mode 100644 index 00000000..43d53ffc --- /dev/null +++ b/Reconstruction/RecPFACyber/script/roofit_jets.cpp @@ -0,0 +1,229 @@ +#include <algorithm> +#include <iomanip> +#include <iostream> +#include <TFile.h> +#include <TCanvas.h> +#include <TH1F.h> +#include <TF1.h> +#include <TRandom3.h> +#include <RooRealVar.h> +#include <RooGaussian.h> +#include <RooDataHist.h> +#include <RooFitResult.h> +#include <RooPlot.h> +#include "/afs/ihep.ac.cn/users/g/guofy/RootUtils/AtlasStyle.C" +#include "/afs/ihep.ac.cn/users/g/guofy/RootUtils/AtlasUtils.C" +#include "/afs/ihep.ac.cn/users/g/guofy/RootUtils/AtlasLabels.C" +#include "/afs/ihep.ac.cn/users/g/guofy/HggTwoSidedCBPdf.cxx" +#include "/afs/ihep.ac.cn/users/g/guofy/HggTwoSidedCBPdf.h" + +using namespace std; +using namespace RooFit; + +vector<double> get_rms90(vector<double> data); + +vector<double> roofit_jets(){ + SetAtlasStyle(); + //gStyle->SetLegendTextSize(0.04); + gStyle->SetLegendFont(42); + gStyle->SetErrorX(0.5); + gStyle->SetOptStat(0); + gStyle->SetLabelSize(0.05); + + + // Read data from txt file + double m_jj, jet1_costheta, jet2_costheta, invPt, barrelRatio; + std::vector<double> event; + std::vector<double> inv_mass; + std::vector<double> mc_chargeE; + std::vector<double> mc_neuhadE; + std::vector<double> rec_trackE; + + // std::ifstream file("out/invmass_fullrec_ecal1.1_hcal70.txt"); + // std::ifstream file("out/invmass_MCtrk_recHCAL_ecal1.1_hcal70.txt"); + // std::ifstream file("scan_calibration/out/invmass_ECALCali1.100_HCALCali70.0.txt"); + +/* std::ifstream file("output.txt"); + if(file.is_open()) + { + // double ll_event, ll_invmass, ll_chargeE, ll_neuhadE, ll_rectrack, ll_EECAL, ll_EHCAL; + // while (file >> ll_event >> ll_invmass ) + // { // é€è¡Œè¯»å–文件ä¸çš„æ•°æ® + // // double dE = ll_chargeE - ll_rectrack; + // // if( (dE<-5) || (dE>5) ) continue; + // event.push_back(ll_event); + // inv_mass.push_back(ll_invmass); // å°†æ¯ä¸ªæ•°æ·»åŠ åˆ°vectorä¸ + // // mc_chargeE.push_back(ll_chargeE); + // // mc_neuhadE.push_back(ll_neuhadE); + // // rec_trackE.push_back(ll_rectrack); + // } + // file.close(); // 关闿–‡ä»¶ + double ll_invmass; + while (file >> ll_invmass ) + { // é€è¡Œè¯»å–文件ä¸çš„æ•°æ® + inv_mass.push_back(ll_invmass); // å°†æ¯ä¸ªæ•°æ·»åŠ åˆ°vectorä¸ + } + file.close(); // 关闿–‡ä»¶ + } +*/ + TFile* rfile = new TFile("jet_all.root","read"); + TTree* rtree = (TTree*)rfile->Get("jets"); + rtree->SetBranchAddress("mass_allParticles", &m_jj); + rtree->SetBranchAddress("GEN_jet1_costheta", &jet1_costheta); + rtree->SetBranchAddress("GEN_jet2_costheta", &jet2_costheta); + rtree->SetBranchAddress("GEN_inv_pt", &invPt); + rtree->SetBranchAddress("barrelRatio", &barrelRatio); + + for(int ievt=0; ievt<rtree->GetEntries(); ievt++){ + //if(ievt>10000) continue; + rtree->GetEntry(ievt); + //if(fabs(jet1_costheta)>0.6 || fabs(jet2_costheta)>0.6 || invPt>1) continue; + if(barrelRatio<0.95) continue; + inv_mass.push_back(m_jj); + } + + // 创建RooFitå˜é‡ + // RooRealVar x("x", "Invariant mass / GeV", 90, 150); + RooRealVar x("x", "Invariant mass / GeV", 80, 180); + // 创建空的RooDataSet + RooDataSet data("data", "data", RooArgSet(x)); + for(int i=0; i<inv_mass.size();i++){ + if(inv_mass[i]<80) continue; + x.setVal(inv_mass[i]); + data.add(RooArgSet(x)); + } + data.Print(); + + // RooRealVar rf_x("x", "x", 90, 150); + RooRealVar rf_mean("mean", "mean of gaussian", 123, 115, 135); + RooRealVar rf_sigma("sigma", "width of gaussian", 5, 3, 12); + + TCanvas *c2 = new TCanvas("c2", "c2", 800, 600); + c2->cd(); + //RooGaussian rf_gauss("gauss", "gaussian PDF", x, rf_mean, rf_sigma); + //vector<double> rms90_range = get_rms90(inv_mass); + //cout << "yyy: " << rms90_range[0] << " " << rms90_range[1] << endl; + //x.setRange("rms90", rms90_range[0], rms90_range[1]); + ////x.setRange(110, 140); + //rf_gauss.fitTo(data, Range("rms90")); + + + + RooRealVar alphaLo("alphaLo","alphaLo",0,5); + RooRealVar nLo("nLo","nLo",0,200); + RooRealVar alphaHi("alphaHi","alphaHi",0,5); + RooRealVar nHi("nHi","nHi",0,150); + + RooAbsPdf* rf_dscb = new HggTwoSidedCBPdf("rf_dscb", "rf_dscb", x, rf_mean, rf_sigma, alphaLo, nLo, alphaHi, nHi); + rf_dscb->fitTo(data); + RooPlot* xframe = x.frame(); + data.plotOn(xframe, Name("gr_data"), DataError(RooAbsData::SumW2), Binning(50), Invisible()); + //rf_gauss.plotOn(xframe, Name("rf_gauss"), LineColor(2), LineWidth(2)); + rf_dscb->plotOn(xframe, Name("rf_dscb"), LineColor(2), LineWidth(2)); + //rf_dscb->paramOn(xframe); + + + //xframe->GetYaxis()->SetRangeUser(0, 390); + xframe->GetYaxis()->SetTitle("Events / GeV"); + xframe->GetXaxis()->SetTitleSize(0.06); + xframe->GetYaxis()->SetTitleSize(0.06); + xframe->GetXaxis()->CenterTitle(); + xframe->GetYaxis()->CenterTitle(); + xframe->GetXaxis()->SetLabelSize(0.05); + xframe->GetYaxis()->SetLabelSize(0.05); + xframe->Draw(); + + + TGraphAsymmErrors* gr1 = (TGraphAsymmErrors*)(xframe->getObject(0)); + TGraphAsymmErrors* gr2 = new TGraphAsymmErrors(); + gr2->SetName("gr_data"); + for(int i=0; i<gr1->GetN(); i++){ + if(gr1->GetPointY(i)==0) continue; + else{ + gr2->SetPoint(i, gr1->GetPointX(i), gr1->GetPointY(i)); + gr2->SetPointError(i, 0, 0, sqrt(gr1->GetPointY(i)), sqrt(gr1->GetPointY(i))); + } + } + + gr2->GetXaxis()->SetRangeUser(100, 160); + gr2->GetYaxis()->SetRangeUser(0, 260); + gr2->GetXaxis()->SetTitle("m_{jj} [GeV]"); + gr2->GetYaxis()->SetTitle("Events / GeV"); + gr2->Draw("P same"); + + //xframe->getObject(1)->Print(); + + //TF1* func = (TF1*)xframe->getObject(1); + //func->Print(); + //func->SetName("rf_dscb"); + //func->SetLineStyle(1); + //func->SetLineWidth(2); + //func->GetXaxis()->SetRangeUser(105,160); + //func->GetYaxis()->SetRangeUser(0, 4400); + //func->Draw("C same"); + + TLegend* l1 = new TLegend(0.23, 0.65, 0.50, 0.9); + l1->SetBorderSize(0); + l1->AddEntry("gr_data", "Rec. events", "PE" ); + l1->AddEntry("rf_dscb", "H #rightarrow jj, DSCB fit", "L"); + //l1->AddEntry("rf_gauss", "H #rightarrow jj, DSCB fit", "L"); + l1->Draw(); + + //TLatex text_CEPC; + //text_CEPC.SetNDC(); + //text_CEPC.SetTextSize(0.050); + //text_CEPC.SetTextFont(22); + //text_CEPC.DrawLatex(0.2, 0.8, "CEPC Simulation"); + + //text_CEPC.SetTextFont(62); + //text_CEPC.SetTextSize(0.04); + //text_CEPC.DrawLatex(0.2, 0.75, "e^{+}e^{-} #rightarrow ZH, H #rightarrow #gamma#gamma"); + //text_CEPC.DrawLatex(0.2, 0.7, "#sqrt{s} = 240 GeV"); + + // èŽ·å–æ‹Ÿåˆå‚数的值和误差 + double fittedMean = rf_mean.getVal(); + double fittedMeanError = rf_mean.getError(); + double fittedSigma = rf_sigma.getVal(); + double fittedSigmaError = rf_sigma.getError(); + double BMR_fit = fittedSigma / fittedMean; + double BMR_error = BMR_error = BMR_fit * + sqrt( (fittedMeanError / fittedMean)*(fittedMeanError / fittedMean) + + (fittedSigmaError / fittedSigma)*(fittedSigmaError / fittedSigma) ); + + // æ‰“å°æ‹Ÿåˆç»“æžœ + // data.Print(); + std::cout << "Fitted mean: " << fittedMean << " +/- " << fittedMeanError << std::endl; + std::cout << "Fitted sigma: " << fittedSigma << " +/- " << fittedSigmaError << std::endl; + cout << "BMR = " << BMR_fit*100. << " +/- " << BMR_error*100. << " %" << endl; + + vector<double> output; + output.push_back(BMR_fit*100.); + output.push_back(BMR_error*100.); + + return output; +} + + +vector<double> get_rms90(vector<double> data){ + std::sort(data.begin(), data.end()); + int num_data = data.size(); + int num_data90 = num_data*0.90; + int num_data10 = num_data*0.10; + + double lower_range = 0; + double upper_range = 0; + double range = 10000.0; + for(int i=0; i<num_data10-3; i++){ + double temp_lower_range = data[i]; + double temp_upper_range = data[i+num_data90]; + double temp_range = temp_upper_range - temp_lower_range; + if (temp_range < range){ + range = temp_range; + lower_range = temp_lower_range; + upper_range = temp_upper_range; + } + } + + vector<double> aa{lower_range, upper_range}; + return aa; +} diff --git a/Reconstruction/RecPFACyber/script/sim.py b/Reconstruction/RecPFACyber/script/sim.py index a8b14c52..2b10df3f 100644 --- a/Reconstruction/RecPFACyber/script/sim.py +++ b/Reconstruction/RecPFACyber/script/sim.py @@ -6,7 +6,7 @@ from Configurables import k4DataSvc dsvc = k4DataSvc("EventDataSvc") from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_ -seed = [12340] +seed = [1024] # rndmengine = HepRndm__Engine_CLHEP__RanluxEngine_() # The default engine in Gaudi rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_("RndmGenSvc.Engine") # The default engine in Geant4 rndmengine.SetSingleton = True @@ -57,7 +57,6 @@ from Configurables import GenPrinter stdheprdr = StdHepRdr("StdHepRdr") stdheprdr.Input = "/cefs/data/stdhep/CEPC240/higgs/update_from_LiangHao_1M/data/E240.Pnnh_gg.e0.p0.whizard195/nnh_gg.e0.p0.00001.stdhep" - genalg = GenAlgo("GenAlgo") #genalg.GenTools = ["GtGunTool"] genalg.GenTools = ["StdHepRdr"] @@ -90,9 +89,9 @@ tpc_sensdettool.TypeOption = 1 from Configurables import CalorimeterSensDetTool from Configurables import DriftChamberSensDetTool cal_sensdettool = CalorimeterSensDetTool("CalorimeterSensDetTool") -cal_sensdettool.CalNamesMergeDisable = ["EcalBarrel", "CaloDetectorEndcap", "HcalBarrel", "HcalEndcaps"] -#cal_sensdettool.CalNamesApplyBirks = ["EcalBarrel", "CaloDetectorEndcap", "HcalBarrel","HcalEndcaps"] -#cal_sensdettool.CalNamesBirksConstants = [0.008415, 0.008415, 0.01, 0.01] # BGO and Glass scintillator +cal_sensdettool.CalNamesMergeDisable = ["EcalBarrel", "EcalEndcap", "HcalBarrel", "HcalEndcaps"] +cal_sensdettool.CalNamesApplyBirks = ["EcalBarrel", "EcalEndcap", "HcalBarrel","HcalEndcaps"] +cal_sensdettool.CalNamesBirksConstants = [0.008415, 0.008415, 0.01, 0.01] # BGO and Glass scintillator # output from Configurables import PodioOutput diff --git a/Reconstruction/RecPFACyber/script/tracking.py b/Reconstruction/RecPFACyber/script/tracking.py index 7e07f554..be11bff4 100644 --- a/Reconstruction/RecPFACyber/script/tracking.py +++ b/Reconstruction/RecPFACyber/script/tracking.py @@ -6,7 +6,7 @@ from Configurables import k4DataSvc dsvc = k4DataSvc("EventDataSvc", input="CaloDigi_TDR_o1_v01.root") from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_ -seed = [12340] +seed = [1024] # rndmengine = HepRndm__Engine_CLHEP__RanluxEngine_() # The default engine in Gaudi rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_("RndmGenSvc.Engine") # The default engine in Geant4 rndmengine.SetSingleton = True @@ -52,7 +52,9 @@ podioinput = PodioInput("PodioReader", collections=[ "SITCollection", "TPCCollection", "OTKBarrelCollection", - "FTDCollection" + "FTDCollection", + "MuonBarrelCollection", + "MuonEndcapCollection" ]) # digitization @@ -135,6 +137,16 @@ digiTPC.TPCTrackerHitsCol = gashitname #digiTPC.N_eff = 30 #digiTPC.OutputLevel = DEBUG +## Muon Detector ## +from Configurables import MuonDigiAlg +digiMuon = MuonDigiAlg("MuonDigiAlg") +digiMuon.MuonBarrelHitsCollection = "MuonBarrelCollection" +digiMuon.MuonEndcapHitsCollection = "MuonEndcapCollection" +digiMuon.MuonBarrelTrackerHits = "MuonBarrelTrackerHits" +digiMuon.MuonEndcapTrackerHits = "MuonEndcapTrackerHits" +digiMuon.WriteNtuple = 0 +digiMuon.OutFileName = "Digi_MUON.root" + # tracking from Configurables import KalTestTool # Close multiple scattering and smooth, used by clupatra @@ -220,12 +232,14 @@ full.FTDRawHits = ftdhitname full.TPCTracks = "ClupatraTracks" # add standalone TPC track full.SiTracks = "SubsetTracks" full.OutputTracks = "CompleteTracks" # default name -full.VTXHitToTrackDistance = 5. +#full.VTXHitToTrackDistance = 5. full.FTDHitToTrackDistance = 5. full.SITHitToTrackDistance = 3. full.SETHitToTrackDistance = 5. full.MinChi2ProbForSiliconTracks = 0 -full.MaxChi2PerHit = 500 +full.MaxChi2PerHit = 200 +full.ForceSiTPCMerging = True +full.ForceTPCSegmentsMerging = True #full.OutputLevel = DEBUG from Configurables import TPCDndxAlg @@ -248,14 +262,14 @@ tmt.MuonTagEfficiency = 0.95 # muon true tag efficiency, default is 1.0 (100%) tmt.MuonDetTanTheta = 1.2 # muon det barrel/endcap separation tan(theta) #tmt.OutputLevel = DEBUG -from Configurables import ReadDigiAlg -readtrk = ReadDigiAlg("ReadDigiAlg") -readtrk.SiTracks = "SubsetTracks" -readtrk.TPCTracks = "ClupatraTracks" -readtrk.FullTracks = "CompleteTracks" -readtrk.TPCTracksAssociation = "ClupatraTracksParticleAssociation" -readtrk.FullTracksAssociation = "CompleteTracksParticleAssociation" -readtrk.OutFileName = "TrackAnaTuple_mu.root" +#from Configurables import ReadDigiAlg +#readtrk = ReadDigiAlg("ReadDigiAlg") +#readtrk.SiTracks = "SubsetTracks" +#readtrk.TPCTracks = "ClupatraTracks" +#readtrk.FullTracks = "CompleteTracks" +#readtrk.TPCTracksAssociation = "ClupatraTracksParticleAssociation" +#readtrk.FullTracksAssociation = "CompleteTracksParticleAssociation" +#readtrk.OutFileName = "TrackAnaTuple_mu.root" # output from Configurables import PodioOutput @@ -266,6 +280,10 @@ out.outputCommands = ["drop *", "keep ECALBarrelParticleAssoCol", "keep HCALBarrel", "keep HCALBarrelParticleAssoCol", + "keep ECALEndcaps", + "keep HCALEndcaps", + "keep ECALEndcapsParticleAssoCol", + "keep HCALEndcapsParticleAssoCol", "keep MCParticle", "keep CompleteTracks", "keep CompleteTracksParticleAssociation" ] @@ -273,7 +291,7 @@ out.outputCommands = ["drop *", # ApplicationMgr from Configurables import ApplicationMgr mgr = ApplicationMgr( - TopAlg = [podioinput, digiVXD, digiSIT, digiSET, digiFTD, digiTPC, tracking, forward, subset, clupatra, full, tpr, tpc_dndx, tmt, readtrk, out], + TopAlg = [podioinput, digiVXD, digiSIT, digiSET, digiFTD, digiTPC, digiMuon, tracking, forward, subset, clupatra, full, tpr, tpc_dndx, tmt, out], EvtSel = 'NONE', EvtMax = 10, ExtSvc = [rndmengine, rndmgensvc, dsvc, evtseeder, geosvc, gearsvc, tracksystemsvc, pidsvc], diff --git a/Reconstruction/RecPFACyber/src/Algorithm/PFOReclusteringAlg.cpp b/Reconstruction/RecPFACyber/src/Algorithm/PFOReclusteringAlg.cpp index f7d59919..c87a00bc 100644 --- a/Reconstruction/RecPFACyber/src/Algorithm/PFOReclusteringAlg.cpp +++ b/Reconstruction/RecPFACyber/src/Algorithm/PFOReclusteringAlg.cpp @@ -8,15 +8,17 @@ StatusCode PFOReclusteringAlg::ReadSettings(Settings& m_settings){ //Initialize parameters if(settings.map_stringPars.find("ReadinPFOName")==settings.map_stringPars.end()) settings.map_stringPars["ReadinPFOName"] = "outputPFO"; - if(settings.map_floatPars.find("ECALCalib")==settings.map_floatPars.end()) settings.map_floatPars["ECALCalib"] = 1.02; - if(settings.map_floatPars.find("HCALCalib")==settings.map_floatPars.end()) settings.map_floatPars["HCALCalib"] = 65.; + if(settings.map_floatPars.find("ECALChargedCalib")==settings.map_floatPars.end()) settings.map_floatPars["ECALChargedCalib"] = 1.26; + if(settings.map_floatPars.find("HCALChargedCalib")==settings.map_floatPars.end()) settings.map_floatPars["HCALChargedCalib"] = 4.0; + if(settings.map_floatPars.find("ECALNeutralCalib")==settings.map_floatPars.end()) settings.map_floatPars["ECALNeutralCalib"] = 1.0; + if(settings.map_floatPars.find("HCALNeutralCalib")==settings.map_floatPars.end()) settings.map_floatPars["HCALNeutralCalib"] = 4.0; if(settings.map_floatPars.find("EnergyRes")==settings.map_floatPars.end()) settings.map_floatPars["EnergyRes"] = 0.4; - if(settings.map_floatPars.find("SplitSigma")==settings.map_floatPars.end()) settings.map_floatPars["SplitSigma"] = 0.; + if(settings.map_floatPars.find("SplitSigma")==settings.map_floatPars.end()) settings.map_floatPars["SplitSigma"] = 0.2; if(settings.map_floatPars.find("NeutralMergeSigma")==settings.map_floatPars.end()) settings.map_floatPars["NeutralMergeSigma"] = 0.; - if(settings.map_floatPars.find("VirtualMergeSigma")==settings.map_floatPars.end()) settings.map_floatPars["VirtualMergeSigma"] = 0.5; - if(settings.map_floatPars.find("MinAngleForNeuMerge")==settings.map_floatPars.end()) settings.map_floatPars["MinAngleForNeuMerge"] = 0.12; - if(settings.map_floatPars.find("MinAngleForVirMerge")==settings.map_floatPars.end()) settings.map_floatPars["MinAngleForVirMerge"] = 0.12; + if(settings.map_floatPars.find("VirtualMergeSigma")==settings.map_floatPars.end()) settings.map_floatPars["VirtualMergeSigma"] = 0.4; + if(settings.map_floatPars.find("MinAngleForNeuMerge")==settings.map_floatPars.end()) settings.map_floatPars["MinAngleForNeuMerge"] = 0.20; + if(settings.map_floatPars.find("MinAngleForVirMerge")==settings.map_floatPars.end()) settings.map_floatPars["MinAngleForVirMerge"] = 0.24; return StatusCode::SUCCESS; @@ -40,88 +42,67 @@ StatusCode PFOReclusteringAlg::RunAlgorithm( CyberDataCol& m_datacol ){ } std::sort(m_chargedPFOs.begin(), m_chargedPFOs.end(), compTrkP); -/* - double totE_Ecal = 0; - double totE_Hcal = 0; - cout<<"Readin PFO: "<<p_PFObjects->size()<<", charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<endl; - for(int i=0; i<m_neutralPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; - totE_Ecal = 0; - totE_Hcal = 0; - for(int i=0; i<m_chargedPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; -*/ //If P_trk < E_cluster, create a virtual neutral PFO. ReCluster_SplitFromChg(m_chargedPFOs, m_neutralPFOs); -/* - cout<<" PFO after ReCluster_SplitFromChg: "<<p_PFObjects->size()<<", charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<endl; - totE_Ecal = 0; - totE_Hcal = 0; - cout<<"After split from Ch: charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<", total "<<p_PFObjects->size()<<endl; - for(int i=0; i<m_neutralPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; - totE_Ecal = 0; - totE_Hcal = 0; - for(int i=0; i<m_chargedPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; -*/ + // double totE_Ecal = 0; + // double totE_Hcal = 0; + // cout<<"PFO after splitting: "<<p_PFObjects->size()<<", charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<endl; + // for(int i=0; i<m_neutralPFOs.size(); i++){ + // cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); + // cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALNeutralCalib"]; + // cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALNeutralCalib"]<<endl; + // totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALNeutralCalib"]; + // totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALNeutralCalib"]; + // } + // cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; + // totE_Ecal = 0; + // totE_Hcal = 0; + // for(int i=0; i<m_chargedPFOs.size(); i++){ + // cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); + // cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALChargedCalib"]; + // cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALChargedCalib"]<<endl; + // totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALChargedCalib"]; + // totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALChargedCalib"]; + // } + // cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; + //If P_trk > E_cluster, merge nearby neutral PFO into the charged. ReCluster_MergeToChg(m_chargedPFOs, m_neutralPFOs); m_datacol.map_CaloHit["bkHit"].insert( m_datacol.map_CaloHit["bkHit"].end(), m_bkCol.map_CaloHit["bkHit"].begin(), m_bkCol.map_CaloHit["bkHit"].end() ); + m_datacol.map_BarCol["bkBar"].insert( m_datacol.map_BarCol["bkBar"].end(), m_bkCol.map_BarCol["bkBar"].begin(), m_bkCol.map_BarCol["bkBar"].end() ); + m_datacol.map_1DCluster["bk1DCluster"].insert( m_datacol.map_1DCluster["bk1DCluster"].end(), m_bkCol.map_1DCluster["bk1DCluster"].begin(), m_bkCol.map_1DCluster["bk1DCluster"].end() ); + m_datacol.map_2DCluster["bk2DCluster"].insert( m_datacol.map_2DCluster["bk2DCluster"].end(), m_bkCol.map_2DCluster["bk2DCluster"].begin(), m_bkCol.map_2DCluster["bk2DCluster"].end() ); + m_datacol.map_HalfCluster["bkHalfCluster"].insert( m_datacol.map_HalfCluster["bkHalfCluster"].end(), m_bkCol.map_HalfCluster["bkHalfCluster"].begin(), m_bkCol.map_HalfCluster["bkHalfCluster"].end() ); m_datacol.map_CaloCluster["bk3DCluster"].insert( m_datacol.map_CaloCluster["bk3DCluster"].end(), m_bkCol.map_CaloCluster["bk3DCluster"].begin(), m_bkCol.map_CaloCluster["bk3DCluster"].end() ); m_datacol.map_PFObjects["bkPFO"].insert( m_datacol.map_PFObjects["bkPFO"].end(), m_bkCol.map_PFObjects["bkPFO"].begin(), m_bkCol.map_PFObjects["bkPFO"].end() ); -/* - double totE_Ecal = 0; - double totE_Hcal = 0; - cout<<"After merge all virtual to Ch: charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<", total "<<p_PFObjects->size()<<endl; - for(int i=0; i<m_neutralPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; - totE_Ecal = 0; - totE_Hcal = 0; - for(int i=0; i<m_chargedPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; -*/ + + //double totE_Ecal = 0; + //double totE_Hcal = 0; + //cout<<"After merge all virtual to Ch: charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<", total "<<p_PFObjects->size()<<endl; + //for(int i=0; i<m_neutralPFOs.size(); i++){ + // cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); + // cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALNeutralCalib"]; + // cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALNeutralCalib"]<<endl; + // totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALNeutralCalib"]; + // totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALNeutralCalib"]; + //} + //cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; + //totE_Ecal = 0; + //totE_Hcal = 0; + //for(int i=0; i<m_chargedPFOs.size(); i++){ + // cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); + // cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALChargedCalib"]; + // cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALChargedCalib"]<<endl; + // totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALChargedCalib"]; + // totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALChargedCalib"]; + //} + //cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; + m_chargedPFOs.clear(); m_neutralPFOs.clear(); @@ -144,8 +125,8 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr if(m_chargedPFOs[ic]->getECALClusters().size()==0 && m_chargedPFOs[ic]->getHCALClusters().size()==0) continue; double track_energy = m_chargedPFOs[ic]->getTrackMomentum(); - double ECAL_energy = settings.map_floatPars["ECALCalib"]*m_chargedPFOs[ic]->getECALClusterEnergy(); - double HCAL_energy = settings.map_floatPars["HCALCalib"]*m_chargedPFOs[ic]->getHCALClusterEnergy(); + double ECAL_energy = settings.map_floatPars["ECALChargedCalib"]*m_chargedPFOs[ic]->getECALClusterEnergy(); + double HCAL_energy = settings.map_floatPars["HCALChargedCalib"]*m_chargedPFOs[ic]->getHCALClusterEnergy(); if(track_energy<0 || ECAL_energy<0 || HCAL_energy<0){ std::cout<<"ERROR: Charged PFO info break. Ptrk "<<track_energy<<", E_ecal "<<ECAL_energy<<", E_hcal "<<HCAL_energy<<endl; continue; @@ -158,7 +139,7 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr //cout<<": ECAL cluster size "<<m_chargedPFOs[ic]->getECALClusters().size()<<", HCAL cluster size "<<m_chargedPFOs[ic]->getHCALClusters().size(); //cout<<", Ptrk = "<<track_energy<<", Eecal = "<<ECAL_energy<<", Ehcal = "<<HCAL_energy<<", deltaE = "<<delta_energy<<", sigmaE = "<<sigmaE<<endl; - if(delta_energy >= settings.map_floatPars["NeutralMergeSigma"]*sigmaE) continue; + if(delta_energy - settings.map_floatPars["NeutralMergeSigma"]*sigmaE >= -1e-9) continue; //cout<<" Do charged PFO merge. "<<endl; // All HCAL clusters in the neutral PFO @@ -168,6 +149,10 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr all_neutral_HCAL_clus.insert(all_neutral_HCAL_clus.end(), tmp_HCAL_clus.begin(), tmp_HCAL_clus.end()); } //cout<<" Neutral HCAL cluster size "<<all_neutral_HCAL_clus.size()<<endl; +//cout<<" Print all HCAL clusters "<<endl; +//for(int acl=0; acl<all_neutral_HCAL_clus.size(); acl++){ +//printf(" Cluster #%d: energy %.8f, position (%.3f, %.3f, %.3f) \n", acl, settings.map_floatPars["HCALCalib"]*all_neutral_HCAL_clus[acl]->getHitsE(), all_neutral_HCAL_clus[acl]->getHitCenter().x(), all_neutral_HCAL_clus[acl]->getHitCenter().y(), all_neutral_HCAL_clus[acl]->getHitCenter().z() ); +//} TVector3 trackclus_pos(0, 0, 0); if(m_chargedPFOs[ic]->getECALClusters().size()>0){ @@ -175,17 +160,18 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr } else{ for(int jc=0; jc<m_chargedPFOs[ic]->getHCALClusters().size(); jc++) - trackclus_pos += m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitCenter() * settings.map_floatPars["HCALCalib"]*m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitsE(); + trackclus_pos += m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitCenter() * settings.map_floatPars["HCALChargedCalib"]*m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitsE(); trackclus_pos = trackclus_pos*(1./HCAL_energy); } -//printf(" charged cluster trk pos: [%.3f, %.3f, %.3f] \n", trackclus_pos.x(), trackclus_pos.y(), trackclus_pos.z()); +//printf(" charged cluster trk pos: [%.3f, %.3f, %.3f] \n", trackclus_pos.x(), trackclus_pos.y(), trackclus_pos.z()); int loop_count = 0; std::vector<const Cyber::Calo3DCluster*> skip_clus; while(delta_energy < 0){ loop_count++; if(loop_count>all_neutral_HCAL_clus.size()+10){ +//cout<<" --- Out of loop number: "<<loop_count<<endl; break; } double min_angle = 999.0; @@ -200,12 +186,13 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr min_angle=pfo_angle; clus_index = in; } +//printf(" Check neutral HCAL cluster #%d: energy %.8f, position (%.3f, %.3f, %.3f), angle with ch: %.4f, current closest cluster %d, minAngle %.4f \n", in, settings.map_floatPars["HCALCalib"]*all_neutral_HCAL_clus[in]->getHitsE(), all_neutral_HCAL_clus[in]->getHitCenter().x(), all_neutral_HCAL_clus[in]->getHitCenter().y(), all_neutral_HCAL_clus[in]->getHitCenter().z(), pfo_angle, clus_index, min_angle ); } -//cout<<" In Loop "<<loop_count<<": current deltaE = "<<delta_energy<<", closest virtual cluster index "<<clus_index<<endl; +//cout<<" In Loop "<<loop_count<<": current deltaE = "<<delta_energy<<", closest virtual cluster index "<<clus_index<<", min Angle "<<min_angle<<endl; if(clus_index<0) break; // No neutral Hcal cluster to be merged - double tmp_delta_E = delta_energy + settings.map_floatPars["HCALCalib"]*all_neutral_HCAL_clus[clus_index]->getHitsE(); + double tmp_delta_E = delta_energy + settings.map_floatPars["HCALNeutralCalib"]*all_neutral_HCAL_clus[clus_index]->getHitsE(); if (TMath::Abs(tmp_delta_E) >= TMath::Abs(delta_energy)){ skip_clus.push_back(all_neutral_HCAL_clus[clus_index]); continue; // No need to merge this HCAL cluster @@ -214,7 +201,8 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr // Update delta_energy delta_energy = tmp_delta_E; // Add this HCAL cluster to charged PFO - m_chargedPFOs[ic]->addHCALCluster(all_neutral_HCAL_clus[clus_index]); +//cout<<" Add neutral HCAL cluster #"<<clus_index<<" into charged PFO #"<<ic<<". Cluster E "<<settings.map_floatPars["HCALCalib"]*all_neutral_HCAL_clus[clus_index]->getHitsE()<<", deltaE "<<delta_energy<<endl; + m_chargedPFOs[ic]->addHCALCluster(all_neutral_HCAL_clus[clus_index]); // Remove this HCAL cluster from neutral PFO bool is_found = false; @@ -256,29 +244,29 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr } } -/* - double totE_Ecal = 0; - double totE_Hcal = 0; - cout<<"After merge real neu to Ch: charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<", total "<<p_PFObjects->size()<<endl; - for(int i=0; i<m_neutralPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; - totE_Ecal = 0; - totE_Hcal = 0; - for(int i=0; i<m_chargedPFOs.size(); i++){ - cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy(); - totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy(); - } - cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; -*/ + + // double totE_Ecal = 0; + // double totE_Hcal = 0; + // cout<<"After merge real neu to Ch: charged "<<m_chargedPFOs.size()<<", neutral "<<m_neutralPFOs.size()<<", total "<<p_PFObjects->size()<<endl; + // for(int i=0; i<m_neutralPFOs.size(); i++){ + // cout<<" PFO #"<<i<<": track size "<<m_neutralPFOs[i]->getTracks().size()<<", leading P "<<m_neutralPFOs[i]->getTrackMomentum(); + // cout<<", ECAL cluster size "<<m_neutralPFOs[i]->getECALClusters().size()<<", totE "<<m_neutralPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALNeutralCalib"]; + // cout<<", HCAL cluster size "<<m_neutralPFOs[i]->getHCALClusters().size()<<", totE "<<m_neutralPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALNeutralCalib"]<<endl; + // totE_Ecal += m_neutralPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALNeutralCalib"]; + // totE_Hcal += m_neutralPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALNeutralCalib"]; + // } + // cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; + // totE_Ecal = 0; + // totE_Hcal = 0; + // for(int i=0; i<m_chargedPFOs.size(); i++){ + // cout<<" PFO #"<<i<<": track size "<<m_chargedPFOs[i]->getTracks().size()<<", leading P "<<m_chargedPFOs[i]->getTrackMomentum(); + // cout<<", ECAL cluster size "<<m_chargedPFOs[i]->getECALClusters().size()<<", totE "<<m_chargedPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALChargedCalib"]; + // cout<<", HCAL cluster size "<<m_chargedPFOs[i]->getHCALClusters().size()<<", totE "<<m_chargedPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALChargedCalib"]<<endl; + // totE_Ecal += m_chargedPFOs[i]->getECALClusterEnergy()*settings.map_floatPars["ECALChargedCalib"]; + // totE_Hcal += m_chargedPFOs[i]->getHCALClusterEnergy()*settings.map_floatPars["HCALChargedCalib"]; + // } + // cout<<"-----Charged cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; + //Merge virtual neutral PFOs created from splitting. @@ -289,8 +277,8 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr m_chargedPFOs[ic]->getTracks()[0]->getTrackStates("Hcal").size()==0) continue; double track_energy = m_chargedPFOs[ic]->getTrackMomentum(); - double ECAL_energy = settings.map_floatPars["ECALCalib"]*m_chargedPFOs[ic]->getECALClusterEnergy(); - double HCAL_energy = settings.map_floatPars["HCALCalib"]*m_chargedPFOs[ic]->getHCALClusterEnergy(); + double ECAL_energy = settings.map_floatPars["ECALChargedCalib"]*m_chargedPFOs[ic]->getECALClusterEnergy(); + double HCAL_energy = settings.map_floatPars["HCALChargedCalib"]*m_chargedPFOs[ic]->getHCALClusterEnergy(); if(track_energy<0 || ECAL_energy<0 || HCAL_energy<0){ std::cout<<"ERROR: Charged PFO info break. Ptrk "<<track_energy<<", E_ecal "<<ECAL_energy<<", E_hcal "<<HCAL_energy<<endl; continue; @@ -336,7 +324,7 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr } else{ for(int jc=0; jc<m_chargedPFOs[ic]->getHCALClusters().size(); jc++) - trackclus_pos += m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitCenter() * settings.map_floatPars["HCALCalib"]*m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitsE(); + trackclus_pos += m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitCenter() * settings.map_floatPars["HCALChargedCalib"]*m_chargedPFOs[ic]->getHCALClusters()[jc]->getHitsE(); trackclus_pos = trackclus_pos*(1./HCAL_energy); } @@ -366,7 +354,7 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr if(clus_index<0) break; // No neutral Hcal cluster to be merged - double tmp_delta_E = delta_energy + settings.map_floatPars["HCALCalib"]*all_neutral_HCAL_clus[clus_index]->getHitsE(); + double tmp_delta_E = delta_energy + settings.map_floatPars["HCALNeutralCalib"]*all_neutral_HCAL_clus[clus_index]->getHitsE(); // cout<<" If include this cluster: new deltaE "<<tmp_delta_E<<", merge = "<<(tmp_delta_E > sigmaE * settings.map_floatPars["VirtualMergeSigma"])<<endl; if(tmp_delta_E > sigmaE * settings.map_floatPars["VirtualMergeSigma"]){ @@ -377,7 +365,7 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr //Create a new virtual neutral cluster with energy = absorbed_energy. std::shared_ptr<Cyber::CaloHit> m_hit = all_neutral_HCAL_clus[clus_index]->getCaloHits()[0]->Clone(); - m_hit->setEnergy(absorbed_energy/settings.map_floatPars["HCALCalib"]); + m_hit->setEnergy(absorbed_energy/settings.map_floatPars["HCALNeutralCalib"]); std::shared_ptr<Cyber::Calo3DCluster> m_clus = std::make_shared<Cyber::Calo3DCluster>(); m_clus->addHit(m_hit.get()); @@ -399,7 +387,7 @@ StatusCode PFOReclusteringAlg::ReCluster_MergeToChg(std::vector< std::shared_ptr if(tmp_HCAL_clus[0]==all_neutral_HCAL_clus[clus_index]){ std::shared_ptr<Cyber::CaloHit> m_newhit = all_neutral_HCAL_clus[clus_index]->getCaloHits()[0]->Clone(); - m_newhit->setEnergy(all_neutral_HCAL_clus[clus_index]->getHitsE() - absorbed_energy/settings.map_floatPars["HCALCalib"] ); + m_newhit->setEnergy(all_neutral_HCAL_clus[clus_index]->getHitsE() - absorbed_energy/settings.map_floatPars["HCALNeutralCalib"] ); std::shared_ptr<Cyber::Calo3DCluster> m_newclus = std::make_shared<Cyber::Calo3DCluster>(); m_newclus->addHit(m_newhit.get()); m_newclus->setType(-1); @@ -490,15 +478,15 @@ StatusCode PFOReclusteringAlg::ReCluster_SplitFromChg( std::vector< std::shared_ if(m_chargedPFOs[ipfo]->getECALClusters().size()==0 && m_chargedPFOs[ipfo]->getHCALClusters().size()==0) continue; double track_energy = m_chargedPFOs[ipfo]->getTrackMomentum(); - double ECAL_energy = settings.map_floatPars["ECALCalib"]*m_chargedPFOs[ipfo]->getECALClusterEnergy(); - double HCAL_energy = settings.map_floatPars["HCALCalib"]*m_chargedPFOs[ipfo]->getHCALClusterEnergy(); + double ECAL_energy = settings.map_floatPars["ECALChargedCalib"]*m_chargedPFOs[ipfo]->getECALClusterEnergy(); + double HCAL_energy = settings.map_floatPars["HCALChargedCalib"]*m_chargedPFOs[ipfo]->getHCALClusterEnergy(); if(track_energy<0 || ECAL_energy<0 || HCAL_energy<0){ std::cout<<"ERROR: Charged PFO info break. Ptrk "<<track_energy<<", E_ecal "<<ECAL_energy<<", E_hcal "<<HCAL_energy<<endl; continue; } double delta_energy = ECAL_energy + HCAL_energy - track_energy; - double sigmaE = settings.map_floatPars["EnergyRes"] * sqrt(ECAL_energy + HCAL_energy); + double sigmaE = settings.map_floatPars["EnergyRes"] * sqrt(track_energy); //cout<<" ReCluster_MergeToChg: In ChPFO #"<<ipfo<<": Ptrk = "<<track_energy<<", Eecal = "<<ECAL_energy<<", Ehcal = "<<HCAL_energy<<", deltaE = "<<delta_energy<<", sigmaE = "<<sigmaE<<endl; @@ -506,54 +494,127 @@ StatusCode PFOReclusteringAlg::ReCluster_SplitFromChg( std::vector< std::shared_ //cout<<" Do charged PFO splitting. "<<endl; //Create a new hit and cluster - TVector3 tmp_pos(0,0,0); + TVector3 tmp_pos(0,0,0); for(int ic=0; ic<m_chargedPFOs[ipfo]->getECALClusters().size(); ic++) - tmp_pos += settings.map_floatPars["ECALCalib"] * m_chargedPFOs[ipfo]->getECALClusters()[ic]->getLongiE() * m_chargedPFOs[ipfo]->getECALClusters()[ic]->getShowerCenter(); - for(int ic=0; ic<m_chargedPFOs[ipfo]->getHCALClusters().size(); ic++) - tmp_pos += settings.map_floatPars["HCALCalib"] * m_chargedPFOs[ipfo]->getHCALClusters()[ic]->getHitsE() * m_chargedPFOs[ipfo]->getHCALClusters()[ic]->getHitCenter(); + tmp_pos += settings.map_floatPars["ECALChargedCalib"] * m_chargedPFOs[ipfo]->getECALClusters()[ic]->getLongiE() * m_chargedPFOs[ipfo]->getECALClusters()[ic]->getShowerCenter(); + for(int ic=0; ic<m_chargedPFOs[ipfo]->getHCALClusters().size(); ic++) + tmp_pos += settings.map_floatPars["HCALChargedCalib"] * m_chargedPFOs[ipfo]->getHCALClusters()[ic]->getHitsE() * m_chargedPFOs[ipfo]->getHCALClusters()[ic]->getHitCenter(); tmp_pos = tmp_pos*(1./(ECAL_energy+HCAL_energy)); - std::shared_ptr<Cyber::CaloHit> m_hit = std::make_shared<Cyber::CaloHit>(); - m_hit->setPosition( tmp_pos ); - m_hit->setEnergy( delta_energy/settings.map_floatPars["HCALCalib"] ); + if(ECAL_energy>0 || HCAL_energy>0){ + //Create a new ECAL virtual PFO + if(ECAL_energy>0){ + double tmp_virtualE = delta_energy * ECAL_energy / (ECAL_energy + HCAL_energy) / settings.map_floatPars["ECALChargedCalib"]; + // -- Create bar + std::shared_ptr<Cyber::CaloUnit> m_bar_u = std::make_shared<Cyber::CaloUnit>(); + std::shared_ptr<Cyber::CaloUnit> m_bar_v = std::make_shared<Cyber::CaloUnit>(); + m_bar_u->setQ(tmp_virtualE/4., tmp_virtualE/4); + m_bar_u->setPosition(tmp_pos); + m_bar_v->setQ(tmp_virtualE/4., tmp_virtualE/4); + m_bar_v->setPosition(tmp_pos); + + // -- Create 1D cluster U/V + std::shared_ptr<Cyber::Calo1DCluster> m_1dclus_u = std::make_shared<Cyber::Calo1DCluster>(); + std::shared_ptr<Cyber::Calo1DCluster> m_1dclus_v = std::make_shared<Cyber::Calo1DCluster>(); + m_1dclus_u->addUnit(m_bar_u.get()); + m_1dclus_v->addUnit(m_bar_v.get()); + + // -- Create 2D cluster + std::shared_ptr<Cyber::Calo2DCluster> m_2dclus = std::make_shared<Cyber::Calo2DCluster>(); + m_2dclus->addShowerU(m_1dclus_u.get()); + m_2dclus->addShowerV(m_1dclus_v.get()); + m_2dclus->addTowerID(0., 0., 0.); + m_2dclus->setPos(tmp_pos); + + // -- Create Half cluster U/V + std::shared_ptr<Cyber::CaloHalfCluster> m_hfclus_u = std::make_shared<Cyber::CaloHalfCluster>(); + std::shared_ptr<Cyber::CaloHalfCluster> m_hfclus_v = std::make_shared<Cyber::CaloHalfCluster>(); + m_hfclus_u->addUnit(m_1dclus_u.get()); + m_hfclus_v->addUnit(m_1dclus_v.get()); + + // -- Create ECAL 3D cluster + std::shared_ptr<Cyber::Calo3DCluster> m_clus = std::make_shared<Cyber::Calo3DCluster>(); + m_clus->addHalfClusterU("LinkedLongiCluster", m_hfclus_u.get()); + m_clus->addHalfClusterV("LinkedLongiCluster", m_hfclus_v.get()); + m_clus->addUnit(m_2dclus.get()); + m_clus->setType(-1); + + std::shared_ptr<Cyber::PFObject> m_pfo = std::make_shared<Cyber::PFObject>(); + m_pfo->addECALCluster( m_clus.get() ); + + m_neutralPFOs.push_back( m_pfo ); + p_PFObjects->push_back( m_pfo ); + +//cout<<" In ChPFO #"<<ipfo<<": create a neutral ECAL PFO. En "<<m_pfo->getECALClusterEnergy()*settings.map_floatPars["ECALCalib"]<<endl; + + m_bkCol.map_BarCol["bkBar"].push_back( m_bar_u ); + m_bkCol.map_BarCol["bkBar"].push_back( m_bar_v ); + m_bkCol.map_1DCluster["bk1DCluster"].push_back( m_1dclus_u ); + m_bkCol.map_1DCluster["bk1DCluster"].push_back( m_1dclus_v ); + m_bkCol.map_HalfCluster["bkHalfCluster"].push_back( m_hfclus_u ); + m_bkCol.map_HalfCluster["bkHalfCluster"].push_back( m_hfclus_v ); + m_bkCol.map_2DCluster["bk2DCluster"].push_back( m_2dclus ); + m_bkCol.map_CaloCluster["bk3DCluster"].push_back(m_clus); + m_bkCol.map_PFObjects["bkPFO"].push_back(m_pfo); + } + + //Create a new virtual HCAL PFO + if(HCAL_energy>0){ + double tmp_virtualE = delta_energy * HCAL_energy / (ECAL_energy + HCAL_energy) / settings.map_floatPars["HCALChargedCalib"]; + std::shared_ptr<Cyber::CaloHit> m_hit = std::make_shared<Cyber::CaloHit>(); + m_hit->setPosition( tmp_pos ); + m_hit->setEnergy( tmp_virtualE ); + + std::shared_ptr<Cyber::Calo3DCluster> m_clus_hcal = std::make_shared<Cyber::Calo3DCluster>(); + m_clus_hcal->addHit(m_hit.get()); + m_clus_hcal->setType(-1); - std::shared_ptr<Cyber::Calo3DCluster> m_clus = std::make_shared<Cyber::Calo3DCluster>(); - m_clus->addHit(m_hit.get()); - m_clus->setType(-1); + std::shared_ptr<Cyber::PFObject> m_pfo_hcal = std::make_shared<Cyber::PFObject>(); + m_pfo_hcal->addHCALCluster( m_clus_hcal.get() ); - std::shared_ptr<Cyber::PFObject> m_pfo = std::make_shared<Cyber::PFObject>(); - m_pfo->addHCALCluster( m_clus.get() ); -//cout<<"Create a new Neutral PFO: energy "<<m_pfo->getHCALClusterEnergy()<<endl; + m_neutralPFOs.push_back( m_pfo_hcal ); + p_PFObjects->push_back( m_pfo_hcal ); - m_neutralPFOs.push_back( m_pfo ); - p_PFObjects->push_back( m_pfo ); +//cout<<" In ChPFO #"<<ipfo<<": create a neutral HCAL PFO. En "<<m_pfo_hcal->getHCALClusterEnergy()*settings.map_floatPars["HCALCalib"]<<endl; - //For this charged PFO: reset HCAL energy. (negative HCAL energy is NOT allowed) - if(HCAL_energy>0 && HCAL_energy-delta_energy>0){ - double m_HcalEnScale = (HCAL_energy-delta_energy)/HCAL_energy; -//cout<<"[FY debug] In PFO "<<ipfo<<": track P "<<m_chargedPFOs[ipfo]->getTrackMomentum()<<", HCAL cluster size "<<m_chargedPFOs[ipfo]->getHCALClusters().size()<<", first HCAL has Nhit "<<m_chargedPFOs[ipfo]->getHCALClusters()[0]->getCaloHits().size()<<endl; -//cout<<"[FY debug] Hcal energy scale = "<<m_HcalEnScale<<endl; + m_bkCol.map_CaloHit["bkHit"].push_back( m_hit ); + m_bkCol.map_CaloCluster["bk3DCluster"].push_back(m_clus_hcal); + m_bkCol.map_PFObjects["bkPFO"].push_back(m_pfo_hcal); + } - //Create new HCAL cluster + //Reset origin cluster energy + double m_EnScale = (ECAL_energy + HCAL_energy - delta_energy)/(ECAL_energy + HCAL_energy); +//cout<<"[FY debug] In PFO "<<ipfo<<": track P "<<m_chargedPFOs[ipfo]->getTrackMomentum()<<", HCAL cluster size "<<m_chargedPFOs[ipfo]->getHCALClusters().size()<<endl; +//", first HCAL has Nhit "<<m_chargedPFOs[ipfo]->getHCALClusters()[0]->getCaloHits().size()<<endl; +//cout<<"[FY debug] Hcal energy scale = "<<m_EnScale<<endl; + + //Create a new PFO + std::shared_ptr<Cyber::PFObject> m_newpfo = m_chargedPFOs[ipfo]->Clone(); + // -- Reset ECAL cluster + std::vector<const Cyber::Calo3DCluster*> tmp_clusvec; tmp_clusvec.clear(); + for(int ic=0; ic<m_chargedPFOs[ipfo]->getECALClusters().size(); ic++){ + std::shared_ptr<Cyber::Calo3DCluster> m_newclus = m_chargedPFOs[ipfo]->getECALClusters()[ic]->Clone(); + m_newclus->setEnergyScale( m_EnScale*m_newclus->getEnergyScale() ); + tmp_clusvec.push_back(m_newclus.get()); + m_bkCol.map_CaloCluster["bk3DCluster"].push_back(m_newclus); + } + m_newpfo->setECALCluster(tmp_clusvec); + + // -- Reset HCAL cluster std::shared_ptr<Cyber::Calo3DCluster> m_newclus = std::make_shared<Cyber::Calo3DCluster>(); for(int ic=0; ic<m_chargedPFOs[ipfo]->getHCALClusters().size(); ic++){ std::vector<const Cyber::CaloHit*> tmp_hits = m_chargedPFOs[ipfo]->getHCALClusters()[ic]->getCaloHits(); for(int ih=0; ih<tmp_hits.size(); ih++){ std::shared_ptr<CaloHit> tmp_newhit = tmp_hits[ih]->Clone(); - tmp_newhit->setEnergy( tmp_newhit->getEnergy()*m_HcalEnScale ); + tmp_newhit->setEnergy( tmp_newhit->getEnergy()*m_EnScale ); m_newclus->addHit(tmp_newhit.get()); m_bkCol.map_CaloHit["bkHit"].push_back( tmp_newhit ); } } m_bkCol.map_CaloCluster["bk3DCluster"].push_back(m_newclus); - -//cout<<"[FY debug] new HCAL cluster: hit size "<<m_newclus->getCaloHits().size()<<", total energy "<<m_newclus->getHitsE()<<endl; - - //Create a new PFO - std::shared_ptr<Cyber::PFObject> m_newpfo = m_chargedPFOs[ipfo]->Clone(); - std::vector<const Cyber::Calo3DCluster*> tmp_clusvec; tmp_clusvec.clear(); - tmp_clusvec.push_back(m_newclus.get()); - m_newpfo->setHCALCluster(tmp_clusvec); + std::vector<const Cyber::Calo3DCluster*> tmp_hcalclus; tmp_hcalclus.clear(); + tmp_hcalclus.push_back(m_newclus.get()); + m_newpfo->setHCALCluster(tmp_hcalclus); m_bkCol.map_PFObjects["bkPFO"].push_back(m_newpfo); @@ -566,15 +627,10 @@ StatusCode PFOReclusteringAlg::ReCluster_SplitFromChg( std::vector< std::shared_ //cout<<"[FY debug] The splitted new charged PFO: track size "<<m_newpfo->getTracks().size()<<", leading P "<<m_newpfo->getTrackMomentum(); //cout<<", ECAL cluster size "<<m_newpfo->getECALClusters().size()<<", totE "<<m_newpfo->getECALClusterEnergy(); //cout<<", HCAL cluster size "<<m_newpfo->getHCALClusters().size()<<", totE "<<m_newpfo->getHCALClusterEnergy()<<endl; +//cout<<endl; } - - m_bkCol.map_CaloHit["bkHit"].push_back( m_hit ); - m_bkCol.map_CaloCluster["bk3DCluster"].push_back(m_clus); - m_bkCol.map_PFObjects["bkPFO"].push_back(m_pfo); } - - return StatusCode::SUCCESS; }; diff --git a/Reconstruction/RecPFACyber/src/Algorithm/TrackClusterConnectingAlg.cpp b/Reconstruction/RecPFACyber/src/Algorithm/TrackClusterConnectingAlg.cpp index 5d3ff580..c4a68647 100644 --- a/Reconstruction/RecPFACyber/src/Algorithm/TrackClusterConnectingAlg.cpp +++ b/Reconstruction/RecPFACyber/src/Algorithm/TrackClusterConnectingAlg.cpp @@ -9,11 +9,15 @@ StatusCode TrackClusterConnectingAlg::ReadSettings(Settings& m_settings){ //Initialize parameters if(settings.map_stringPars.find("ReadinECALClusterName")==settings.map_stringPars.end()) settings.map_stringPars["ReadinECALClusterName"] = "EcalCluster"; if(settings.map_stringPars.find("ReadinHCALClusterName")==settings.map_stringPars.end()) settings.map_stringPars["ReadinHCALClusterName"] = "HcalCluster"; + if(settings.map_floatPars.find("ECALChargedCalib")==settings.map_floatPars.end()) settings.map_floatPars["ECALChargedCalib"] = 1.26; + if(settings.map_floatPars.find("HCALChargedCalib")==settings.map_floatPars.end()) settings.map_floatPars["HCALChargedCalib"] = 4.0; + if(settings.map_floatPars.find("ECALNeutralCalib")==settings.map_floatPars.end()) settings.map_floatPars["ECALNeutralCalib"] = 1.0; + if(settings.map_floatPars.find("HCALNeutralCalib")==settings.map_floatPars.end()) settings.map_floatPars["HCALNeutralCalib"] = 4.0; if(settings.map_floatPars.find("th_ChFragEn")==settings.map_floatPars.end()) settings.map_floatPars["th_ChFragEn"] = 2.; if(settings.map_floatPars.find("th_ChFragDepth")==settings.map_floatPars.end()) settings.map_floatPars["th_ChFragDepth"] = 100.; if(settings.map_floatPars.find("th_ChFragMinR")==settings.map_floatPars.end()) settings.map_floatPars["th_ChFragMinR"] = 200.; - if(settings.map_floatPars.find("th_HcalMatchingR")==settings.map_floatPars.end()) settings.map_floatPars["th_HcalMatchingR"] = 150.; + if(settings.map_floatPars.find("th_HcalMatchingR")==settings.map_floatPars.end()) settings.map_floatPars["th_HcalMatchingR"] = 100.; if(settings.map_floatPars.find("th_MIPEnergy")==settings.map_floatPars.end()) settings.map_floatPars["th_MIPEnergy"] = 0.5; if(settings.map_floatPars.find("th_AbsorbCone")==settings.map_floatPars.end()) settings.map_floatPars["th_AbsorbCone"] = 0.8; @@ -43,6 +47,8 @@ StatusCode TrackClusterConnectingAlg::Initialize( CyberDataCol& m_datacol ){ m_tracks.push_back( m_datacol.TrackCol[itrk].get() ); } + m_bkCol.EnergyCorrSvc = m_datacol.EnergyCorrSvc; + //cout<<"Readin Track size: "<<m_tracks.size()<<", ECAL cluster size: "<<m_EcalClusters.size()<<", HCAL cluster size "<<m_HcalClusters.size()<<endl; //cout<<"Print track"<<endl; //for(int i=0; i<m_tracks.size(); i++) @@ -305,6 +311,18 @@ StatusCode TrackClusterConnectingAlg::EcalChFragAbsorption( std::vector<const Cy } } } + + //Do cluster energy correction + for(int ic=0; ic<m_newclusCol.size(); ic++){ + double tmp_clusE = m_newclusCol[ic]->getEnergy()*settings.map_floatPars.at("ECALNeutralCalib"); + TVector3 clus_pos = m_newclusCol[ic]->getShowerCenter(); + double tmp_phi = std::atan2(clus_pos.y(), clus_pos.x())* 180.0 / TMath::Pi(); //TODO: use TVector3 to calculate + if (tmp_phi < 0) tmp_phi += 360.0; + double tmp_theta = std::atan2(clus_pos.z(), clus_pos.Perp())* 180.0 / TMath::Pi() + 90; + + double tmp_scale = m_bkCol.EnergyCorrSvc->energyCorrection(tmp_clusE, tmp_phi, tmp_theta)/tmp_clusE; + m_newclusCol[ic]->setEnergyScale( tmp_scale ); + } //for(int ic=0; ic<m_newclusCol.size(); ic++){ // cout<<" ECAL Cluster #"<<ic<<": En = "<<m_newclusCol[ic]->getLongiE()<<", track size "<<m_newclusCol[ic]->getAssociatedTracks().size()<<endl; //} diff --git a/Reconstruction/RecPFACyber/src/CyberPFAlg.cpp b/Reconstruction/RecPFACyber/src/CyberPFAlg.cpp index 70185d2c..cf64cb4c 100644 --- a/Reconstruction/RecPFACyber/src/CyberPFAlg.cpp +++ b/Reconstruction/RecPFACyber/src/CyberPFAlg.cpp @@ -12,8 +12,8 @@ using namespace dd4hep; int Cyber::CaloUnit::Nmodule = 32; int Cyber::CaloUnit::Nstave = 15; int Cyber::CaloUnit::Nlayer = 14; -int Cyber::CaloUnit::NbarPhi_odd[14] = {39, 39, 39, 39, 37, 37, 37, 37, 37, 35, 35, 35, 35, 33}; -int Cyber::CaloUnit::NbarPhi_even[14] = {29, 29, 31, 31, 33, 35, 35, 37, 37, 39, 41, 41, 43, 43}; +int Cyber::CaloUnit::NbarPhi_odd[14] = {39, 37, 37, 37, 37, 37, 35, 35, 35, 35, 33, 33, 33, 33}; +int Cyber::CaloUnit::NbarPhi_even[14] = {27, 29, 29, 31, 31, 33, 35, 35, 37, 37, 39, 41, 41, 43}; int Cyber::CaloUnit::NbarZ = 36; //int Cyber::CaloUnit::over_module[28] = {13,15,16,18,19,21,22,24,25,26,28,29,30,32,33,35,36,38,39,41,42,43,45,46}; //int Cyber::CaloUnit::over_module_set = 2; @@ -51,16 +51,22 @@ StatusCode CyberPFAlg::initialize() m_pMCParticleCreatorSettings.map_stringPars["MCParticleCollections"] = name_MCParticleCol.value(); m_pTrackCreatorSettings.map_stringVecPars["trackCollections"] = name_TrackCol.value(); + m_pTrackCreatorSettings.map_boolPars["DoCleanTrack"] = m_doCleanTrack.value(); + m_pTrackCreatorSettings.map_boolPars["UseTruthMatchTrk"] = m_useTruthMatchTrk.value(); + m_pTrackCreatorSettings.map_stringPars["TrackIDWeightFile"] = m_trackIDFile.value(); + m_pTrackCreatorSettings.map_stringPars["TrackIDMethod"] = m_trackIDMethod.value(); m_pTrackCreatorSettings.map_floatPars["BField"] = m_BField; - m_pTrackCreatorSettings.map_floatPars["TrkEndZCut"] = 200.; - m_pTrackCreatorSettings.map_floatPars["TrkEndRCutMin"] = 700.; - m_pTrackCreatorSettings.map_floatPars["TrkEndRCutMax"] = 1600.; - m_pTrackCreatorSettings.map_floatPars["TrkStartRCutMin"] = 635.; - m_pTrackCreatorSettings.map_floatPars["TrkStartRCutMax"] = 640.; - m_pTrackCreatorSettings.map_floatPars["TrkLengthCut"] = 130.; - m_pTrackCreatorSettings.map_floatPars["BrokenTrkMinP"] = 0.5; - m_pTrackCreatorSettings.map_floatPars["BrokenTrkDeltaPCut"] = 0.15; - m_pTrackCreatorSettings.map_floatPars["BrokenTrkDistance"] = 10.; + m_pTrackCreatorSettings.map_floatPars["TrkMaxIP"] = 100.; + m_pTrackCreatorSettings.map_floatPars["BDTCut"] = -0.8289; + //m_pTrackCreatorSettings.map_floatPars["TrkEndZCut"] = 200.; + //m_pTrackCreatorSettings.map_floatPars["TrkEndRCutMin"] = 700.; + //m_pTrackCreatorSettings.map_floatPars["TrkEndRCutMax"] = 1600.; + //m_pTrackCreatorSettings.map_floatPars["TrkStartRCutMin"] = 635.; + //m_pTrackCreatorSettings.map_floatPars["TrkStartRCutMax"] = 640.; + //m_pTrackCreatorSettings.map_floatPars["TrkLengthCut"] = 130.; + //m_pTrackCreatorSettings.map_floatPars["BrokenTrkMinP"] = 0.5; + //m_pTrackCreatorSettings.map_floatPars["BrokenTrkDeltaPCut"] = 0.15; + //m_pTrackCreatorSettings.map_floatPars["BrokenTrkDistance"] = 10.; std::vector<std::string> name_CaloHits = name_EcalHits; std::vector<std::string> name_CaloReadout = name_EcalReadout; @@ -71,10 +77,13 @@ StatusCode CyberPFAlg::initialize() m_CaloHitsCreatorSettings.map_stringPars["EcalType"] = m_EcalType.value(); m_OutputCreatorSettings.map_stringPars["OutputPFO"] = name_PFObject.value(); - m_OutputCreatorSettings.map_boolPars["UseTruthTrk"] = m_useTruthTrk.value(); + m_OutputCreatorSettings.map_boolPars["UseTruthTrk"] = m_useMCPTrk.value(); + m_OutputCreatorSettings.map_boolPars["UseTruthMatchTrk"] = m_useTruthMatchTrk.value(); m_OutputCreatorSettings.map_floatPars["BField"] = m_BField.value(); - m_OutputCreatorSettings.map_floatPars["ECALCalib"] = m_EcalCalib.value(); - m_OutputCreatorSettings.map_floatPars["HCALCalib"] = m_HcalCalib.value(); + m_OutputCreatorSettings.map_floatPars["ECALChargedCalib"] = m_EcalChargedCalib.value(); + m_OutputCreatorSettings.map_floatPars["HCALChargedCalib"] = m_HcalChargedCalib.value(); + m_OutputCreatorSettings.map_floatPars["ECALNeutralCalib"] = m_EcalNeutralCalib.value(); + m_OutputCreatorSettings.map_floatPars["HCALNeutralCalib"] = m_HcalNeutralCalib.value(); //Initialize Creators m_pMCParticleCreator = new MCParticleCreator( m_pMCParticleCreatorSettings ); @@ -157,6 +166,12 @@ StatusCode CyberPFAlg::initialize() m_geosvc = service<IGeomSvc>("GeomSvc"); if ( !m_geosvc ) throw "CyberPFAlg :Failed to find GeomSvc ..."; + m_dd4hep = m_geosvc->lcdd(); + if ( !m_dd4hep ) throw "CyberPFAlg :Failed to get dd4hep::Detector ..."; + + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + m_volumeManager = m_dd4hep->volumeManager(); + m_energycorsvc = service<ICrystalEcalSvc>("CrystalEcalEnergyCorrectionSvc"); if ( !m_energycorsvc ) throw "CyberPFAlg :Failed to find CrystalEcalEnergyCorrectionSvc ..."; //m_energycorsvc->initialize(); @@ -207,6 +222,9 @@ StatusCode CyberPFAlg::initialize() t_MCParticle->Branch("mcEn", &m_mcEn); t_MCParticle->Branch("mcMass", &m_mcMass); t_MCParticle->Branch("mcCharge", &m_mcCharge); + t_MCParticle->Branch("mcVTXx", &m_mcVTXx); + t_MCParticle->Branch("mcVTXy", &m_mcVTXy); + t_MCParticle->Branch("mcVTXz", &m_mcVTXz); t_MCParticle->Branch("mcEPx", &m_mcEPx); t_MCParticle->Branch("mcEPy", &m_mcEPy); t_MCParticle->Branch("mcEPz", &m_mcEPz); @@ -610,6 +628,7 @@ StatusCode CyberPFAlg::initialize() // Tracks t_Track->Branch("m_Ntrk", &m_Ntrk); t_Track->Branch("m_type", &m_type); + t_Track->Branch("m_Nhit", &m_Nhit); t_Track->Branch("m_trkstate_d0", &m_trkstate_d0); t_Track->Branch("m_trkstate_z0", &m_trkstate_z0); t_Track->Branch("m_trkstate_phi", &m_trkstate_phi); @@ -678,9 +697,9 @@ StatusCode CyberPFAlg::execute() //Readin collections m_pMCParticleCreator->CreateMCParticle( m_DataCol, *r_MCParticleCol ); - if(m_useTruthTrk) m_pTrackCreator->CreateTracksFromMCParticle(m_DataCol, *r_MCParticleCol); + if(m_useMCPTrk) m_pTrackCreator->CreateTracksFromMCParticle(m_DataCol, *r_MCParticleCol); else m_pTrackCreator->CreateTracks( m_DataCol, r_TrackCols, r_MCPTrkAssoCol ); - m_pCaloHitsCreator->CreateCaloHits( m_DataCol, r_CaloHitCols, map_readout_decoder, map_CaloMCPAssoCols ); + m_pCaloHitsCreator->CreateCaloHits( m_DataCol, r_CaloHitCols, map_readout_decoder, map_CaloMCPAssoCols, m_volumeManager); //Perform PFA algorithm m_algorithmManager.RunAlgorithm( m_DataCol ); @@ -710,6 +729,9 @@ StatusCode CyberPFAlg::execute() m_mcEn.push_back( m_MCPCol[imc].getEnergy() ); m_mcMass.push_back( m_MCPCol[imc].getMass() ); m_mcCharge.push_back( m_MCPCol[imc].getCharge() ); + m_mcVTXx.push_back( m_MCPCol[imc].getVertex()[0] ); + m_mcVTXy.push_back( m_MCPCol[imc].getVertex()[1] ); + m_mcVTXz.push_back( m_MCPCol[imc].getVertex()[2] ); m_mcEPx.push_back( m_MCPCol[imc].getEndpoint()[0] ); m_mcEPy.push_back( m_MCPCol[imc].getEndpoint()[1] ); m_mcEPz.push_back( m_MCPCol[imc].getEndpoint()[2] ); @@ -1377,7 +1399,8 @@ StatusCode CyberPFAlg::execute() if (tmp_phi < 0) tmp_phi += 360.0; double tmp_theta = std::atan2(m_EcalClusterCol[icl]->getShowerCenter().z(), m_EcalClusterCol[icl]->getShowerCenter().Perp())* 180.0 / M_PI + 90; //cout<<" Theta: "<<tmp_theta<<" Phi: "<<tmp_phi<<endl; - m_EcalClus_Escale.push_back(m_energycorsvc->energyCorrection(m_EcalClusterCol[icl]->getLongiE(), tmp_phi, tmp_theta)); + //m_EcalClus_Escale.push_back(m_energycorsvc->energyCorrection(m_EcalClusterCol[icl]->getLongiE(), tmp_phi, tmp_theta)); + m_EcalClus_Escale.push_back(m_EcalClusterCol[icl]->getLongiE()); if(m_EcalClusterCol[icl]->getAssociatedTracks().size()==1){ @@ -1518,6 +1541,7 @@ StatusCode CyberPFAlg::execute() m_Ntrk = m_trkCol.size(); for(int itrk=0; itrk<m_Ntrk; itrk++){ m_type.push_back(m_trkCol[itrk]->getType()); + m_Nhit.push_back(m_trkCol[itrk]->getTrackerHits()); std::vector<TrackState> AllTrackStates = m_trkCol[itrk]->getAllTrackStates(); for(int istate=0; istate<AllTrackStates.size(); istate++){ m_trkstate_d0.push_back( AllTrackStates[istate].D0 ); @@ -1590,7 +1614,7 @@ StatusCode CyberPFAlg::execute() double tmp_phi = std::atan2(t_ecal_clusters[ie]->getShowerCenter().y(), t_ecal_clusters[ie]->getShowerCenter().x())* 180.0 / M_PI; if (tmp_phi < 0) tmp_phi += 360.0; double tmp_theta = std::atan2(t_ecal_clusters[ie]->getShowerCenter().z(), t_ecal_clusters[ie]->getShowerCenter().Perp())* 180.0 / M_PI + 90; - pfo_ecal_clus_Escale.push_back(m_energycorsvc->energyCorrection(t_ecal_clusters[ie]->getLongiE(), tmp_phi, tmp_theta)); + pfo_ecal_clus_Escale.push_back(t_ecal_clusters[ie]->getLongiE()); } for(int ih=0; ih<t_hcal_clusters.size(); ih++){ @@ -1655,7 +1679,7 @@ StatusCode CyberPFAlg::finalize() //r_HCalHitCols.clear(); r_CaloHitCols.clear(); //m_energycorsvc->finalize(); - + delete m_cellIDConverter, m_geosvc; info() << "Processed " << _nEvt << " events " << endmsg; return GaudiAlgorithm::finalize(); } @@ -1669,6 +1693,9 @@ void CyberPFAlg::ClearMCParticle(){ m_mcEn.clear(); m_mcMass.clear(); m_mcCharge.clear(); + m_mcVTXx.clear(); + m_mcVTXy.clear(); + m_mcVTXz.clear(); m_mcEPx.clear(); m_mcEPy.clear(); m_mcEPz.clear(); @@ -2093,6 +2120,7 @@ void CyberPFAlg::ClearCluster(){ void CyberPFAlg::ClearTrack(){ m_type.clear(); + m_Nhit.clear(); m_trkstate_d0.clear(); m_trkstate_z0.clear(); m_trkstate_phi.clear(); diff --git a/Reconstruction/RecPFACyber/src/Objects/Calo1DCluster.cc b/Reconstruction/RecPFACyber/src/Objects/Calo1DCluster.cc index 5e9a8728..9e99f930 100644 --- a/Reconstruction/RecPFACyber/src/Objects/Calo1DCluster.cc +++ b/Reconstruction/RecPFACyber/src/Objects/Calo1DCluster.cc @@ -65,10 +65,11 @@ namespace Cyber{ } TVector3 Calo1DCluster::getPos() const{ - TVector3 pos(0,0,0); + if(pos.x()!=0 || pos.y()!=0 || pos.z()!=0) return pos; + TVector3 m_pos(0,0,0); double Etot=getEnergy(); - for(int i=0;i<Bars.size();i++) pos += Bars[i]->getPosition() * (Bars[i]->getEnergy()/Etot); - return pos; + for(int i=0;i<Bars.size();i++) m_pos += Bars[i]->getPosition() * (Bars[i]->getEnergy()/Etot); + return m_pos; } double Calo1DCluster::getT1() const{ diff --git a/Reconstruction/RecPFACyber/src/Objects/Calo2DCluster.cc b/Reconstruction/RecPFACyber/src/Objects/Calo2DCluster.cc index 69605fcc..bc91695b 100644 --- a/Reconstruction/RecPFACyber/src/Objects/Calo2DCluster.cc +++ b/Reconstruction/RecPFACyber/src/Objects/Calo2DCluster.cc @@ -100,9 +100,9 @@ namespace Cyber{ TVector3 Calo2DCluster::getPos() const{ - TVector3 m_pos(0, 0, 0); - if(towerID.size()==0) return m_pos; + if( pos.x()!=0 || pos.y()!=0 || pos.z()!=0 || towerID.size()==0 ) return pos; + TVector3 m_pos(0., 0., 0.); float rotAngle = -towerID[0][0]*TMath::TwoPi()/Cyber::CaloUnit::Nmodule; TVector3 m_vecX(0., 0., 0.); TVector3 m_vecY(0., 0., 0.); diff --git a/Reconstruction/RecPFACyber/src/Objects/Calo3DCluster.cc b/Reconstruction/RecPFACyber/src/Objects/Calo3DCluster.cc index dbbf49fa..2ddce73e 100644 --- a/Reconstruction/RecPFACyber/src/Objects/Calo3DCluster.cc +++ b/Reconstruction/RecPFACyber/src/Objects/Calo3DCluster.cc @@ -51,6 +51,7 @@ namespace Cyber{ for(int ihf=0; ihf<iter.second.size(); ihf++) m_clus->addHalfClusterV(iter.first, iter.second[ihf]); for(auto iter:m_TrackCol) m_clus->addAssociatedTrack(iter); + m_clus->setEnergyScale(Escale); m_clus->setLinkedMCP(MCParticleWeight); m_clus->FitAxis(); @@ -215,13 +216,14 @@ namespace Cyber{ double Calo3DCluster::getHitsE() const{ double en=0; for(int i=0;i<hits.size(); i++) en+=hits[i]->getEnergy(); - return en; + return en*Escale; } double Calo3DCluster::getEnergy() const{ double result = 0; for(int m=0; m<m_2dclusters.size(); m++) result += m_2dclusters[m]->getEnergy(); + if(result == 0) result = getLongiE(); return result; } @@ -237,7 +239,7 @@ namespace Cyber{ for(auto iclus: iter.second) en += iclus->getEnergy(); } - return en; + return en*Escale; } TVector3 Calo3DCluster::getHitCenter() const{ diff --git a/Reconstruction/RecPFACyber/src/Objects/CaloUnit.cc b/Reconstruction/RecPFACyber/src/Objects/CaloUnit.cc index b2a9b619..649e777e 100644 --- a/Reconstruction/RecPFACyber/src/Objects/CaloUnit.cc +++ b/Reconstruction/RecPFACyber/src/Objects/CaloUnit.cc @@ -101,7 +101,7 @@ namespace Cyber{ std::shared_ptr<CaloUnit> CaloUnit::Clone() const{ std::shared_ptr<CaloUnit> m_bar = std::make_shared<CaloUnit>(); m_bar->setcellID(cellID); - m_bar->setcellID( system, module, stave, dlayer, slayer, bar ); + m_bar->setcellID( system, module, stave, part, dlayer, slayer, bar ); m_bar->setPosition(position); m_bar->setQ(Q1, Q2); m_bar->setT(T1, T2); diff --git a/Reconstruction/RecPFACyber/src/Tools/CaloHitsCreator.cpp b/Reconstruction/RecPFACyber/src/Tools/CaloHitsCreator.cpp index 2b19c092..6eb324dd 100644 --- a/Reconstruction/RecPFACyber/src/Tools/CaloHitsCreator.cpp +++ b/Reconstruction/RecPFACyber/src/Tools/CaloHitsCreator.cpp @@ -11,7 +11,8 @@ namespace Cyber{ StatusCode CaloHitsCreator::CreateCaloHits( CyberDataCol& m_DataCol, std::vector<DataHandle<edm4hep::CalorimeterHitCollection>*>& r_CaloHitCols, std::map<std::string, dd4hep::DDSegmentation::BitFieldCoder*>& map_decoder, - std::map<std::string, DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection>*>& map_CaloParticleAssoCol ) + std::map<std::string, DataHandle<edm4hep::MCRecoCaloParticleAssociationCollection>*>& map_CaloParticleAssoCol, + const dd4hep::VolumeManager& m_volumeManager ) { if(r_CaloHitCols.size()==0 || settings.map_stringVecPars.at("CaloHitCollections").size()==0) StatusCode::SUCCESS; @@ -32,7 +33,7 @@ namespace Cyber{ //Convert to local objects: for(auto iter : m_DataCol.collectionMap_CaloHit){ - if( settings.map_stringPars.at("EcalType")=="BarEcal" && iter.first == "ECALBarrel") continue; + if( settings.map_stringPars.at("EcalType")=="BarEcal" && (iter.first == "ECALBarrel" || iter.first == "ECALEndcaps" )) continue; std::vector<std::shared_ptr<Cyber::CaloHit>> m_hitCol; m_hitCol.clear(); const edm4hep::MCRecoCaloParticleAssociationCollection* const_MCPCaloAssoCol; @@ -65,60 +66,117 @@ namespace Cyber{ if(settings.map_stringPars.at("EcalType")=="BarEcal"){ std::vector<std::shared_ptr<Cyber::CaloUnit>> m_barCol; m_barCol.clear(); - const edm4hep::MCRecoCaloParticleAssociationCollection* const_MCPCaloAssoCol = map_CaloParticleAssoCol["ECALBarrel"]->get(); - auto CaloHits = m_DataCol.collectionMap_CaloHit["ECALBarrel"]; - std::map<std::uint64_t, std::vector<Cyber::CaloUnit> > map_cellID_hits; map_cellID_hits.clear(); - for(auto& hit : CaloHits){ - Cyber::CaloUnit m_bar; - m_bar.setcellID(hit.getCellID()); - m_bar.setPosition( TVector3(hit.getPosition().x, hit.getPosition().y, hit.getPosition().z) ); - m_bar.setQ(hit.getEnergy()/2., hit.getEnergy()/2.); - m_bar.setT(hit.getTime(), hit.getTime()); - for(int ilink=0; ilink<const_MCPCaloAssoCol->size(); ilink++){ - if( hit == const_MCPCaloAssoCol->at(ilink).getRec() ) m_bar.addLinkedMCP( std::make_pair(const_MCPCaloAssoCol->at(ilink).getSim(), const_MCPCaloAssoCol->at(ilink).getWeight()) ); - } - - - map_cellID_hits[hit.getCellID()].push_back(m_bar); - } - for(auto& hit : map_cellID_hits){ - if(hit.second.size()!=2){ std::cout<<"WARNING: didn't find correct hit pairs! "<<std::endl; continue; } + //Readin ECAL barrel hits + if( m_DataCol.collectionMap_CaloHit.find("ECALBarrel") != m_DataCol.collectionMap_CaloHit.end() ){ + const edm4hep::MCRecoCaloParticleAssociationCollection* const_MCPCaloAssoCol = map_CaloParticleAssoCol["ECALBarrel"]->get(); + auto CaloHits = m_DataCol.collectionMap_CaloHit["ECALBarrel"]; + std::map<std::uint64_t, std::vector<Cyber::CaloUnit> > map_cellID_hits; map_cellID_hits.clear(); + for(auto& hit : CaloHits){ + Cyber::CaloUnit m_bar; + m_bar.setcellID(hit.getCellID()); + m_bar.setPosition( TVector3(hit.getPosition().x, hit.getPosition().y, hit.getPosition().z) ); + m_bar.setQ(hit.getEnergy()/2., hit.getEnergy()/2.); + m_bar.setT(hit.getTime(), hit.getTime()); + + unsigned long long tmp_id = hit.getCellID(); + dd4hep::PlacedVolume ipv = m_volumeManager.lookupVolumePlacement(tmp_id); + dd4hep::Volume ivol = ipv.volume(); + std::vector< double > iVolParam = ivol.solid().dimensions(); + auto maxElement = std::max_element(iVolParam.begin(), iVolParam.end()); + iVolParam.clear(); + m_bar.setBarLength(*maxElement * 20); + + for(int ilink=0; ilink<const_MCPCaloAssoCol->size(); ilink++){ + if( hit == const_MCPCaloAssoCol->at(ilink).getRec() ) m_bar.addLinkedMCP( std::make_pair(const_MCPCaloAssoCol->at(ilink).getSim(), const_MCPCaloAssoCol->at(ilink).getWeight()) ); + } + + map_cellID_hits[hit.getCellID()].push_back(m_bar); + } + for(auto& hit : map_cellID_hits){ + if(hit.second.size()!=2){ std::cout<<"WARNING: didn't find correct hit pairs! "<<std::endl; continue; } - //Cyber::CaloUnit* m_bar = new Cyber::CaloUnit(); - std::shared_ptr<Cyber::CaloUnit> m_bar = std::make_shared<Cyber::CaloUnit>(); + //Cyber::CaloUnit* m_bar = new Cyber::CaloUnit(); + std::shared_ptr<Cyber::CaloUnit> m_bar = std::make_shared<Cyber::CaloUnit>(); - unsigned long long id = hit.first; - m_bar->setcellID( id ); - m_bar->setcellID( map_decoder["ECALBarrel"]->get(id, "system"), - map_decoder["ECALBarrel"]->get(id, "module"), - map_decoder["ECALBarrel"]->get(id, "stave"), - map_decoder["ECALBarrel"]->get(id, "dlayer"), - map_decoder["ECALBarrel"]->get(id, "slayer"), - map_decoder["ECALBarrel"]->get(id, "bar")); - m_bar->setPosition(hit.second[0].getPosition()); - m_bar->setQ( hit.second[0].getEnergy(), hit.second[1].getEnergy() ); - m_bar->setT( hit.second[0].getT1(), hit.second[1].getT1() ); - - //---oooOOO000OOOooo---set bar length---oooOOO000OOOooo--- - //TODO: reading bar length from geosvc. - double t_bar_length; - if(m_bar->getSlayer()==1) t_bar_length = 374.667; - else{ - if( m_bar->getModule()%2==0 ) t_bar_length = 288 + (m_bar->getDlayer()-1)* 12.708; - else t_bar_length = 409 - (m_bar->getDlayer()-1)* 4.667; + unsigned long long id = hit.first; + m_bar->setcellID( id ); + m_bar->setcellID( map_decoder["ECALBarrel"]->get(id, "system"), + map_decoder["ECALBarrel"]->get(id, "module"), + map_decoder["ECALBarrel"]->get(id, "stave"), + -1, + map_decoder["ECALBarrel"]->get(id, "dlayer"), + map_decoder["ECALBarrel"]->get(id, "slayer"), + map_decoder["ECALBarrel"]->get(id, "bar")); + m_bar->setPosition(hit.second[0].getPosition()); + m_bar->setBarLength(hit.second[0].getBarLength()); + m_bar->setQ( hit.second[0].getEnergy(), hit.second[1].getEnergy() ); + m_bar->setT( hit.second[0].getT1(), hit.second[1].getT1() ); + + //add MCParticle link + for(int ilink=0; ilink<hit.second[0].getLinkedMCP().size(); ilink++) m_bar->addLinkedMCP( hit.second[0].getLinkedMCP()[ilink] ); + + m_barCol.push_back(m_bar); //Save for later use in algorithms } - m_bar->setBarLength(t_bar_length); - //---oooOOO000OOOooo---set bar length---oooOOO000OOOooo--- + + m_DataCol.map_BarCol["BarCol"] = m_barCol; + const_MCPCaloAssoCol = nullptr; + } - //add MCParticle link - for(int ilink=0; ilink<hit.second[0].getLinkedMCP().size(); ilink++) m_bar->addLinkedMCP( hit.second[0].getLinkedMCP()[ilink] ); + if( m_DataCol.collectionMap_CaloHit.find("ECALEndcaps") != m_DataCol.collectionMap_CaloHit.end() ){ + const edm4hep::MCRecoCaloParticleAssociationCollection* const_MCPCaloAssoCol = map_CaloParticleAssoCol["ECALEndcaps"]->get(); + auto CaloHits = m_DataCol.collectionMap_CaloHit["ECALEndcaps"]; + std::map<std::uint64_t, std::vector<Cyber::CaloUnit> > map_cellID_hits; map_cellID_hits.clear(); + for(auto& hit : CaloHits){ + Cyber::CaloUnit m_bar; + m_bar.setcellID(hit.getCellID()); + m_bar.setPosition( TVector3(hit.getPosition().x, hit.getPosition().y, hit.getPosition().z) ); + m_bar.setQ(hit.getEnergy()/2., hit.getEnergy()/2.); + m_bar.setT(hit.getTime(), hit.getTime()); + + unsigned long long tmp_id = hit.getCellID(); + dd4hep::PlacedVolume ipv = m_volumeManager.lookupVolumePlacement(tmp_id); + dd4hep::Volume ivol = ipv.volume(); + std::vector< double > iVolParam = ivol.solid().dimensions(); + auto maxElement = std::max_element(iVolParam.begin(), iVolParam.end()); + iVolParam.clear(); + m_bar.setBarLength(*maxElement * 20); + + for(int ilink=0; ilink<const_MCPCaloAssoCol->size(); ilink++){ + if( hit == const_MCPCaloAssoCol->at(ilink).getRec() ) m_bar.addLinkedMCP( std::make_pair(const_MCPCaloAssoCol->at(ilink).getSim(), const_MCPCaloAssoCol->at(ilink).getWeight()) ); + } + + + map_cellID_hits[hit.getCellID()].push_back(m_bar); + } + for(auto& hit : map_cellID_hits){ + if(hit.second.size()!=2){ std::cout<<"WARNING: didn't find correct hit pairs! "<<std::endl; continue; } + + //Cyber::CaloUnit* m_bar = new Cyber::CaloUnit(); + std::shared_ptr<Cyber::CaloUnit> m_bar = std::make_shared<Cyber::CaloUnit>(); + + unsigned long long id = hit.first; + m_bar->setcellID( id ); + m_bar->setcellID( map_decoder["ECALEndcaps"]->get(id, "system"), + map_decoder["ECALEndcaps"]->get(id, "module"), + map_decoder["ECALEndcaps"]->get(id, "stave"), + map_decoder["ECALEndcaps"]->get(id, "part"), + map_decoder["ECALEndcaps"]->get(id, "dlayer"), + map_decoder["ECALEndcaps"]->get(id, "slayer"), + map_decoder["ECALEndcaps"]->get(id, "bar")); + m_bar->setPosition(hit.second[0].getPosition()); + m_bar->setBarLength(hit.second[0].getBarLength()); + m_bar->setQ( hit.second[0].getEnergy(), hit.second[1].getEnergy() ); + m_bar->setT( hit.second[0].getT1(), hit.second[1].getT1() ); + + //add MCParticle link + for(int ilink=0; ilink<hit.second[0].getLinkedMCP().size(); ilink++) m_bar->addLinkedMCP( hit.second[0].getLinkedMCP()[ilink] ); + + m_barCol.push_back(m_bar); //Save for later use in algorithms + } - m_barCol.push_back(m_bar); //Save for later use in algorithms + m_DataCol.map_BarCol["BarCol"].insert( m_DataCol.map_BarCol["BarCol"].end(), m_barCol.begin(), m_barCol.end() ); + const_MCPCaloAssoCol = nullptr; } - - - m_DataCol.map_BarCol["BarCol"] = m_barCol; - const_MCPCaloAssoCol = nullptr; } return StatusCode::SUCCESS; }; diff --git a/Reconstruction/RecPFACyber/src/Tools/OutputCreator.cpp b/Reconstruction/RecPFACyber/src/Tools/OutputCreator.cpp index 22531521..3ee25ae3 100644 --- a/Reconstruction/RecPFACyber/src/Tools/OutputCreator.cpp +++ b/Reconstruction/RecPFACyber/src/Tools/OutputCreator.cpp @@ -28,21 +28,25 @@ namespace Cyber{ edm4hep::ClusterCollection* m_Hcalcluster = m_outClusterColHandler["HcalCluster"]->createAndPut(); edm4hep::TrackCollection* m_trkCol = nullptr; - if(settings.map_boolPars.at("UseTruthTrk")) m_trkCol = m_outTrkHandler.createAndPut(); + if(settings.map_boolPars.at("UseTruthTrk") || settings.map_boolPars.at("UseTruthMatchTrk") ) m_trkCol = m_outTrkHandler.createAndPut(); //PFO std::vector<std::shared_ptr<Cyber::PFObject>> p_pfos = m_DataCol.map_PFObjects[settings.map_stringPars.at("OutputPFO")]; /* +cout<<endl; +cout<<"Calibration const: "<<settings.map_floatPars.at("ECALNeutralCalib")<<", "<<settings.map_floatPars.at("ECALChargedCalib")<<", "<<settings.map_floatPars.at("HCALNeutralCalib")<<", "<<settings.map_floatPars.at("HCALChargedCalib")<<endl; std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; double totE_Ecal = 0; double totE_Hcal = 0; for(int i=0; i<p_pfos.size(); i++){ + double ecalcalib = p_pfos[i]->getTracks().size()==0 ? settings.map_floatPars.at("ECALNeutralCalib") : settings.map_floatPars.at("ECALChargedCalib"); + double hcalcalib = p_pfos[i]->getTracks().size()==0 ? settings.map_floatPars.at("HCALNeutralCalib") : settings.map_floatPars.at("HCALChargedCalib"); cout<<" PFO #"<<i<<": track size "<<p_pfos[i]->getTracks().size()<<", leading P "<<p_pfos[i]->getTrackMomentum(); - cout<<", ECAL cluster size "<<p_pfos[i]->getECALClusters().size()<<", totE "<<p_pfos[i]->getECALClusterEnergy(); - cout<<", HCAL cluster size "<<p_pfos[i]->getHCALClusters().size()<<", totE "<<p_pfos[i]->getHCALClusterEnergy()<<endl; - totE_Ecal += p_pfos[i]->getECALClusterEnergy(); - totE_Hcal += p_pfos[i]->getHCALClusterEnergy(); + cout<<", ECAL cluster size "<<p_pfos[i]->getECALClusters().size()<<", totE "<<p_pfos[i]->getECALClusterEnergy()*ecalcalib; + cout<<", HCAL cluster size "<<p_pfos[i]->getHCALClusters().size()<<", totE "<<p_pfos[i]->getHCALClusterEnergy()*hcalcalib<<endl; + totE_Ecal += p_pfos[i]->getECALClusterEnergy()*ecalcalib; + totE_Hcal += p_pfos[i]->getHCALClusterEnergy()*hcalcalib; } cout<<"-----Neutral cluster Ecal total energy: "<<totE_Ecal<<", Hcal total energy: "<<totE_Hcal<<endl; */ @@ -52,6 +56,8 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; std::vector<const Track*> vec_trks = p_pfos[ip]->getTracks(); std::vector<const Calo3DCluster*> vec_Ecalclus = p_pfos[ip]->getECALClusters(); std::vector<const Calo3DCluster*> vec_Hcalclus = p_pfos[ip]->getHCALClusters(); + double ecalcalib = vec_trks.size()==0 ? settings.map_floatPars.at("ECALNeutralCalib") : settings.map_floatPars.at("ECALChargedCalib"); + double hcalcalib = vec_trks.size()==0 ? settings.map_floatPars.at("HCALNeutralCalib") : settings.map_floatPars.at("HCALChargedCalib"); TVector3 vec_Pos(0.,0.,0.); @@ -71,7 +77,7 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; auto _hit = m_calohitCol->create(); _hit.setCellID(_cellID); - _hit.setEnergy( p_hit->getEnergy()*settings.map_floatPars.at("ECALCalib") ); + _hit.setEnergy( p_hit->getEnergy()*ecalcalib ); _hit.setPosition( pos ); _hit.setType(1); //Ecal barrel m_clus.addToHits(_hit); @@ -89,21 +95,21 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; auto _hit = m_corehitCol->create(); _hit.setCellID(_cellID); - _hit.setEnergy( p_core->getEnergy()*settings.map_floatPars.at("ECALCalib") ); + _hit.setEnergy( p_core->getEnergy()*ecalcalib ); _hit.setPosition( pos ); _hit.setType(1); //Ecal barrel m_core.addToHits(_hit); - totE += p_core->getEnergy()*settings.map_floatPars.at("ECALCalib"); + totE += p_core->getEnergy()*ecalcalib; } - double tmp_clusE = p_clus->getEnergy()*settings.map_floatPars.at("ECALCalib"); + double tmp_clusE = p_clus->getLongiE()*ecalcalib; TVector3 clus_pos = p_clus->getShowerCenter(); edm4hep::Vector3f pos( clus_pos.x(), clus_pos.y(), clus_pos.z() ); - double tmp_phi = std::atan2(clus_pos.y(), clus_pos.x())* 180.0 / M_PI; //TODO: use TVector3 to calculate - if (tmp_phi < 0) tmp_phi += 360.0; - double tmp_theta = std::atan2(clus_pos.z(), clus_pos.Perp())* 180.0 / M_PI + 90; - tmp_clusE = m_DataCol.EnergyCorrSvc->energyCorrection(tmp_clusE, tmp_phi, tmp_theta); - totE = m_DataCol.EnergyCorrSvc->energyCorrection(totE, tmp_phi, tmp_theta); + //double tmp_phi = std::atan2(clus_pos.y(), clus_pos.x())* 180.0 / M_PI; //TODO: use TVector3 to calculate + //if (tmp_phi < 0) tmp_phi += 360.0; + //double tmp_theta = std::atan2(clus_pos.z(), clus_pos.Perp())* 180.0 / M_PI + 90; + //tmp_clusE = m_DataCol.EnergyCorrSvc->energyCorrection(tmp_clusE, tmp_phi, tmp_theta); + //totE = m_DataCol.EnergyCorrSvc->energyCorrection(totE, tmp_phi, tmp_theta); m_core.setEnergy(totE); m_core.setPosition( pos ); @@ -131,7 +137,7 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; m_clus.addToHits(_hit); } - double tmp_clusE = p_clus->getHitsE()*settings.map_floatPars.at("HCALCalib"); + double tmp_clusE = p_clus->getHitsE()*hcalcalib; m_clus.setEnergy( tmp_clusE ); edm4hep::Vector3f pos( p_clus->getHitCenter().x(), p_clus->getHitCenter().y(), p_clus->getHitCenter().z() ); m_clus.setPosition( pos ); @@ -162,7 +168,7 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; } if(trkIndex>=0){ auto m_trk = vec_trks[trkIndex]->getOriginTrack(); - if( !m_trk.isAvailable() || settings.map_boolPars.at("UseTruthTrk") ) + if( !m_trk.isAvailable() || settings.map_boolPars.at("UseTruthTrk") || settings.map_boolPars.at("UseTruthMatchTrk")) m_trk = TruthTrack( vec_trks[trkIndex]->getLeadingMCP(), m_trkCol ); m_pfo.addToTracks( m_trk ); @@ -172,6 +178,7 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; edm4hep::Vector3f p3(p3vec.x(), p3vec.y(), p3vec.z()); m_pfo.setMomentum(p3); m_pfo.setEnergy( vec_trks[trkIndex]->getMomentum() ); + m_pfo.setMass(139.57039); //TODO: all charged particles are set to pion mass. } else{ TVector3 p3vec = vec_Pos*( (EcalClusE+HcalClusE)/vec_Pos.Mag() ); @@ -183,7 +190,7 @@ std::cout<<" Input PFO size: "<<p_pfos.size()<<std::endl; } } - +//printf(" Create PFO #%d: charge %.1f, p4 (%.7f, %.7f, %.7f, %.7f), mass %.3f \n", ip, m_pfo.getCharge(), m_pfo.getMomentum().x, m_pfo.getMomentum().y, m_pfo.getMomentum().z, m_pfo.getEnergy(), m_pfo.getMass() ); } /* double totE = 0; @@ -198,7 +205,8 @@ totE = 0; for(int i=0; i<m_pfocol->size(); i++){ auto m_pfo = m_pfocol->at(i); if(m_pfo.getCharge()==0) continue; - cout<<" PFO #"<<i<<": track size "<<m_pfo.tracks_size()<<", cluster size "<<m_pfo.clusters_size()<<", energy "<<m_pfo.getEnergy()<<endl; + cout<<" PFO #"<<i<<": track size "<<m_pfo.tracks_size()<<", leading P "<<sqrt(m_pfo.getMomentum().x*m_pfo.getMomentum().x + m_pfo.getMomentum().y*m_pfo.getMomentum().y + m_pfo.getMomentum().z*m_pfo.getMomentum().z); + cout<<", cluster size "<<m_pfo.clusters_size()<<", energy "<<m_pfo.getEnergy()<<endl; totE += m_pfo.getEnergy(); } cout<<"-----Charged cluster Ecal total energy: "<<totE<<endl; @@ -227,7 +235,7 @@ std::cout<<" Created PFO size: "<<m_pfocol->size()<<std::endl; m_trkst.Z0 = 0; m_trkst.phi = TMath::ATan2(mcp_p.x, mcp_p.x); m_trkst.tanLambda = mcp_p.z / mcp_pT; - m_trkst.omega = 0.3 * settings.map_floatPars.at("BField") / 1000. / mcp_pT; + m_trkst.omega = 0.299792458 * settings.map_floatPars.at("BField") / 1000. / mcp_pT; m_trkst.referencePoint = mcp_vertex; m_track.addToTrackStates(m_trkst); diff --git a/Reconstruction/RecPFACyber/src/Tools/TrackCreator.cpp b/Reconstruction/RecPFACyber/src/Tools/TrackCreator.cpp index 7b09a954..06008654 100644 --- a/Reconstruction/RecPFACyber/src/Tools/TrackCreator.cpp +++ b/Reconstruction/RecPFACyber/src/Tools/TrackCreator.cpp @@ -14,7 +14,7 @@ namespace Cyber{ std::vector<DataHandle<edm4hep::TrackCollection>*>& r_TrackCols, DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection>* r_MCParticleTrkCol ){ - if(r_TrackCols.size()==0 || settings.map_stringVecPars.at("trackCollections").size()==0) StatusCode::SUCCESS; + if(r_TrackCols.size()==0 || settings.map_stringVecPars.at("trackCollections").size()==0) return StatusCode::SUCCESS; //Save readin collections m_DataCol.collectionMap_Track.clear(); @@ -75,14 +75,14 @@ namespace Cyber{ } } - //SelectGoodTrack(m_trkCol); + if(settings.map_boolPars.at("DoCleanTrack")) SelectGoodTrack(m_trkCol); m_DataCol.TrackCol = m_trkCol; - //Track extrapolation // Write settings: geometry description // m_TrkExtraSettings.map_floatPar["Nlayers"] = 28; + if(settings.map_boolPars.at("UseTruthMatchTrk")) m_TrkExtraSettings.map_intPars["Input_track"] = 1; m_TrkExtraAlg = new TrackExtrapolatingAlg(); m_TrkExtraAlg->ReadSettings(m_TrkExtraSettings); m_TrkExtraAlg->Initialize( m_DataCol ); @@ -131,7 +131,7 @@ namespace Cyber{ m_trkst.Kappa = 1 / mcp_pT; if(charge<0) m_trkst.Kappa = -m_trkst.Kappa; m_trkst.tanLambda = mcp_p.Z() / mcp_pT; - m_trkst.Omega = 0.3 * settings.map_floatPars.at("BField") / 1000. / mcp_pT; + m_trkst.Omega = 0.299792458 * settings.map_floatPars.at("BField") / 1000. / mcp_pT; m_trkst.referencePoint = mcp_vertex; m_trkstates.push_back(m_trkst); @@ -157,53 +157,119 @@ namespace Cyber{ StatusCode TrackCreator::SelectGoodTrack(std::vector<std::shared_ptr<Cyber::Track>>& trkCol){ - if(trkCol.size()<2) return StatusCode::SUCCESS; - - for(int itrk=0; itrk<trkCol.size(); itrk++){ - //Endpoint cut - if( fabs( trkCol[itrk]->getEndPoint().z() )<settings.map_floatPars.at("TrkEndZCut") && - trkCol[itrk]->getEndPoint().Perp()>settings.map_floatPars.at("TrkEndRCutMin") && - trkCol[itrk]->getEndPoint().Perp()<settings.map_floatPars.at("TrkEndRCutMax") ){ + //Use truth matched tracks + if(settings.map_boolPars.at("UseTruthMatchTrk")){ - trkCol.erase(trkCol.begin() + itrk); - itrk--; - continue; + std::map<edm4hep::MCParticle, std::vector<std::shared_ptr<Cyber::Track>>> truthMap; + for(int itrk=0; itrk<trkCol.size(); itrk++){ + truthMap[ trkCol[itrk]->getLeadingMCP() ].push_back( trkCol[itrk] ); } - //Start point cut - if( trkCol[itrk]->getStartPoint().Perp()>settings.map_floatPars.at("TrkStartRCutMin") && - trkCol[itrk]->getStartPoint().Perp()<settings.map_floatPars.at("TrkStartRCutMax") ){ + std::vector<std::shared_ptr<Cyber::Track>> tmp_selTrk; tmp_selTrk.clear(); + for(auto iter: truthMap){ + if(iter.second.size()<=0) continue; + int m_index = -1; + double minIP = 999999; + for(int itrk=0; itrk<iter.second.size(); itrk++){ + double tmp_IP = sqrt( iter.second[itrk]->getD0()*iter.second[itrk]->getD0() + iter.second[itrk]->getZ0()*iter.second[itrk]->getZ0() ); + if(tmp_IP<minIP){ + minIP = tmp_IP; + m_index = itrk; + } + } - trkCol.erase(trkCol.begin() + itrk); - itrk--; - continue; + if(m_index>=0) tmp_selTrk.push_back( iter.second[m_index] ); + } + for(int itrk=0; itrk<trkCol.size(); itrk++){ + if( find(tmp_selTrk.begin(), tmp_selTrk.end(), trkCol[itrk])==tmp_selTrk.end() ){ + trkCol.erase(trkCol.begin() + itrk); + itrk--; + } } - //Track length cut - if( (trkCol[itrk]->getEndPoint().Perp()-trkCol[itrk]->getStartPoint().Perp() )<settings.map_floatPars.at("TrkLengthCut") ){ +//cout<<"Matched track size: "<<trkCol.size()<<endl; - trkCol.erase(trkCol.begin() + itrk); - itrk--; - continue; + //Create truth track from linked MC particle + std::vector<std::shared_ptr<Cyber::Track>> truthtrk; + for(int itrk=0; itrk<trkCol.size(); itrk++){ + edm4hep::MCParticle mcp = trkCol[itrk]->getLeadingMCP(); + + std::shared_ptr<Cyber::Track> m_trk = std::make_shared<Cyber::Track>(); + std::vector<Cyber::TrackState> m_trkstates; + + TVector3 mcp_vertex(mcp.getVertex().x, mcp.getVertex().y, mcp.getVertex().z); + TVector3 mcp_p(mcp.getMomentum().x, mcp.getMomentum().y, mcp.getMomentum().z); + double mcp_pT = TMath::Sqrt(mcp_p.X()*mcp_p.X() + mcp_p.Y()*mcp_p.Y()); + double charge = mcp.getCharge(); + + // Evaluate track state at vertex + Cyber::TrackState m_trkst; + m_trkst.location = 1; // At IP + m_trkst.D0 = 0; + m_trkst.Z0 = 0; + m_trkst.phi0 = TMath::ATan2(mcp_p.Y(), mcp_p.X()); + m_trkst.Kappa = 1 / mcp_pT; + if(charge<0) m_trkst.Kappa = -m_trkst.Kappa; + m_trkst.tanLambda = mcp_p.Z() / mcp_pT; + m_trkst.Omega = 0.3 * settings.map_floatPars.at("BField") / 1000. / mcp_pT; + m_trkst.referencePoint = mcp_vertex; + m_trkstates.push_back(m_trkst); + + m_trk->setTrackStates("Input", m_trkstates); + m_trk->setType(0); // It is a "MC track" and not detected by any tracker system + m_trk->addLinkedMCP( std::make_pair(mcp, 1.) ); + truthtrk.push_back(m_trk); } +//cout<<"Created truth track size: "<<truthtrk.size()<<endl; + trkCol = truthtrk; + + std::sort(trkCol.begin(), trkCol.end(), compTrkP); + return StatusCode::SUCCESS; } - if(trkCol.size()<2) return StatusCode::SUCCESS; - - //Remove the broken tracks - std::sort(trkCol.begin(), trkCol.end(), compTrkIP); - for(int itrk=0; itrk<trkCol.size()-1; itrk++){ - for(int jtrk=itrk+1; jtrk<trkCol.size(); jtrk++){ - double deltaP = (trkCol[itrk]->getP3() - trkCol[jtrk]->getP3()).Mag(); - if( trkCol[jtrk]->getP3().Perp() < settings.map_floatPars.at("BrokenTrkMinP") && - ( deltaP/max(trkCol[itrk]->getMomentum(), trkCol[jtrk]->getMomentum()) < settings.map_floatPars.at("BrokenTrkDeltaPCut") || - (trkCol[itrk]->getEndPoint()-trkCol[jtrk]->getStartPoint()).Mag() < settings.map_floatPars.at("BrokenTrkDistance") ) ){ - trkCol.erase(trkCol.begin() + jtrk); - jtrk--; - if(itrk>jtrk+1) itrk--; - } - } + + //Select tracks with some custom criteria + float trk_P, trk_Pt, trk_Nhit, trk_cosT, trk_startR, trk_startZ, trk_endR, trk_endZ, trk_length, trk_IP; + std::ifstream file(settings.map_stringPars.at("TrackIDWeightFile")); + if(!file.good()){ + std::cout << "ERROR: Did not find BDT weight file. Will skip the track cleaning. " << std::endl; + std::sort(trkCol.begin(), trkCol.end(), compTrkP); + return StatusCode::SUCCESS; } + TMVA::Reader *mva_rdr = new TMVA::Reader("Silent"); + mva_rdr->AddVariable("trk_P", &trk_P); + mva_rdr->AddVariable("trk_Pt", &trk_Pt); + mva_rdr->AddVariable("trk_Nhit", &trk_Nhit); + mva_rdr->AddVariable("trk_IP", &trk_IP); + mva_rdr->AddVariable("trk_cosT", &trk_cosT); + mva_rdr->AddVariable("trk_startR", &trk_startR); + mva_rdr->AddVariable("trk_startZ", &trk_startZ); + mva_rdr->AddVariable("trk_endR", &trk_endR); + mva_rdr->AddVariable("trk_endZ", &trk_endZ); + mva_rdr->AddVariable("trk_length", &trk_length); + + mva_rdr->BookMVA(settings.map_stringPars.at("TrackIDMethod"), settings.map_stringPars.at("TrackIDWeightFile")); +//cout<<"Use BDT track cleaning. BDT cut "<<settings.map_floatPars.at("BDTCut")<<endl; + for(int itrk=0; itrk<trkCol.size(); itrk++){ + //float tmp_IP = sqrt( trkCol[itrk]->getD0()*trkCol[itrk]->getD0() + trkCol[itrk]->getZ0()*trkCol[itrk]->getZ0() ); + trk_P = trkCol[itrk]->getMomentum(); + trk_Pt = trkCol[itrk]->getPt(); + trk_Nhit = trkCol[itrk]->getTrackerHits(); + trk_cosT = trkCol[itrk]->getP3().CosTheta(); + trk_startR = trkCol[itrk]->getStartPoint().Perp(); + trk_startZ = trkCol[itrk]->getStartPoint().z(); + trk_endR = trkCol[itrk]->getEndPoint().Perp(); + trk_endZ = trkCol[itrk]->getEndPoint().z(); + trk_length = trkCol[itrk]->getEndPoint().Perp() - trkCol[itrk]->getStartPoint().Perp(); + trk_IP = sqrt(trkCol[itrk]->getD0()*trkCol[itrk]->getD0() + trkCol[itrk]->getZ0()*trkCol[itrk]->getZ0()); + float BDTout = mva_rdr->EvaluateMVA(settings.map_stringPars.at("TrackIDMethod")); +//printf(" In track #%d: P %.3f, Pt %.3f, cosT %.3f, start (%.3f, %.3f), end (%.3f, %.3f), Nhit %.0f, length %.3f, IP %.3f, BDT %.3f \n ", itrk, trk_P, trk_Pt, trk_cosT, trk_startR, trk_startZ, trk_endR, trk_endZ, trk_Nhit, trk_length, trk_IP, BDTout); + if(BDTout<settings.map_floatPars.at("BDTCut")){ + trkCol.erase(trkCol.begin() + itrk); + itrk--; + } + } std::sort(trkCol.begin(), trkCol.end(), compTrkP); + delete mva_rdr; return StatusCode::SUCCESS; } -- GitLab