8 #include "CoreUtils/ServiceUtil.h" 12 namespace gar_pandora {
15 : m_settings(settings),
17 m_rotation(*pRotation),
18 m_eCalBarrelLayerThickness(0.
f),
19 m_eCalEndCapLayerThickness(0.
f),
20 artCalorimeterHitVector(0)
22 fGeo = gar::providerFrom<geo::GeometryGAr>();
37 if ( (
m_eCalEndCapLayerThickness < std::numeric_limits<float>::epsilon()) || (m_eCalBarrelLayerThickness < std::numeric_limits<float>::epsilon()) )
38 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
53 PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->
CreateECalCaloHits());
55 return pandora::STATUS_CODE_SUCCESS;
73 if (
nullptr == pCaloHit)
76 PandoraApi::CaloHit::Parameters caloHitParameters;
77 caloHitParameters.m_hitType = pandora::ECAL;
78 caloHitParameters.m_isDigital =
false;
83 float absorberCorrection(1.);
113 <<
" caloHitParameters.m_hitType = " << caloHitParameters.m_hitType.Get()
114 <<
" caloHitParameters.m_isDigital = " << caloHitParameters.m_isDigital.Get()
115 <<
" caloHitParameters.m_layer = " << caloHitParameters.m_layer.Get()
116 <<
" caloHitParameters.m_isInOuterSamplingLayer = " << caloHitParameters.m_isInOuterSamplingLayer.Get()
117 <<
" caloHitParameters.m_cellGeometry = " << caloHitParameters.m_cellGeometry.Get()
118 <<
" caloHitParameters.m_expectedDirection = " << caloHitParameters.m_expectedDirection.Get()
119 <<
" caloHitParameters.m_inputEnergy = " << caloHitParameters.m_inputEnergy.Get()
120 <<
" caloHitParameters.m_time = " << caloHitParameters.m_time.Get()
121 <<
" caloHitParameters.m_cellSize0 = " << caloHitParameters.m_cellSize0.Get()
122 <<
" caloHitParameters.m_cellSize1 = " << caloHitParameters.m_cellSize1.Get()
123 <<
" caloHitParameters.m_cellThickness = " << caloHitParameters.m_cellThickness.Get()
124 <<
" caloHitParameters.m_nCellRadiationLengths = " << caloHitParameters.m_nCellRadiationLengths.Get()
125 <<
" caloHitParameters.m_nCellInteractionLengths = " << caloHitParameters.m_nCellInteractionLengths.Get()
126 <<
" caloHitParameters.m_hadronicEnergy = " << caloHitParameters.m_hadronicEnergy.Get()
127 <<
" caloHitParameters.m_mipEquivalentEnergy = " << caloHitParameters.m_mipEquivalentEnergy.Get()
128 <<
" caloHitParameters.m_electromagneticEnergy = " << caloHitParameters.m_electromagneticEnergy.Get();
132 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(
m_pandora, caloHitParameters));
134 catch (pandora::StatusCodeException &statusCodeException)
137 <<
"Failed to extract ecal calo hit: " << statusCodeException.ToString();
142 <<
"Failed to extract ecal calo hit: " << exception.what();
146 return pandora::STATUS_CODE_SUCCESS;
153 const float *pCaloHitPosition(pCaloHit->
Position());
155 const pandora::CartesianVector positionVector( (pCaloHitPosition[0] -
m_origin[0]) *
CLHEP::cm, (pCaloHitPosition[1] -
m_origin[1]) * CLHEP::cm, (pCaloHitPosition[2] -
m_origin[2]) * CLHEP::cm);
158 caloHitParameters.m_cellGeometry = pandora::RECTANGULAR;
159 caloHitParameters.m_positionVector = newPositionVector;
160 caloHitParameters.m_expectedDirection = newPositionVector.GetUnitVector();
161 caloHitParameters.m_pParentAddress = (
void*)pCaloHit;
162 caloHitParameters.m_inputEnergy = pCaloHit->
Energy();
163 caloHitParameters.m_time = pCaloHit->
Time().first;
170 caloHitParameters.m_hitRegion = pandora::ENDCAP;
172 const int physicalLayer(
std::min(static_cast<int>(caloHitParameters.m_layer.Get()), static_cast<int>(layers.size()-1)));
173 caloHitParameters.m_cellSize0 = layers[physicalLayer].cellSize0 *
CLHEP::cm;
174 caloHitParameters.m_cellSize1 = layers[physicalLayer].cellSize1 *
CLHEP::cm;
176 double thickness = (layers[physicalLayer].inner_thickness+layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
177 double nRadLengths = layers[physicalLayer].inner_nRadiationLengths;
178 double nIntLengths = layers[physicalLayer].inner_nInteractionLengths;
179 double layerAbsorberThickness = (layers[physicalLayer].inner_thickness-layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
182 thickness += (layers[physicalLayer-1].outer_thickness -layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
183 nRadLengths += layers[physicalLayer-1].outer_nRadiationLengths;
184 nIntLengths += layers[physicalLayer-1].outer_nInteractionLengths;
185 layerAbsorberThickness += (layers[physicalLayer-1].outer_thickness -layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
188 caloHitParameters.m_cellThickness = thickness;
189 caloHitParameters.m_nCellRadiationLengths = nRadLengths;
190 caloHitParameters.m_nCellInteractionLengths = nIntLengths;
192 if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon())
194 MF_LOG_ERROR(
"CaloHitCreator::GetEndcapCaloHitProperties")
195 <<
"Calo hit has 0 radiation length or interaction length: not creating a Pandora calo hit.";
196 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
199 absorberCorrection = 1.;
200 for (
unsigned int i = 0, iMax = layers.size(); i < iMax; ++i)
202 float absorberThickness((layers[i].inner_thickness - layers[i].sensitive_thickness/2.0 ) *
CLHEP::cm);
205 absorberThickness += (layers[i-1].outer_thickness - layers[i-1].sensitive_thickness/2.0) *
CLHEP::cm;
207 if (absorberThickness < std::numeric_limits<float>::epsilon())
210 if (layerAbsorberThickness > std::numeric_limits<float>::epsilon())
211 absorberCorrection = absorberThickness / layerAbsorberThickness;
216 caloHitParameters.m_cellNormalVector = (pCaloHit->
Position()[0] *
CLHEP::cm > 0) ? pandora::CartesianVector(1, 0, 0) : pandora::CartesianVector(-1, 0, 0);
222 const std::vector<gar::geo::LayeredCalorimeterStruct::Layer> &
layers,
unsigned int barrelSymmetryOrder, PandoraApi::CaloHit::Parameters &caloHitParameters,
FloatVector const& ,
float &absorberCorrection )
const 224 caloHitParameters.m_hitRegion = pandora::BARREL;
226 const int physicalLayer(
std::min(static_cast<int>(caloHitParameters.m_layer.Get()), static_cast<int>(layers.size()-1)));
227 caloHitParameters.m_cellSize0 = layers[physicalLayer].cellSize0 *
CLHEP::cm;
228 caloHitParameters.m_cellSize1 = layers[physicalLayer].cellSize1 *
CLHEP::cm;
230 double thickness = (layers[physicalLayer].inner_thickness+layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
231 double nRadLengths = layers[physicalLayer].inner_nRadiationLengths;
232 double nIntLengths = layers[physicalLayer].inner_nInteractionLengths;
234 double layerAbsorberThickness = (layers[physicalLayer].inner_thickness-layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
236 thickness += (layers[physicalLayer-1].outer_thickness -layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
237 nRadLengths += layers[physicalLayer-1].outer_nRadiationLengths;
238 nIntLengths += layers[physicalLayer-1].outer_nInteractionLengths;
239 layerAbsorberThickness += (layers[physicalLayer-1].outer_thickness -layers[physicalLayer].sensitive_thickness/2.0) *
CLHEP::cm;
242 caloHitParameters.m_cellThickness = thickness;
243 caloHitParameters.m_nCellRadiationLengths = nRadLengths;
244 caloHitParameters.m_nCellInteractionLengths = nIntLengths;
246 if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon())
248 MF_LOG_ERROR(
"CaloHitCreator::GetBarrelCaloHitProperties")
249 <<
"Calo hit has 0 radiation length or interaction length: not creating a Pandora calo hit.";
250 throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER);
253 absorberCorrection = 1.;
254 for (
unsigned int i = 0, iMax = layers.size(); i < iMax; ++i)
256 float absorberThickness((layers[i].inner_thickness - layers[i].sensitive_thickness/2.0 ) *
CLHEP::cm);
259 absorberThickness += (layers[i-1].outer_thickness - layers[i-1].sensitive_thickness/2.0) *
CLHEP::cm;
261 if (absorberThickness < std::numeric_limits<float>::epsilon())
264 if (layerAbsorberThickness > std::numeric_limits<float>::epsilon())
265 absorberCorrection = absorberThickness / layerAbsorberThickness;
270 if (barrelSymmetryOrder > 2)
272 const double phi = atan2( pCaloHit->
Position()[2], pCaloHit->
Position()[1] );
274 MF_LOG_DEBUG(
"CaloHitCreator::GetBarrelCaloHitProperties" )
275 <<
"This hit does not have any cellIDs set, will use phi-direction for normal vector " 278 caloHitParameters.m_cellNormalVector = pandora::CartesianVector(0, std::cos(phi), std::sin(phi));
282 const float *pCaloHitPosition( pCaloHit->
Position() );
283 const float phi = std::atan2( pCaloHitPosition[2], pCaloHitPosition[1] );
284 caloHitParameters.m_cellNormalVector = pandora::CartesianVector(0, std::cos(phi), std::sin(phi));
323 rearDistanceToEdge =
std::max(rearDistance, overlapDistance);
327 return static_cast<int>(
std::min(radialDistanceToEdge, rearDistanceToEdge));
334 const float *pCaloHitPosition(pCaloHit->
Position());
336 if (symmetryOrder <= 2)
337 return std::sqrt((pCaloHitPosition[1] * pCaloHitPosition[1]) + (pCaloHitPosition[2] * pCaloHitPosition[2]) *
CLHEP::cm);
339 float maximumRadius(0.
f);
340 const float twoPi(2.
f *
M_PI);
342 for (
unsigned int i = 0; i < symmetryOrder; ++i)
344 const float phi = phi0 + i * twoPi /
static_cast<float>(symmetryOrder);
345 float radius = pCaloHitPosition[2] * std::cos(phi) + pCaloHitPosition[1] * std::sin(phi);
347 if (radius > maximumRadius)
348 maximumRadius = radius;
362 MF_LOG_WARNING(
"CaloHitCreator::CreateECalCaloHits") <<
" Failed to find ecal hits for label " << label <<
std::endl;
363 return pandora::STATUS_CODE_NOT_FOUND;
366 MF_LOG_DEBUG(
"CaloHitCreator::CreateECalCaloHits") <<
" Found: " << theHits->size() <<
" Hits " <<
std::endl;
368 for (
unsigned int i = 0; i < theHits->size(); ++i)
371 ecalCaloHitVector.push_back(hit);
374 return pandora::STATUS_CODE_SUCCESS;
380 : m_CaloHitCollection(
"" ),
381 m_CaloHitInstanceName(
"" ),
383 m_eCalMipThreshold(0.
f),
385 m_eCalToHadGeVBarrel(1.
f),
386 m_eCalToHadGeVEndCap(1.
f),
387 m_maxECalHitHadronicEnergy(10000.
f),
388 m_nOuterSamplingLayers(3),
389 m_layersFromEdgeMaxRearDistance(250.
f),
390 m_eCalBarrelOuterR(0.
f),
391 m_eCalBarrelOuterZ(0.
f),
392 m_eCalBarrelInnerPhi0(0.
f),
393 m_eCalBarrelOuterPhi0(0.
f),
394 m_eCalBarrelInnerSymmetry(0.
f),
395 m_eCalBarrelOuterSymmetry(8),
396 m_eCalBarrelNormalVector({0.0, 0.0, 1.0}),
397 m_eCalEndCapOuterR(0.
f),
398 m_eCalEndCapOuterZ(0.
f),
399 m_eCalEndCapInnerSymmetryOrder(0),
400 m_eCalEndCapInnerPhiCoordinate(0.
f)
static constexpr double cm
float m_eCalToHadGeVEndCap
The calibration from deposited ECal endcap energy to hadronic energy.
std::vector< art::Ptr< gar::rec::CaloHit > > CalorimeterHitVector
std::string m_CaloHitCollection
The calorimeter hit collection.
std::vector< float > FloatVector
float m_eCalMipThreshold
Threshold for creating calo hits in the ECal, units mip.
void GetBarrelCaloHitProperties(const gar::rec::CaloHit *const pCaloHit, const std::vector< gar::geo::LayeredCalorimeterStruct::Layer > &layers, unsigned int barrelSymmetryOrder, PandoraApi::CaloHit::Parameters &caloHitParameters, FloatVector const &normalVector, float &absorberCorrection) const
raw::CellID_t CellID() const
float m_eCalEndCapOuterR
ECal endcap outer r coordinate.
Handle< PROD > getHandle(SelectorBase const &) const
CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, const RotationTransformation *const pRotation)
std::pair< float, float > Time() const
float m_eCalEndCapOuterZ
ECal endcap outer z coordinate.
std::vector< gar::rec::CaloHit > RawCalorimeterHitVector
float m_eCalToEMGeV
The calibration from deposited ECal energy to EM energy.
#define MF_LOG_ERROR(category)
gar::geo::BitFieldCoder const * m_fieldDecoder
int m_nOuterSamplingLayers
Number of layers from edge for hit to be flagged as an outer layer hit.
float GetMaximumRadius(const gar::rec::CaloHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const
float m_eCalToHadGeVBarrel
The calibration from deposited ECal barrel energy to hadronic energy.
pandora::StatusCode CreateCaloHits(const art::Event &pEvent)
float m_eCalBarrelOuterZ
ECal barrel outer z coordinate.
Helper class for decoding and encoding a bit field of 64bits for convenient declaration.
float m_eCalBarrelOuterPhi0
ECal barrel outer phi0 coordinate.
std::string m_CaloHitInstanceName
The calorimeter hit instance name.
int GetNLayersFromEdge(const gar::rec::CaloHit *const pCaloHit) const
float m_eCalBarrelOuterR
ECal barrel outer r coordinate.
const geo::GeometryCore * fGeo
const Settings m_settings
The calo hit creator settings.
static int max(int a, int b)
CalorimeterHitVector artCalorimeterHitVector
FloatVector m_eCalBarrelNormalVector
ECal barrel normal vector.
Q_EXPORT QTSManip setw(int w)
void GetEndCapCaloHitProperties(const gar::rec::CaloHit *const pCaloHit, const std::vector< gar::geo::LayeredCalorimeterStruct::Layer > &layers, PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const
const RotationTransformation & m_rotation
General GArSoft Utilities.
long64 get(long64 bitfield, size_t index) const
const float * Position() const
unsigned int m_eCalEndCapInnerSymmetryOrder
ECal endcap inner symmetry.
unsigned int m_eCalBarrelOuterSymmetry
ECal barrel outer symmetry order.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
float m_eCalToMip
The calibration from deposited ECal energy to mip.
const pandora::Pandora & m_pandora
Reference to the pandora object to create calo hits.
const std::string GetECALCellIDEncoding() const
void GetCommonCaloHitProperties(const gar::rec::CaloHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const
#define MF_LOG_WARNING(category)
pandora::StatusCode CollectECALCaloHits(const art::Event &pEvent, const std::string &label, const std::string &instanceName, CalorimeterHitVector &ecalCaloHitVector)
float m_layersFromEdgeMaxRearDistance
Maximum number of layers from candidate outer layer hit to rear of detector.
unsigned int m_eCalBarrelInnerSymmetry
ECal barrel inner symmetry order.
float m_eCalBarrelLayerThickness
ECal barrel layer thickness.
float m_eCalEndCapLayerThickness
ECal endcap layer thickness.
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
std::map< gar::geo::LayeredCalorimeterData::LayoutType, std::shared_ptr< gar::geo::LayeredCalorimeterData > > GetECALLayeredCalorimeterData() const
pandora::StatusCode CreateECalCaloHits() const
float m_eCalEndCapInnerPhiCoordinate
ECal endcap inner phi.