diff --git a/Digitisers/SimpleDigi/CMakeLists.txt b/Digitisers/SimpleDigi/CMakeLists.txt index 4e2687bc123eeb14f5b013af3cf0461ec48605db..28c8ea89d61d17c7d123b9d1366e94f49ac7aa29 100644 --- a/Digitisers/SimpleDigi/CMakeLists.txt +++ b/Digitisers/SimpleDigi/CMakeLists.txt @@ -3,6 +3,7 @@ gaudi_add_module(SimpleDigi SOURCES src/PlanarDigiAlg.cpp src/TPCDigiAlg.cpp src/voxel.cpp + src/CylinderDigiAlg.cpp LINK GearSvc EventSeeder TrackSystemSvcLib diff --git a/Digitisers/SimpleDigi/src/CylinderDigiAlg.cpp b/Digitisers/SimpleDigi/src/CylinderDigiAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3c67e60c89c427ce12a7c4bc27561b1b971f120 --- /dev/null +++ b/Digitisers/SimpleDigi/src/CylinderDigiAlg.cpp @@ -0,0 +1,119 @@ +#include "CylinderDigiAlg.h" + +#include "edm4hep/Vector3f.h" + +#include "DD4hep/Detector.h" +#include <DD4hep/Objects.h> +#include "DD4hep/DD4hepUnits.h" +#include "DDRec/Vector3D.h" + +#include "GaudiKernel/INTupleSvc.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/IRndmGen.h" +#include "GaudiKernel/IRndmGenSvc.h" +#include "GaudiKernel/RndmGenerators.h" + +DECLARE_COMPONENT( CylinderDigiAlg ) + +CylinderDigiAlg::CylinderDigiAlg(const std::string& name, ISvcLocator* svcLoc) +: GaudiAlgorithm(name, svcLoc){ + // Input collections + declareProperty("InputSimTrackerHitCollection", m_inputColHdls, "Handle of the Input SimTrackerHit collection"); + + // Output collections + declareProperty("OutputTrackerHitCollection", m_outputColHdls, "Handle of the output TrackerHit collection"); + declareProperty("TrackerHitAssociationCollection", m_assColHdls, "Handle of the Association collection between SimTrackerHit and TrackerHit"); +} + +StatusCode CylinderDigiAlg::initialize(){ + m_geosvc = service<IGeomSvc>("GeomSvc"); + if(!m_geosvc){ + error() << "Failed to get the GeomSvc" << endmsg; + return StatusCode::FAILURE; + } + auto detector = m_geosvc->lcdd(); + if(!detector){ + error() << "Failed to get the Detector from GeomSvc" << endmsg; + return StatusCode::FAILURE; + } + std::string name = m_inputColHdls.objKey(); + debug() << "Readout name: " << name << endmsg; + m_decoder = m_geosvc->getDecoder(name); + if(!m_decoder){ + error() << "Failed to get the decoder. " << endmsg; + return StatusCode::FAILURE; + } + + info() << "CylinderDigiAlg::initialized" << endmsg; + return GaudiAlgorithm::initialize(); +} + + +StatusCode CylinderDigiAlg::execute(){ + auto trkhitVec = m_outputColHdls.createAndPut(); + auto assVec = m_assColHdls.createAndPut(); + + const edm4hep::SimTrackerHitCollection* STHCol = nullptr; + try { + STHCol = m_inputColHdls.get(); + } + catch(GaudiException &e){ + debug() << "Collection " << m_inputColHdls.fullKey() << " is unavailable in event " << m_nEvt << endmsg; + return StatusCode::SUCCESS; + } + if(STHCol->size()==0) return StatusCode::SUCCESS; + debug() << m_inputColHdls.fullKey() << " has SimTrackerHit "<< STHCol->size() << endmsg; + + for(auto simhit : *STHCol){ + auto particle = simhit.getMCParticle(); + if(!particle.isAvailable()) continue; + + auto& mom0 = particle.getMomentum(); + double pt = sqrt(mom0.x*mom0.x+mom0.y*mom0.y); + if(particle.isCreatedInSimulation()&&pt<0.01&&particle.isStopped()) continue; + + auto cellId = simhit.getCellID(); + int system = m_decoder->get(cellId, "system"); + int chamber = m_decoder->get(cellId, "chamber"); + int layer = m_decoder->get(cellId, "layer" ); + auto& pos = simhit.getPosition(); + auto& mom = simhit.getMomentum(); + + double phi = atan2(pos[1], pos[0]); + double r = sqrt(pos[0]*pos[0]+pos[1]*pos[1]); + double dphi = m_resRPhi/r; + phi += randSvc()->generator(Rndm::Gauss(0, dphi))->shoot(); + double smearedX = r*cos(phi); + double smearedY = r*sin(phi); + double smearedZ = pos[2] + randSvc()->generator(Rndm::Gauss(0, m_resZ))->shoot(); + + auto trkHit = trkhitVec->create(); + trkHit.setCellID(cellId); + trkHit.setTime(simhit.getTime()); + trkHit.setEDep(simhit.getEDep()); + trkHit.setPosition (edm4hep::Vector3d(smearedX, smearedY, smearedZ)); + trkHit.setCovMatrix(std::array<float, 6>{m_resRPhi*m_resRPhi/2, 0, m_resRPhi*m_resRPhi/2, 0, 0, m_resZ*m_resZ}); + //trkHit.setType(CEPC::CYLINDER); + trkHit.addToRawHits(simhit.getObjectID()); + debug() << "Hit " << simhit.id() << ": " << pos << " -> " << trkHit.getPosition() << "s:" << system << " c:" << chamber << " l:" << layer + << " pt = " << pt << " " << mom.x << " " << mom.y << " " << mom.z << endmsg; + + auto ass = assVec->create(); + + float weight = 1.0; + + debug() <<" Set relation between " << " sim hit " << simhit.id() << " to tracker hit " << trkHit.id() << " with a weight of " << weight << endmsg; + ass.setSim(simhit); + ass.setRec(trkHit); + ass.setWeight(weight); + } + + m_nEvt++; + + return StatusCode::SUCCESS; +} + +StatusCode CylinderDigiAlg::finalize(){ + info() << "Processed " << m_nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} diff --git a/Digitisers/SimpleDigi/src/CylinderDigiAlg.h b/Digitisers/SimpleDigi/src/CylinderDigiAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..af3ffe2100f8151e0076c7ff4643f369f9f836ab --- /dev/null +++ b/Digitisers/SimpleDigi/src/CylinderDigiAlg.h @@ -0,0 +1,39 @@ +#ifndef CylinderDigiAlg_H +#define CylinderDigiAlg_H + +#include "k4FWCore/DataHandle.h" +#include "GaudiKernel/NTuple.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" + +#include <DDRec/DetectorData.h> +#include "DetInterface/IGeomSvc.h" + +class CylinderDigiAlg : public GaudiAlgorithm{ + public: + + CylinderDigiAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize() ; + virtual StatusCode execute() ; + virtual StatusCode finalize() ; + +protected: + + SmartIF<IGeomSvc> m_geosvc; + dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + + // Input collections + DataHandle<edm4hep::SimTrackerHitCollection> m_inputColHdls{"DriftChamberHitsCollection", Gaudi::DataHandle::Reader, this}; + // Output collections + DataHandle<edm4hep::TrackerHitCollection> m_outputColHdls{"DCTrackerHits", Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> m_assColHdls{"DCTrackerHitAssociationCollection", Gaudi::DataHandle::Writer, this}; + + Gaudi::Property<float> m_resRPhi{this, "ResRPhi", 0.1}; + Gaudi::Property<float> m_resZ {this, "ResZ", 2.828}; + + int m_nEvt=0; +}; +#endif diff --git a/Simulation/DetSimSD/CMakeLists.txt b/Simulation/DetSimSD/CMakeLists.txt index fa8ba9ef3e13d27da31d8c25763278ba795ef47c..210e3639bd4ea751e65e55ba8fc87955dc56fb96 100644 --- a/Simulation/DetSimSD/CMakeLists.txt +++ b/Simulation/DetSimSD/CMakeLists.txt @@ -15,6 +15,7 @@ gaudi_add_module(DetSimSD src/GenericTrackerSensDetTool.cpp src/GenericTrackerSensitiveDetector.cpp + src/TrackerCombineSensitiveDetector.cpp LINK DetSimInterface DetInterface ${DD4hep_COMPONENT_LIBRARIES} diff --git a/Simulation/DetSimSD/src/DriftChamberSensDetTool.cpp b/Simulation/DetSimSD/src/DriftChamberSensDetTool.cpp index 43dfa17828453c1545318eea45c0aec7e271976e..c911d47071bfd1410708fbebc1bd5d3d2501954d 100644 --- a/Simulation/DetSimSD/src/DriftChamberSensDetTool.cpp +++ b/Simulation/DetSimSD/src/DriftChamberSensDetTool.cpp @@ -5,7 +5,7 @@ #include "DD4hep/Detector.h" #include "DriftChamberSensitiveDetector.h" - +#include "TrackerCombineSensitiveDetector.h" DECLARE_COMPONENT(DriftChamberSensDetTool) StatusCode DriftChamberSensDetTool::initialize() { @@ -39,12 +39,19 @@ DriftChamberSensDetTool::createSD(const std::string& name) { G4VSensitiveDetector* sd = nullptr; if (name == "DriftChamber") { - DriftChamberSensitiveDetector* dcsd = new DriftChamberSensitiveDetector(name, *dd4hep_geo); - dcsd->setDedxSimTool(m_dedx_simtool); - - sd = dcsd; + auto sens = dd4hep_geo->sensitiveDetector(name); + if(!sens.combineHits()){ + DriftChamberSensitiveDetector* dcsd = new DriftChamberSensitiveDetector(name, *dd4hep_geo); + dcsd->setDedxSimTool(m_dedx_simtool); + sd = dcsd; + } + else{ + sd = new TrackerCombineSensitiveDetector(name, *dd4hep_geo); + } + } + else{ + warning() << "The SD " << name << " want to use SD for DriftChamber" << endmsg; } - return sd; } diff --git a/Simulation/DetSimSD/src/GenericTrackerSensDetTool.cpp b/Simulation/DetSimSD/src/GenericTrackerSensDetTool.cpp index 480f509aa57c563e90c032aac64abcaca4957a31..edb275a8d76e4d0710368611e916f4c026837e12 100644 --- a/Simulation/DetSimSD/src/GenericTrackerSensDetTool.cpp +++ b/Simulation/DetSimSD/src/GenericTrackerSensDetTool.cpp @@ -5,6 +5,7 @@ #include "DD4hep/Detector.h" #include "GenericTrackerSensitiveDetector.h" +#include "TrackerCombineSensitiveDetector.h" #include "CLHEP/Units/SystemOfUnits.h" @@ -33,8 +34,14 @@ G4VSensitiveDetector* GenericTrackerSensDetTool::createSD(const std::string& nam debug() << "createSD for " << name << endmsg; dd4hep::Detector* dd4hep_geo = m_geosvc->lcdd(); - - G4VSensitiveDetector* sd = new GenericTrackerSensitiveDetector(name, *dd4hep_geo); + auto sens = dd4hep_geo->sensitiveDetector(name); + G4VSensitiveDetector* sd = nullptr; + if(sens.combineHits()){ + sd = new TrackerCombineSensitiveDetector(name, *dd4hep_geo); + } + else{ + sd = new GenericTrackerSensitiveDetector(name, *dd4hep_geo); + } return sd; } diff --git a/Simulation/DetSimSD/src/TrackerCombineSensitiveDetector.cpp b/Simulation/DetSimSD/src/TrackerCombineSensitiveDetector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d53d3b99c915a4428be09f2dfceec72040f7195 --- /dev/null +++ b/Simulation/DetSimSD/src/TrackerCombineSensitiveDetector.cpp @@ -0,0 +1,56 @@ +#include "TrackerCombineSensitiveDetector.h" + +#include "G4Step.hh" +#include "G4VProcess.hh" +#include "G4SDManager.hh" +#include "DD4hep/DD4hepUnits.h" + +TrackerCombineSensitiveDetector::TrackerCombineSensitiveDetector(const std::string& name, + dd4hep::Detector& description) + : DDG4SensitiveDetector(name, description), + m_hc(nullptr){ + G4String CollName = m_sensitive.hitsCollection(); + collectionName.insert(CollName); +} + +void TrackerCombineSensitiveDetector::Initialize(G4HCofThisEvent* HCE){ + userData.e_cut = m_sensitive.energyCutoff(); + + m_hc = new HitCollection(GetName(), collectionName[0]); + int HCID = G4SDManager::GetSDMpointer()->GetCollectionID(m_hc); + HCE->AddHitsCollection( HCID, m_hc ); +} + +G4bool TrackerCombineSensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*){ + dd4hep::sim::Geant4StepHandler h(step); + bool return_code = false; + if ( userData.current == -1 ) userData.start(getCellID(step), step, h.pre); + else if ( !userData.track || userData.current != h.track->GetTrackID() ) { + return_code = userData.extractHit(m_hc) != 0; + userData.start(getCellID(step), step, h.pre); + } + + // ....update ..... + userData.update(step); + + void *prePV = h.volume(h.pre), *postPV = h.volume(h.post); + if ( prePV != postPV ) { + return_code = userData.extractHit(m_hc) != 0; + void* postSD = h.sd(h.post); + if ( 0 != postSD ) { + void* preSD = h.sd(h.pre); + if ( preSD == postSD ) { + // fucd: getCellID(step) for preVolume not postVolume, so should start at next step + //userData.start(getCellID(step), step, h.post); + } + } + } + else if ( userData.track->GetTrackStatus() == fStopAndKill ) { + return_code = userData.extractHit(m_hc) != 0; + } + return return_code; +} + +void TrackerCombineSensitiveDetector::EndOfEvent(G4HCofThisEvent* HCE){ + userData.clear(); +} diff --git a/Simulation/DetSimSD/src/TrackerCombineSensitiveDetector.h b/Simulation/DetSimSD/src/TrackerCombineSensitiveDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..cf0cb844eb64a076d8c39477c94a6fd62f677402 --- /dev/null +++ b/Simulation/DetSimSD/src/TrackerCombineSensitiveDetector.h @@ -0,0 +1,95 @@ +// ********************************************************* +// +// $Id: TrackerCombineSensitiveDetector.hh,v 1.0 2022/03/27 + +#ifndef TrackerCombineSensitiveDetector_h +#define TrackerCombineSensitiveDetector_h + +#include "DetSimSD/DDG4SensitiveDetector.h" +#include "DDG4/Defs.h" + +namespace dd4hep { + namespace sim { + struct TrackerCombine { + Geant4TrackerHit pre; + Geant4TrackerHit post; + G4Track* track; + double e_cut; + int current; + long long int cellID; + TrackerCombine() : pre(), post(), track(0), e_cut(0.0), current(-1), cellID(0) {} + void start(long long int cell, G4Step* step, G4StepPoint* point) { + pre.storePoint(step,point); + current = pre.truth.trackID; + track = step->GetTrack(); + cellID = cell; + post = pre; + //std::cout << "start: " << cellID << " " << pre.position << " current = " << current << std::endl; + } + void update(G4Step* step) { + post.storePoint(step,step->GetPostStepPoint()); + pre.truth.deposit += post.truth.deposit; + //std::cout << "update: " << cellID << " " << post.position << " current = " << current << std::endl; + } + void clear() { + pre.truth.clear(); + current = -1; + track = 0; + } + Geant4TrackerHit* extractHit(DDG4SensitiveDetector::HitCollection* c) { + //std::cout << "create Geant4TrackerHit: " << cellID << " current = " << current << " track = " << track << " de = " << pre.truth.deposit << std::endl; + if ( current == -1 || !track ) { + return 0; + } + else if ( pre.truth.deposit <= e_cut && !Geant4Hit::isGeantino(track) ) { + clear(); + return 0; + } + double rho1 = pre.position.Rho(); + double rho2 = post.position.Rho(); + double rho = 0.5*(rho1+rho2); + Position pos = 0.5 * (pre.position + post.position); + double z = pos.z(); + double r = sqrt(rho*rho+z*z); + Position path = post.position - pre.position; + double angle_O_pre_post = acos(-pre.position.Unit().Dot(path.Unit())); + double angle_O_post_pre = acos(post.position.Unit().Dot(path.Unit())); + double angle_O_P_pre = asin(pre.position.R()*sin(angle_O_pre_post)/r); + if(angle_O_pre_post>dd4hep::halfpi||angle_O_post_pre>dd4hep::halfpi){ + bool backward = angle_O_post_pre>angle_O_pre_post; + double angle_O_P_pre = backward ? dd4hep::pi - asin(pre.position.R()*sin(angle_O_pre_post)/r) : asin(pre.position.R()*sin(angle_O_pre_post)/r); + double pre2P = r/sin(angle_O_pre_post)*sin(angle_O_pre_post+angle_O_P_pre); + pos = pre.position + pre2P*path.Unit(); + } + Momentum mom = 0.5 * (pre.momentum + post.momentum); + Geant4TrackerHit* hit = new Geant4TrackerHit(pre.truth.trackID, + pre.truth.pdgID, + pre.truth.deposit, + pre.truth.time); + hit->cellID = cellID; + hit->position = pos; + hit->momentum = mom; + hit->length = path.R();; + clear(); + c->insert(hit); + return hit; + } + }; + } +} + +class TrackerCombineSensitiveDetector: public DDG4SensitiveDetector { + public: + TrackerCombineSensitiveDetector(const std::string& name, dd4hep::Detector& description); + + void Initialize(G4HCofThisEvent* HCE); + G4bool ProcessHits(G4Step* step, G4TouchableHistory* history); + void EndOfEvent(G4HCofThisEvent* HCE); + + protected: + HitCollection* m_hc = nullptr; + + private: + dd4hep::sim::TrackerCombine userData; +}; +#endif