Skip to content

Commit

Permalink
Edm4hep extension with DriftChamberDigi and DCH digitizer improvement (
Browse files Browse the repository at this point in the history
…#9)

* Moove to the nightlies to have edm4hep::RecIonizationCluster

* Make a new DriftChamberDigi object available by extending edm4hep

* Add cellID to the digitized DCH hits

* [DCHDigitizer] protect against negative distance to wire
  • Loading branch information
BrieucF authored Sep 6, 2023
1 parent 8c09714 commit 12b894e
Show file tree
Hide file tree
Showing 7 changed files with 412 additions and 4 deletions.
39 changes: 37 additions & 2 deletions DCHdigi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
project(DCHdigi)

# Build the extension data model and link it against the upstream model
PODIO_GENERATE_DATAMODEL(extension dataFormatExtension/driftChamberHit.yaml ext_headers ext_sources
UPSTREAM_EDM edm4hep:${EDM4HEP_DATA_DIR}/edm4hep.yaml
IO_BACKEND_HANDLERS ${PODIO_IO_HANDLERS}
OUTPUT_FOLDER ${CMAKE_INSTALL_PREFIX}/extension)
PODIO_ADD_DATAMODEL_CORE_LIB(extension "${ext_headers}" "${ext_sources}"
OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/extension)
target_link_libraries(extension PUBLIC EDM4HEP::edm4hep)
PODIO_ADD_ROOT_IO_DICT(extensionDict extension "${ext_headers}" ${CMAKE_CURRENT_SOURCE_DIR}/extension/src/selection.xml
OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/extension)
PODIO_ADD_SIO_IO_BLOCKS(extension "${ext_headers}" "${ext_sources}")
add_library(extension::extensionDict ALIAS extensionDict)
message(${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
list(APPEND EXTENSION_INSTALL_LIBS extension extensionDict)
install(TARGETS ${EXTENSION_INSTALL_LIBS}
EXPORT ${PROJECT_NAME}Targets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/extension"
COMPONENT dev)

install(FILES
"${PROJECT_BINARY_DIR}/extensionDictDict.rootmap"
DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT dev)

install(FILES
dataFormatExtension/driftChamberHit.yaml
DESTINATION "${CMAKE_INSTALL_DATADIR}/extension" COMPONENT dev)

install(FILES
"${PROJECT_BINARY_DIR}/libextensionDict_rdict.pcm"
DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT dev)

file(GLOB sources
${PROJECT_SOURCE_DIR}/src/*.cpp
)
Expand All @@ -13,13 +46,15 @@ gaudi_add_module(DCHdigi
LINK
Gaudi::GaudiKernel
EDM4HEP::edm4hep
extensionDict
k4FWCore::k4FWCore
DD4hep::DDRec
)

target_include_directories(DCHdigi PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
${CMAKE_INSTALL_PREFIX}/extension
)

set_target_properties(DCHdigi PROPERTIES PUBLIC_HEADER "${headers}")
Expand All @@ -39,5 +74,5 @@ install(TARGETS DCHdigi

install(FILES ${scripts} DESTINATION test)

SET(test_name "test_DCHsimpleDigitizer")
ADD_TEST(NAME t_${test_name} COMMAND k4run test/runDCHsimpleDigitizer.py)
ADD_TEST(NAME "t_DCHsimpleDigitizer" COMMAND k4run test/runDCHsimpleDigitizer.py)
ADD_TEST(NAME "t_DCHsimpleDigitizerExtendedEdm" COMMAND k4run test/runDCHsimpleDigitizerExtendedEdm.py)
22 changes: 22 additions & 0 deletions DCHdigi/dataFormatExtension/driftChamberHit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
options:
# should getters / setters be prefixed with get / set?
getSyntax: True
# should POD members be exposed with getters/setters in classes that have them as members?
exposePODMembers: False
includeSubfolder: True

datatypes:

extension::DriftChamberDigi:
Description: "Drift chamber digitized hit (before tracking)"
Author: "B. Francois, CERN"
Members:
- uint64_t cellID // ID of the wire that created this hit
- float distanceToWire // smeared distance of closest approach between the wire and the hit
- float zPositionAlongWire // smeared z position in the local wire coordinate system
- float time // time of the hit [ns].
- float eDep // energy deposited on the hit [GeV].
- float eDepError // error measured on eDep [GeV].
OneToManyRelations:
- edm4hep::RecIonizationCluster clusters // ionization clusters that were reconstructed in the cell
77 changes: 77 additions & 0 deletions DCHdigi/include/DCHsimpleDigitizerExtendedEdm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#pragma once

// GAUDI
#include "Gaudi/Property.h"
#include "GaudiAlg/GaudiAlgorithm.h"
#include "GaudiKernel/IRndmGenSvc.h"
#include "GaudiKernel/RndmGenerators.h"

// K4FWCORE
#include "k4FWCore/DataHandle.h"
#include "k4Interface/IGeoSvc.h"

// EDM4HEP
#include "edm4hep/SimTrackerHitCollection.h"

// EDM4HEP extension
#include "extension/DriftChamberDigiCollection.h"

// DD4HEP
#include "DD4hep/Detector.h" // for dd4hep::VolumeManager
#include "DDSegmentation/BitFieldCoder.h"

/** @class DCHsimpleDigitizerExtendedEdm
*
* Algorithm for creating digitized drift chamber hits (extension::DriftChamberDigi) from edm4hep::SimTrackerHit.
* You have to specify the expected resolution in z and in xy (distance to the wire). The smearing is applied in the wire reference frame.
*
* @author Brieuc Francois
* @date 2023-03
*
*/

class DCHsimpleDigitizerExtendedEdm : public GaudiAlgorithm {
public:
explicit DCHsimpleDigitizerExtendedEdm(const std::string&, ISvcLocator*);
virtual ~DCHsimpleDigitizerExtendedEdm();
/** Initialize.
* @return status code
*/
virtual StatusCode initialize() final;
/** Execute.
* @return status code
*/
virtual StatusCode execute() final;
/** Finalize.
* @return status code
*/
virtual StatusCode finalize() final;

private:
// Input sim tracker hit collection name
DataHandle<edm4hep::SimTrackerHitCollection> m_input_sim_hits{"inputSimHits", Gaudi::DataHandle::Reader, this};
// Output digitized tracker hit collection name
DataHandle<extension::DriftChamberDigiCollection> m_output_digi_hits{"outputDigiHits", Gaudi::DataHandle::Writer, this};

// Detector readout name
Gaudi::Property<std::string> m_readoutName{this, "readoutName", "CDCHHits", "Name of the detector readout"};
// Pointer to the geometry service
ServiceHandle<IGeoSvc> m_geoSvc;
// Decoder for the cellID
dd4hep::DDSegmentation::BitFieldCoder* m_decoder;
// Volume manager to get the physical cell sensitive volume
dd4hep::VolumeManager m_volman;

// z position resolution in mm
FloatProperty m_z_resolution{this, "zResolution", 1.0,
"Spatial resolution in the z direction (from reading out the wires at both sides) [mm]"};
// xy resolution in mm
FloatProperty m_xy_resolution{this, "xyResolution", 0.1, "Spatial resolution in the xy direction [mm]"};

// Random Number Service
IRndmGenSvc* m_randSvc;
// Gaussian random number generator used for the smearing of the z position
Rndm::Numbers m_gauss_z;
// Gaussian random number generator used for the smearing of the xy position
Rndm::Numbers m_gauss_xy;
};
1 change: 1 addition & 0 deletions DCHdigi/src/DCHsimpleDigitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ StatusCode DCHsimpleDigitizer::execute() {
digiHitGlobalPosition[1] / dd4hep::mm,
digiHitGlobalPosition[2] / dd4hep::mm);
output_digi_hit.setPosition(digiHitGlobalPositionVector);
output_digi_hit.setCellID(cellID);
}
debug() << "Output Digi Hit collection size: " << output_digi_hits->size() << endmsg;
return StatusCode::SUCCESS;
Expand Down
105 changes: 105 additions & 0 deletions DCHdigi/src/DCHsimpleDigitizerExtendedEdm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "DCHsimpleDigitizerExtendedEdm.h"

// DD4hep
#include "DD4hep/Detector.h"
#include "DDRec/Vector3D.h"

// ROOT
#include "Math/Cylindrical3D.h"

DECLARE_COMPONENT(DCHsimpleDigitizerExtendedEdm)

DCHsimpleDigitizerExtendedEdm::DCHsimpleDigitizerExtendedEdm(const std::string& aName, ISvcLocator* aSvcLoc)
: GaudiAlgorithm(aName, aSvcLoc), m_geoSvc("GeoSvc", "DCHsimpleDigitizerExtendedEdm") {
declareProperty("inputSimHits", m_input_sim_hits, "Input sim tracker hit collection name");
declareProperty("outputDigiHits", m_output_digi_hits, "Output digitized tracker hit collection name");
}

DCHsimpleDigitizerExtendedEdm::~DCHsimpleDigitizerExtendedEdm() {}

StatusCode DCHsimpleDigitizerExtendedEdm::initialize() {
// Initialize random services
if (service("RndmGenSvc", m_randSvc).isFailure()) {
error() << "Couldn't get RndmGenSvc!" << endmsg;
return StatusCode::FAILURE;
}
if (m_gauss_z.initialize(m_randSvc, Rndm::Gauss(0., m_z_resolution)).isFailure()) {
error() << "Couldn't initialize RndmGenSvc!" << endmsg;
return StatusCode::FAILURE;
}
if (m_gauss_xy.initialize(m_randSvc, Rndm::Gauss(0., m_xy_resolution)).isFailure()) {
error() << "Couldn't initialize RndmGenSvc!" << endmsg;
return StatusCode::FAILURE;
}

// check if readout exists
if (m_geoSvc->lcdd()->readouts().find(m_readoutName) == m_geoSvc->lcdd()->readouts().end()) {
error() << "Readout <<" << m_readoutName << ">> does not exist." << endmsg;
return StatusCode::FAILURE;
}
// set the cellID decoder
m_decoder = m_geoSvc->lcdd()->readout(m_readoutName).idSpec().decoder();
// retrieve the volume manager
m_volman = m_geoSvc->lcdd()->volumeManager();

return StatusCode::SUCCESS;
}

StatusCode DCHsimpleDigitizerExtendedEdm::execute() {
// Get the input collection with Geant4 hits
const edm4hep::SimTrackerHitCollection* input_sim_hits = m_input_sim_hits.get();
debug() << "Input Sim Hit collection size: " << input_sim_hits->size() << endmsg;

// Digitize the sim hits
extension::DriftChamberDigiCollection* output_digi_hits = m_output_digi_hits.createAndPut();
for (const auto& input_sim_hit : *input_sim_hits) {
auto output_digi_hit = output_digi_hits->create();
// smear the hit position: need to go in the wire local frame to smear in the direction aligned/perpendicular with the wire for z/distanceToWire, taking e.g. stereo angle into account
// retrieve the cell detElement
dd4hep::DDSegmentation::CellID cellID = input_sim_hit.getCellID();
auto cellDetElement = m_volman.lookupDetElement(cellID);
// retrieve the wire (in DD4hep 1.23 there is no easy way to access the volume daughters we have to pass by detElements, in later versions volumes can be used)
const std::string& wireDetElementName =
Form("superLayer_%d_layer_%d_phi_%d_wire", m_decoder->get(cellID, "superLayer"),
m_decoder->get(cellID, "layer"), m_decoder->get(cellID, "phi"));
dd4hep::DetElement wireDetElement = cellDetElement.child(wireDetElementName);
// get the transformation matrix used to place the wire
const auto& wireTransformMatrix = wireDetElement.nominal().worldTransformation();
// Retrieve global position in mm and apply unit transformation (translation matrix is stored in cm)
double simHitGlobalPosition[3] = {input_sim_hit.getPosition().x * dd4hep::mm,
input_sim_hit.getPosition().y * dd4hep::mm,
input_sim_hit.getPosition().z * dd4hep::mm};
double simHitLocalPosition[3] = {0, 0, 0};
// get the simHit coordinate in cm in the wire reference frame to be able to apply smearing of radius perpendicular to the wire
wireTransformMatrix.MasterToLocal(simHitGlobalPosition, simHitLocalPosition);
debug() << "Cell ID string: " << m_decoder->valueString(cellID) << endmsg;
;
debug() << "Global simHit x " << simHitGlobalPosition[0] << " --> Local simHit x " << simHitLocalPosition[0]
<< " in cm" << endmsg;
debug() << "Global simHit y " << simHitGlobalPosition[1] << " --> Local simHit y " << simHitLocalPosition[1]
<< " in cm" << endmsg;
debug() << "Global simHit z " << simHitGlobalPosition[2] << " --> Local simHit z " << simHitLocalPosition[2]
<< " in cm" << endmsg;
// build a vector to easily apply smearing of distance to the wire
dd4hep::rec::Vector3D simHitLocalPositionVector(simHitLocalPosition[0], simHitLocalPosition[1],
simHitLocalPosition[2]);
// get the smeared distance to the wire (cylindrical coordinate as the smearing should be perpendicular to the wire)
debug() << "Original distance to wire: " << simHitLocalPositionVector.rho() << endmsg;
double smearedDistanceToWire = simHitLocalPositionVector.rho() + m_gauss_xy.shoot() * dd4hep::mm;
while(smearedDistanceToWire < 0){
debug() << "Negative smearedDistanceToWire (" << smearedDistanceToWire << ") shooting another random number" << endmsg;
smearedDistanceToWire = simHitLocalPositionVector.rho() + m_gauss_xy.shoot() * dd4hep::mm;
}
debug() << "Smeared distance to wire: " << smearedDistanceToWire << endmsg;
// smear the z position (in local coordinate the z axis is aligned with the wire i.e. it take the stereo angle into account);
double smearedZ = simHitLocalPositionVector.z() + m_gauss_z.shoot() * dd4hep::mm;
// fill the output DriftChamberDigi (making sure we are back in mm)
output_digi_hit.setCellID(cellID);
output_digi_hit.setDistanceToWire(smearedDistanceToWire / dd4hep::mm);
output_digi_hit.setZPositionAlongWire(smearedZ / dd4hep::mm);
}
debug() << "Output Digi Hit collection size: " << output_digi_hits->size() << endmsg;
return StatusCode::SUCCESS;
}

StatusCode DCHsimpleDigitizerExtendedEdm::finalize() { return StatusCode::SUCCESS; }
Loading

0 comments on commit 12b894e

Please sign in to comment.