Skip to content

Commit

Permalink
Add support for reconstruction of "turbine" endcap ecal (#88)
Browse files Browse the repository at this point in the history
* Add support for endcap turbine calorimeter

* Add support for endcap turbine calorimeter

* Add support for endcap turbine calorimeter

* Added endcap turbine positioning tool

* Minor changes (i.e. adding comments, removing commented lines

* Remove segmentation members

* Move most of the code in towersNumber to initialize

* removal of bool member variables and change to interface of retrievePhiThetaExtrema

* removal of bool member variables and change to interface of retrievePhiThetaExtrema

* Changes to support turbine endcal ecal

* Resolve conflicts

* Change GaudiTool to AlgTool

* Remove conflict text

* update test scripts

* remove EventCounter in tests (#105)
Fix conflicts with main branch

* Remove segmentation members

Fix conflicts with main branch

* Changes to support turbine endcal ecal

Fix conflicts with main branch

* update test scripts
Fix conflicts with main branch

---------

Co-authored-by: Erich Varnes <[email protected]>
Co-authored-by: Giovanni Marchiori <[email protected]>
  • Loading branch information
3 people authored Aug 14, 2024
1 parent 423b959 commit aa0ddf6
Show file tree
Hide file tree
Showing 7 changed files with 1,018 additions and 402 deletions.
302 changes: 134 additions & 168 deletions RecFCCeeCalorimeter/src/components/CaloTowerToolFCCee.cpp

Large diffs are not rendered by default.

41 changes: 17 additions & 24 deletions RecFCCeeCalorimeter/src/components/CaloTowerToolFCCee.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@
// from Gaudi
#include "GaudiKernel/AlgTool.h"

// k4geo
#include "detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h"
#include "detectorSegmentations/FCCSWGridPhiTheta_k4geo.h"

// k4FWCore
#include "k4FWCore/DataHandle.h"
#include "k4Interface/ITowerToolThetaModule.h"
class IGeoSvc;

// dd4hep
#include "DDSegmentation/MultiSegmentation.h"

namespace dd4hep {
namespace DDSegmentation {
Expand Down Expand Up @@ -109,7 +104,7 @@ class CaloTowerToolFCCee : public AlgTool, virtual public ITowerToolThetaModule

private:
/// Type of the segmentation
enum class SegmentationType {kWrong, kModuleTheta, kMulti, kPhiTheta};
enum class SegmentationType {kWrong, kModuleTheta, kMulti, kPhiTheta, kEndcapTurbine};
/** Correct way to access the neighbour of the phi tower, taking into account
* the full coverage in phi.
* Full coverage means that first tower in phi, with ID = 0 is a direct
Expand All @@ -121,15 +116,18 @@ class CaloTowerToolFCCee : public AlgTool, virtual public ITowerToolThetaModule
/** This is where the cell info is filled into towers
* @param[in] aTowers Calorimeter towers.
* @param[in] aCells Calorimeter cells collection.
* @param[in] aSegmentation Segmentation of the calorimeter
* @param[in] fillTowerCells If true, make a list of the cells in each tower
*/
void CellsIntoTowers(std::vector<std::vector<float>>& aTowers, const edm4hep::CalorimeterHitCollection* aCells,
dd4hep::DDSegmentation::Segmentation* aSegmentation, SegmentationType aType,
bool fillTowersCells);
/** Check if the readout name exists. If so, it returns the segmentation.
/** Find the maximum phi, theta covered by a readout
* @param[in] aReadoutName Readout name to be checked for maximum phi, theta
* @param[out] phiThetaPair Values of the maximum phi and theta
*/
StatusCode retrievePhiThetaExtrema(std::string aReadoutName, std::pair<double, double> &phiThetaPair);
/** Check if the readout name exists. If so, it returns the segmentation.
* @param[in] aReadoutName Readout name to be retrieved
*/
std::pair<double, double> retrievePhiThetaExtrema(dd4hep::DDSegmentation::Segmentation* aSegmentation, SegmentationType aType);
std::pair<dd4hep::DDSegmentation::Segmentation*, SegmentationType> retrieveSegmentation(std::string aReadoutName);
/// Handle for electromagnetic barrel cells (input collection)
mutable DataHandle<edm4hep::CalorimeterHitCollection> m_ecalBarrelCells{"ecalBarrelCells", Gaudi::DataHandle::Reader, this};
Expand Down Expand Up @@ -168,20 +166,6 @@ class CaloTowerToolFCCee : public AlgTool, virtual public ITowerToolThetaModule
/// Name of the hcal forward calorimeter readout
Gaudi::Property<std::string> m_hcalFwdReadoutName{this, "hcalFwdReadoutName", "",
"name of the hcal fwd readout"};
/// ModuleTheta segmentation of the electromagnetic barrel (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_ecalBarrelSegmentation;
/// ModuleTheta?? segmentation of the ecal endcap calorimeter (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_ecalEndcapSegmentation;
/// ModuleTheta?? segmentation of the ecal forward calorimeter (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_ecalFwdSegmentation;
/// ModuleTheta?? segmentation of the hadronic barrel (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_hcalBarrelSegmentation;
/// ModuleTheta?? segmentation of the hadronic extended barrel (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_hcalExtBarrelSegmentation;
/// ModuleTheta?? segmentation of the hcal endcap calorimeter (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_hcalEndcapSegmentation;
/// ModuleTheta?? segmentation of the hcal forward calorimeter (owned by DD4hep)
dd4hep::DDSegmentation::Segmentation* m_hcalFwdSegmentation;
/// Type of segmentation of the electromagnetic barrel
SegmentationType m_ecalBarrelSegmentationType;
/// Type of segmentation of the ecal endcap calorimeter
Expand All @@ -198,6 +182,15 @@ class CaloTowerToolFCCee : public AlgTool, virtual public ITowerToolThetaModule
SegmentationType m_hcalFwdSegmentationType;
/// decoder: only for barrel
dd4hep::DDSegmentation::BitFieldCoder* m_decoder;
// Set of bools to record whether a proper segmentation was found
bool m_ecalBarrelSegmentationOK;
bool m_ecalEndcapSegmentationOK;
bool m_ecalFwdSegmentationOK;
bool m_hcalBarrelSegmentationOK;
bool m_hcalExtBarrelSegmentationOK;
bool m_hcalEndcapSegmentationOK;
bool m_hcalFwdSegmentationOK;

/// Maximum theta of detector
float m_thetaMax;
/// Maximum phi of the detector
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "CellPositionsECalEndcapTurbineSegTool.h"

// EDM
#include "edm4hep/CalorimeterHitCollection.h"

#include <cmath>

DECLARE_COMPONENT(CellPositionsECalEndcapTurbineSegTool)

CellPositionsECalEndcapTurbineSegTool::CellPositionsECalEndcapTurbineSegTool(const std::string& type, const std::string& name,
const IInterface* parent)
: AlgTool(type, name, parent) {
declareInterface<ICellPositionsTool>(this);
}

StatusCode CellPositionsECalEndcapTurbineSegTool::initialize() {
StatusCode sc = AlgTool::initialize();
if (sc.isFailure()) return sc;
m_geoSvc = service("GeoSvc");
if (!m_geoSvc) {
error() << "Unable to locate Geometry service." << endmsg;
return StatusCode::FAILURE;
}

// get segmentation
m_segmentation = dynamic_cast<dd4hep::DDSegmentation::FCCSWEndcapTurbine_k4geo*>(m_geoSvc->getDetector()->readout(m_readoutName).segmentation().segmentation());
if (m_segmentation == nullptr) {
error() << "There is no endcap turbine segmentation!!!!" << endmsg;
return StatusCode::FAILURE;
}
debug() << "Found endcap turbine segmentation" << endmsg;

// Take readout bitfield decoder from GeoSvc
m_decoder = m_geoSvc->getDetector()->readout(m_readoutName).idSpec().decoder();
m_volman = m_geoSvc->getDetector()->volumeManager();

// check if decoder contains "layer"
std::vector<std::string> fields;
for (uint itField = 0; itField < m_decoder->size(); itField++) {
fields.push_back((*m_decoder)[itField].name());
debug() << "In positioning tool, field is " << (*m_decoder)[itField].name() << endmsg;
}
auto iter = std::find(fields.begin(), fields.end(), "layer");
if (iter == fields.end()) {
error() << "Readout does not contain field: 'layer'" << endmsg;
}

return sc;
}

void CellPositionsECalEndcapTurbineSegTool::getPositions(const edm4hep::CalorimeterHitCollection& aCells,
edm4hep::CalorimeterHitCollection& outputColl) {

debug() << "Input collection size : " << aCells.size() << endmsg;

// Loop through input cell collection, call xyzPosition method for each cell
// and assign position to cloned hit to be saved in outputColl
for (const auto& cell : aCells) {
auto outSeg = CellPositionsECalEndcapTurbineSegTool::xyzPosition(cell.getCellID());
auto edmPos = edm4hep::Vector3f();
edmPos.x = outSeg.x() / dd4hep::mm;
edmPos.y = outSeg.y() / dd4hep::mm;
edmPos.z = outSeg.z() / dd4hep::mm;

auto positionedHit = cell.clone();
positionedHit.setPosition(edmPos);
outputColl.push_back(positionedHit);

// Debug information about cell position
debug() << "Cell energy (GeV) : " << positionedHit.getEnergy() << "\tcellID " << positionedHit.getCellID() << endmsg;
debug() << "Position of cell (mm) : \t" << outSeg.x() / dd4hep::mm << "\t" << outSeg.y() / dd4hep::mm << "\t"
<< outSeg.z() / dd4hep::mm << "\n"
<< endmsg;
}
debug() << "Output positions collection size: " << outputColl.size() << endmsg;
}

dd4hep::Position CellPositionsECalEndcapTurbineSegTool::xyzPosition(const uint64_t& aCellId) const {

dd4hep::Position outSeg;
double radius;

// find position of volume corresponding to first of group of merged cells
debug() << "cellID: " << aCellId << endmsg;
dd4hep::DDSegmentation::CellID volumeId = aCellId;
debug() << "volumeId: " << volumeId << endmsg;
m_decoder->set(volumeId, "rho", 0);
debug() << "volumeId: " << volumeId << endmsg;
m_decoder->set(volumeId, "z", 0);
debug() << "volumeId: " << volumeId << endmsg;
auto detelement = m_volman.lookupDetElement(volumeId);
const auto& transformMatrix = detelement.nominal().worldTransformation();
double outGlobal[3];
double inLocal[] = {0, 0, 0};
transformMatrix.LocalToMaster(inLocal, outGlobal);
debug() << "Position of volume (mm) : \t"
<< outGlobal[0] / dd4hep::mm << "\t"
<< outGlobal[1] / dd4hep::mm << "\t"
<< outGlobal[2] / dd4hep::mm << endmsg;

// get R, phi of volume
radius = std::sqrt(std::pow(outGlobal[0], 2) + std::pow(outGlobal[1], 2));
double phi = std::atan2(outGlobal[1], outGlobal[0]);
debug() << "R (mm), phi of volume : \t" << radius / dd4hep::mm << " , " << phi << endmsg;

// now get offset in theta and in phi from cell ID (due to theta grid + merging in theta/modules)
// the local position is normalised to r_xy=1 so theta is atan(1/z)
dd4hep::DDSegmentation::Vector3D inSeg = m_segmentation->position(aCellId);
debug() << "Local position of cell (mm) : \t"
<< inSeg.x() / dd4hep::mm << "\t"
<< inSeg.y() / dd4hep::mm << "\t"
<< inSeg.z() / dd4hep::mm << endmsg;
outSeg = inSeg;
debug() << "Position of cell (mm) : \t" << outSeg.x() / dd4hep::mm << "\t" << outSeg.y() / dd4hep::mm << "\t"
<< outSeg.z() / dd4hep::mm << "\n"
<< endmsg;

return outSeg;
}

int CellPositionsECalEndcapTurbineSegTool::layerId(const uint64_t& aCellId) {
int layer;
dd4hep::DDSegmentation::CellID cID = aCellId;
layer = m_decoder->get(cID, "layer");
return layer;
}

StatusCode CellPositionsECalEndcapTurbineSegTool::finalize() { return AlgTool::finalize(); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#ifndef RECCALORIMETER_CELLPOSITIONSECALENDCAPTURBINESEGTOOL_H
#define RECCALORIMETER_CELLPOSITIONSECALENDCAPTURBINESEGTOOL_H

// GAUDI
#include "GaudiKernel/AlgTool.h"
#include "GaudiKernel/ServiceHandle.h"

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

// k4geo
#include "detectorCommon/DetUtils_k4geo.h"
#include "detectorSegmentations/FCCSWEndcapTurbine_k4geo.h"

// DD4hep
#include "DD4hep/Readout.h"
#include "DD4hep/Volumes.h"
#include "DDSegmentation/Segmentation.h"
#include "TGeoManager.h"

class IGeoSvc;
namespace DD4hep {
namespace DDSegmentation {
class Segmentation;
}
}

/** @class CellPositionsECalEndcapTurbineSegTool Reconstruction/RecFCCeeCalorimeter/src/components/CellPositionsECalEndcapTurbineSegTool.h
* CellPositionsECalEndcapTurbineSegTool.h
*
* Tool to determine each Calorimeter cell position.
*
* For the FCCee Endcap ECAL, determined from the placed volumes and the FCCSW endcap turbine segmentation.
*
* @author Erich Varnes
*/

class CellPositionsECalEndcapTurbineSegTool : public AlgTool, virtual public ICellPositionsTool {
public:
CellPositionsECalEndcapTurbineSegTool(const std::string& type, const std::string& name, const IInterface* parent);
~CellPositionsECalEndcapTurbineSegTool() = default;

virtual StatusCode initialize() final;

virtual StatusCode finalize() final;

virtual void getPositions(const edm4hep::CalorimeterHitCollection& aCells, edm4hep::CalorimeterHitCollection& outputColl) final;

virtual dd4hep::Position xyzPosition(const uint64_t& aCellId) const final;

virtual int layerId(const uint64_t& aCellId) final;

private:
/// Pointer to the geometry service
SmartIF<IGeoSvc> m_geoSvc;
/// Name of the electromagnetic calorimeter readout
Gaudi::Property<std::string> m_readoutName{this, "readoutName", "ECalEndcapTurbine"};
/// Merged module-theta segmentation
dd4hep::DDSegmentation::FCCSWEndcapTurbine_k4geo* m_segmentation;
/// Cellid decoder
dd4hep::DDSegmentation::BitFieldCoder* m_decoder;
/// Volume manager
dd4hep::VolumeManager m_volman;
};
#endif /* RECCALORIMETER_CELLPOSITIONSECALENDCAPTURBINESEGTOOL_H */
Loading

0 comments on commit aa0ddf6

Please sign in to comment.