24 #include "GaudiKernel/ITHistSvc.h"
25 #include "GaudiKernel/MsgStream.h"
26 #include "GaudiKernel/SystemOfUnits.h"
35 m_highestVolume(nullptr),
36 m_extrapolator(
"Trk::Extrapolator/AtlasExtrapolator"),
39 m_materialCollectionValidation(false),
40 m_validationTree(nullptr),
41 m_validationRunTree(nullptr),
42 m_validationTreeFolder(
"/val/EventTreeTG"),
43 m_validationTreeName(
"EventTreeTG"),
44 m_validationTreeDescription(
"Event output of the EnergyLossExtrapolationValidation Algorithm"),
45 m_validationRunTreeFolder(
"/val/RunTreeTG"),
46 m_validationRunTreeName(
"RunTreeTG"),
47 m_validationRunTreeDescription(
"Run stats of the EnergyLossExtrapolationValidation Algorithm"),
57 m_totalRecordedLayers(0),
58 m_avgRecordedLayers(0.),
79 m_collectedLayerForward(0),
80 m_collectedLayerBack(0),
83 m_theCylinders(
nullptr),
88 declareProperty(
"Extrapolator" , m_extrapolator);
89 declareProperty(
"UseMaterialCollection" , m_materialCollectionValidation);
91 declareProperty(
"ValidationTreeName" , m_validationTreeName);
92 declareProperty(
"ValidationRunTreeName" , m_validationRunTreeName);
93 declareProperty(
"ValidationTreeDescription" , m_validationTreeDescription);
94 declareProperty(
"ValidationRunTreeDescription" , m_validationRunTreeDescription);
95 declareProperty(
"ValidationTreeFolder" , m_validationTreeFolder);
96 declareProperty(
"ValidationRunTreeFolder" , m_validationRunTreeFolder);
98 declareProperty(
"StartPerigeeMinEta" , m_minEta);
99 declareProperty(
"StartPerigeeMaxEta" , m_maxEta);
100 declareProperty(
"StartPerigeeUsePt" , m_usePt);
101 declareProperty(
"StartPerigeeMomentum" , m_momentum);
103 declareProperty(
"ValidationCylinders" , m_cylinders);
104 declareProperty(
"ValidationCylinderR" , m_cylinderVR);
105 declareProperty(
"ValidationCylinderZ" , m_cylinderVZ);
106 declareProperty(
"StrictOnionMode" , m_onion);
108 declareProperty(
"ParticleType" , m_particleType);
120 delete m_theCylinders;
133 ATH_MSG_DEBUG(
"initialize() m_materialCollectionValidation = " << m_materialCollectionValidation );
136 if (m_extrapolator.retrieve().isFailure()) {
137 ATH_MSG_FATAL(
"initialize() Could not retrieve Tool " << m_extrapolator <<
". Exiting." );
138 return StatusCode::FAILURE;
142 m_validationTree =
new TTree(m_validationTreeName.c_str(), m_validationTreeDescription.c_str());
143 m_validationRunTree =
new TTree(m_validationRunTreeName.c_str(), m_validationRunTreeDescription.c_str());
146 m_validationTree->Branch(
"Entries", &m_entries,
"entries/i");
147 m_validationTree->Branch(
"Energy", m_energy,
"energy[entries]/F");
148 m_validationTree->Branch(
"EnergyLoss", m_energyLoss,
"eLoss[entries]/F");
149 m_validationTree->Branch(
"tInX0", m_parameterX0,
"tinX0[entries]/F");
150 m_validationTree->Branch(
"Radius", m_radius,
"radius[entries]/F");
151 m_validationTree->Branch(
"PosX", m_positionX,
"posX[entries]/F");
152 m_validationTree->Branch(
"PosY", m_positionY,
"posY[entries]/F");
153 m_validationTree->Branch(
"PosZ", m_positionZ,
"posZ[entries]/F");
154 m_validationTree->Branch(
"Eta", m_parameterEta,
"eta[entries]/F");
155 m_validationTree->Branch(
"Phi", m_parameterPhi,
"phi[entries]/F");
156 m_validationTree->Branch(
"Layer", m_layer,
"layer[entries]/i");
158 m_validationRunTree->Branch(
"Layers", &m_cylinders,
"layers/i");
159 m_validationRunTree->Branch(
"CylR", m_cylinderR,
"cylR[layers]/F");
160 m_validationRunTree->Branch(
"CylZ", m_cylinderZ,
"cylZ[layers]/F");
161 m_validationRunTree->Branch(
"Momentum",&m_momentum,
"momentum/F");
162 m_validationRunTree->Branch(
"UsePt", &m_usePt,
"usePt/O");
163 m_validationRunTree->Branch(
"MinEta", &m_minEta,
"minEta/F");
164 m_validationRunTree->Branch(
"MaxEta", &m_maxEta,
"maxEta/F");
165 m_validationRunTree->Branch(
"PDG", &m_pdg,
"pdg/I");
166 m_validationRunTree->Branch(
"Events", &m_events,
"events/i");
167 m_validationRunTree->Branch(
"AvgRecordedLayers", &m_avgRecordedLayers,
"avgRecLayers/F");
170 SmartIF<ITHistSvc> tHistSvc{service(
"THistSvc")};
172 ATH_MSG_ERROR(
"initialize() Could not find Hist Service -> Switching ValidationMode Off !" );
173 delete m_validationTree; m_validationTree =
nullptr;
174 delete m_validationRunTree; m_validationRunTree =
nullptr;
176 if ((tHistSvc->regTree(m_validationTreeFolder, m_validationTree)).isFailure()
177 || (tHistSvc->regTree(m_validationRunTreeFolder, m_validationRunTree)).isFailure() ) {
178 ATH_MSG_ERROR(
"initialize() Could not register the validation Trees -> Switching ValidationMode Off !" );
179 delete m_validationTree; m_validationTree =
nullptr;
180 delete m_validationRunTree; m_validationRunTree =
nullptr;
185 m_gaussDist =
new Rndm::Numbers(randSvc(), Rndm::Gauss(0.,1.));
186 m_flatDist =
new Rndm::Numbers(randSvc(), Rndm::Flat(0.,1.));
193 ATH_MSG_INFO(
"initialize() cylinder dimensions vector from jobOptions :" );
194 for (
size_t lay=0; lay<m_cylinders+1; ++lay) {
195 ATH_MSG_INFO(
"initialize() m_cylinderVR[" << lay <<
"] = " << m_cylinderVR[lay] <<
"\t ... m_cylinderVZ[" << lay <<
"] = " << m_cylinderVZ[lay] );
198 ATH_MSG_INFO(
"initialize() cylinder dimensions array for algorithm and ROOT tree :" );
199 for (
size_t lay=0; lay<m_cylinders+1; ++lay) {
200 m_cylinderR[lay] = m_cylinderVR[lay] > 0 ? m_cylinderVR[lay] : s_cylInitR[lay];
201 m_cylinderZ[lay] = m_cylinderVZ[lay] > 0 ? m_cylinderVZ[lay] : s_cylInitZ[lay];
207 if (m_onion && lay>0 && (m_cylinderR[lay] < m_cylinderR[lay-1])) {
208 ATH_MSG_WARNING(
"initialize() layer " << lay <<
"dimensions are smaller than those of layer " << lay-1 <<
" - constraining m_cylinders to " << lay-1 );
210 ATH_MSG_INFO(
"initialize() m_cylinderR[" << lay <<
"] = " << m_cylinderR[lay] <<
"\t ... m_cylinderZ[" << lay <<
"] = " << m_cylinderZ[lay] );
214 ATH_MSG_INFO(
"initialize() m_cylinderR[" << lay <<
"] = " << m_cylinderR[lay] <<
"\t ... m_cylinderZ[" << lay <<
"] = " << m_cylinderZ[lay] );
221 for (
size_t lay=0; lay<m_cylinders+1; ++lay) {
223 ATH_MSG_INFO(
"initialize() Cylinder " << lay <<
": " << *m_theCylinders->at(lay) );
224 m_theDiscs1->push_back(
new Trk::DiscSurface(*createTransform(0.,0.,-m_cylinderZ[lay]), 0., m_cylinderR[lay]));
225 ATH_MSG_INFO(
"initialize() Disc1 " << lay <<
": " << *m_theDiscs1->at(lay) );
226 m_theDiscs2->push_back(
new Trk::DiscSurface(*createTransform(0.,0., m_cylinderZ[lay]), 0., m_cylinderR[lay]));
227 ATH_MSG_INFO(
"initialize() Disc2 " << lay <<
": " << *m_theDiscs2->at(lay) );
230 if (m_particleType==0) m_pdg = 999;
231 else if (m_particleType==1) m_pdg = 11;
232 else if (m_particleType==2) m_pdg = 13;
233 else if (m_particleType==3) m_pdg = 211;
234 else if (m_particleType==4) m_pdg = 321;
235 ATH_MSG_INFO(
"initialize() ParticleType = " << m_particleType <<
" ... PDG = " << m_pdg );
238 return StatusCode::SUCCESS;
246 ATH_MSG_INFO(
"finalize() ================== Output Statistics =========================" );
248 ATH_MSG_INFO(
"finalize() = - breaks fwd : " <<
double(m_breaksForward)/
double(m_triesForward)
249 <<
" (" << m_breaksForward <<
"/" << m_triesForward <<
")" );
250 ATH_MSG_INFO(
"finalize() = - breaks bwd : " <<
double(m_breaksBack)/
double(m_triesBack)
251 <<
" (" << m_breaksBack <<
"/" << m_triesBack <<
")" );
252 if (m_materialCollectionValidation){
254 ATH_MSG_INFO(
"finalize() = - layer collected fwd : " << m_collectedLayerForward );
255 ATH_MSG_INFO(
"finalize() = - layer collected bwd : " << m_collectedLayerBack );
257 ATH_MSG_INFO(
"finalize() ==============================================================" );
259 m_avgRecordedLayers = m_events ? (
float)m_totalRecordedLayers / (
float)m_events : 0;
261 if (m_validationRunTree)
262 m_validationRunTree->Fill();
265 return StatusCode::SUCCESS;
272 const EventContext& ctx = Gaudi::Hive::currentContext();
274 if (!m_highestVolume){
282 ATH_MSG_WARNING(
"execute() No highest TrackingVolume / no VolumeBounds ... pretty useless!" );
283 return StatusCode::SUCCESS;
295 m_parameterP[
par] = 0.;
297 m_energyLoss[
par] = 0.;
298 m_parameterX0[
par] = 0.;
300 m_positionX[
par] = 0.;
301 m_positionY[
par] = 0.;
302 m_positionZ[
par] = 0.;
303 m_parameterEta[
par] = 0.;
304 m_parameterPhi[
par] = 0.;
305 m_parameterTheta[
par] = 0.;
312 m_parameterPhi[0] =
M_PI * (2 * m_flatDist->shoot() - 1);
313 m_parameterEta[0] = m_minEta + m_flatDist->shoot()*(m_maxEta-m_minEta);
317 m_parameterP[0] = m_momentum;
320 m_parameterP[0] /=
std::sin(m_parameterTheta[0]);
321 m_parameterQoverP[0] =
charge/m_parameterP[0];
325 double energy1 = sqrt(m_parameterP[0]*m_parameterP[0] +
mass*
mass);
335 m_parameterQoverP[0],
339 ATH_MSG_DEBUG(
"execute() Start Parameters : [phi,eta] = [ " << startParameters.momentum().phi() <<
", " << startParameters.eta() <<
" ]" );
347 if (!m_materialCollectionValidation) {
349 lastParameters = m_extrapolator->extrapolate(
352 *(m_theCylinders->at(0)),
360 const std::vector<const Trk::TrackStateOnSurface*>* collectedMaterial =
361 m_extrapolator->extrapolateM(
364 *(m_theCylinders->at(0)),
370 if (collectedMaterial && !collectedMaterial->empty()) {
374 m_collectedLayerForward += collectedMaterial->size();
376 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosIter = collectedMaterial->begin();
377 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosIterEnd = collectedMaterial->end();
378 for ( ; tsosIter != tsosIterEnd; ++tsosIter) {
379 newX0 += (*tsosIter)->materialEffectsOnTrack() ? (*tsosIter)->materialEffectsOnTrack()->thicknessInX0() : 0;
387 for (
size_t lay = 1; lay<m_cylinders+1; ++lay) {
389 if (!m_onion) newX0 = 0;
393 if (!lastParameters) {
394 ATH_MSG_WARNING(
"execute() Layer " << lay <<
": start parameters for cylinder NOT found - skip event !" );
397 ATH_MSG_VERBOSE(
"execute() Layer " << lay <<
": start parameters for cylinder found: " << *lastParameters );
401 newParameters =
nullptr;
402 if (!m_materialCollectionValidation) {
404 newParameters = m_extrapolator->extrapolate(
406 m_onion ? *lastParameters : startParameters,
407 *(m_theCylinders->at(lay)),
415 const std::vector<const Trk::TrackStateOnSurface*>* collectedMaterial =
416 m_extrapolator->extrapolateM(ctx,
417 m_onion ? *lastParameters : startParameters,
418 *(m_theCylinders->at(lay)),
424 if (collectedMaterial && !collectedMaterial->empty()){
429 m_collectedLayerForward += collectedMaterial->size();
431 m_collectedLayerForward = collectedMaterial->size();
433 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosIter = collectedMaterial->begin();
434 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosIterEnd = collectedMaterial->end();
435 for ( ; tsosIter != tsosIterEnd; ++tsosIter) {
436 newX0 += (*tsosIter)->materialEffectsOnTrack() ? (*tsosIter)->materialEffectsOnTrack()->thicknessInX0() : 0;
444 if (!newParameters) {
446 if (!m_materialCollectionValidation) {
448 newParameters = m_extrapolator->extrapolate(
450 m_onion ? *lastParameters : startParameters,
451 (m_parameterEta[0] < 0) ? *(m_theDiscs1->at(lay))
452 : *(m_theDiscs2->at(lay)),
460 const std::vector<const Trk::TrackStateOnSurface*>* collectedMaterial =
461 m_extrapolator->extrapolateM(ctx,
462 m_onion ? *lastParameters : startParameters,
463 (m_parameterEta[0] < 0) ? *(m_theDiscs1->at(lay)) : *(m_theDiscs2->at(lay)),
469 if (collectedMaterial && !collectedMaterial->empty()){
474 m_collectedLayerForward += collectedMaterial->size();
476 m_collectedLayerForward = collectedMaterial->size();
478 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosIter = collectedMaterial->begin();
479 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosIterEnd = collectedMaterial->end();
480 for ( ; tsosIter != tsosIterEnd; ++tsosIter) {
481 newX0 += (*tsosIter)->materialEffectsOnTrack() ? (*tsosIter)->materialEffectsOnTrack()->thicknessInX0() : 0;
490 if (!newParameters) {
491 ATH_MSG_WARNING(
"execute() Layer " << lay <<
" intersection did not work !" );
494 else if (m_highestVolume && newParameters && !(m_highestVolume->inside(newParameters->
position()))) {
495 ATH_MSG_WARNING(
"execute() Layer " << lay <<
" intersection is outside the known world !" );
502 ATH_MSG_VERBOSE(
"execute() Track Parameters at layer " << lay <<
": " << *newParameters );
503 ATH_MSG_DEBUG(
"execute() Track Parameters at layer " << lay <<
": [r,z] = [ " << newPosition.perp() <<
", " << newPosition.z() );
508 m_parameterPhi[m_entries] = newParameters->parameters()[
Trk::phi];
509 m_parameterEta[m_entries] = newParameters->
momentum().eta();
510 m_parameterTheta[m_entries] = newParameters->parameters()[
Trk::theta];
511 m_parameterP[m_entries] = newParameters->
momentum().mag();
512 m_parameterX0[m_entries] = (
float)newX0;
513 ATH_MSG_DEBUG(
"execute() Layer " << lay <<
": cumulated X0 = " << m_parameterX0[m_entries] );
516 m_energy[m_entries] = sqrt(m_parameterP[m_entries]*m_parameterP[m_entries] +
mass*
mass);
517 m_energyLoss[m_entries] = energy1-m_energy[m_entries];
518 ATH_MSG_DEBUG(
"execute() Layer " << lay <<
": cumulated Energy Loss = " << m_energyLoss[m_entries] );
521 m_layer[m_entries] = lay;
523 m_radius[m_entries] = newPosition.perp();
524 m_positionX[m_entries] = newPosition.x();
525 m_positionY[m_entries] = newPosition.y();
526 m_positionZ[m_entries] = newPosition.z();
530 lastParameters = newParameters;
535 m_totalRecordedLayers += m_entries;
541 if (m_validationTree)
542 m_validationTree->Fill();
545 ATH_MSG_DEBUG(
"execute() deleting DataVector parameters ... " );
547 return StatusCode::SUCCESS;
552 double x,
double y,
double z,
double phi,
double theta,
double alphaZ)
567 Amg::Vector3D surfaceXdirection(surfaceYdirection.cross(surfaceZdirection));
570 surfaceRotation.col(0) = surfaceXdirection;
571 surfaceRotation.col(1) = surfaceYdirection;
572 surfaceRotation.col(2) = surfaceZdirection;
575 return std::make_unique<Amg::Transform3D>(surfaceRotation, surfacePosition);