ATLAS Offline Software
Loading...
Searching...
No Matches
NnClusterizationFactory.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
18
19
20
21#include "GaudiKernel/ITHistSvc.h"
25
26//for position estimate and clustering
34
35//get std::isnan()
36#include <cmath>
37#include <algorithm>
38#include <limits>
39
40namespace {
41 std::pair<int, bool>
42 coerceToIntRange(double v){
43 constexpr double minint = std::numeric_limits<int>::min();
44 constexpr double maxint = std::numeric_limits<int>::max();
45 auto d = std::clamp(v, minint, maxint);
46
47 return {static_cast<int>(d), d != v};
48 }
49}
50
51
52namespace InDet {
53 const std::array<std::regex, NnClusterizationFactory::kNNetworkTypes>
55 std::regex("^NumberParticles(|/|_.*)$"),
56 std::regex("^ImpactPoints([0-9])P(|/|_.*)$"),
57 std::regex("^ImpactPointErrorsX([0-9])(|/|_.*)$"),
58 std::regex("^ImpactPointErrorsY([0-9])(|/|_.*)$"),
59 };
60
62 const std::string& n, const IInterface* p)
63 : AthAlgTool(name, n, p){
64 declareInterface<NnClusterizationFactory>(this);
65 }
66
68 ATH_CHECK(m_chargeDataKey.initialize());
71 if (m_doRunI) {
73 } else {
75 }
76 // =0 means invalid in the following, but later on the values will be decremented by one and they indicate the index in the NN collection
78 m_NNId.clear();
79 m_NNId.resize( kNNetworkTypes -1 ) ;
80 // map networks to element in network collection
81 unsigned int nn_id=0;
82 std::smatch match_result;
83 for(const std::string &nn_name : m_nnOrder) {
84 ++nn_id;
85 for (unsigned int network_i=0; network_i<kNNetworkTypes; ++network_i) {
86 if (std::regex_match( nn_name, match_result, m_nnNames[network_i])) {
87 if (network_i == kNumberParticlesNN) {
88 m_nParticleNNId = nn_id;
89 } else {
90 if (m_nParticleGroup[network_i]>0) {
91 if (m_nParticleGroup[network_i]>=match_result.size()) {
92 ATH_MSG_ERROR("Regex and match group of particle multiplicity do not coincide (groups=" << match_result.size()
93 << " n particle group=" << m_nParticleGroup[network_i]
94 << "; type=" << network_i << ")");
95 }
96 int n_particles=std::stoi( match_result[m_nParticleGroup[network_i]].str());
97 if (n_particles<=0 or static_cast<unsigned int>(n_particles)>m_maxSubClusters) {
98 ATH_MSG_ERROR( "Failed to extract number of clusters the NN is meant for. Got " << match_result[m_nParticleGroup[network_i]].str()
99 << " But this is not in the valid range 1..." << m_maxSubClusters);
100 return StatusCode::FAILURE;
101 }
102 if (static_cast<unsigned int>(n_particles)>=m_NNId[network_i-1].size()) {
103 m_NNId[network_i-1].resize( n_particles );
104 }
105 m_NNId[network_i-1][n_particles-1] = nn_id;
106 } else {
107 if (m_NNId[network_i-1].empty()) {
108 m_NNId[network_i-1].resize(1);
109 }
110 m_NNId[network_i-1][0] = nn_id;
111 }
112 }
113 }
114 }
115 }
116 // check whether the NN IDs are all valid
117 // if valid decrease IDs by 1, because the ID is used as index in the NN collection.
118 if ((m_nParticleNNId==0) or (m_nParticleNNId>=m_nnOrder.size())) {
119 ATH_MSG_ERROR( "No NN specified to estimate the number of particles.");
120 return StatusCode::FAILURE;
121 }
123 ATH_MSG_VERBOSE("Expect NN " << s_nnTypeNames[0] << " at index " << m_nParticleNNId );
124 unsigned int type_i=0;
125 for (std::vector<unsigned int> &nn_id : m_NNId) {
126 ++type_i;
127 if (nn_id.empty()) {
128 ATH_MSG_ERROR( "No " << s_nnTypeNames[type_i] << " specified.");
129 return StatusCode::FAILURE;
130 }
131 if (m_nParticleGroup[type_i-1]>0 and nn_id.size() != m_maxSubClusters) {
132 ATH_MSG_ERROR( "Number of networks of type " << s_nnTypeNames[type_i] << " does match the maximum number of supported sub clusters " << m_maxSubClusters);
133 return StatusCode::FAILURE;
134 }
135 unsigned int n_particles=0;
136 for (unsigned int &a_nn_id : nn_id ) {
137 ++n_particles;
138 if ((a_nn_id==0) or (a_nn_id>m_nnOrder.size())) {
139 ATH_MSG_ERROR( "No " << s_nnTypeNames[type_i] << " specified for " << n_particles);
140 return StatusCode::FAILURE;
141 }
142 --a_nn_id;
143 ATH_MSG_VERBOSE("Expect NN " << s_nnTypeNames[type_i] << " for " << n_particles << " particle(s) at index " << a_nn_id );
144 }
145 }
146 ATH_CHECK( m_readKeyWithoutTrack.initialize( !m_readKeyWithoutTrack.key().empty() ) );
147 ATH_CHECK( m_readKeyWithTrack.initialize( !m_readKeyWithTrack.key().empty() ) );
148 ATH_CHECK( m_readKeyJSON.initialize( !m_readKeyJSON.key().empty() ) );
149 return StatusCode::SUCCESS;
150 }
151
152
153 std::vector<double>
155 const auto vectorSize{calculateVectorDimension(input.useTrackInfo)};
156 const auto invalidValue{std::numeric_limits<double>::quiet_NaN()};
157 std::vector<double> inputData(vectorSize, invalidValue);
158 size_t vectorIndex{0};
159 for (unsigned int u=0;u<m_sizeX;u++){
160 for (unsigned int s=0;s<m_sizeY;s++){
161 inputData[vectorIndex++] = input.matrixOfToT[u][s];
162 }
163 }
164 for (unsigned int s=0;s<m_sizeY;s++){
165 inputData[vectorIndex++] = input.vectorOfPitchesY[s];
166 }
167 inputData[vectorIndex++] = input.ClusterPixLayer;
168 inputData[vectorIndex++] = input.ClusterPixBarrelEC;
169 inputData[vectorIndex++] = input.phi;
170 inputData[vectorIndex++] = input.theta;
171 if (not input.useTrackInfo) inputData[vectorIndex] = input.etaModule;
172 return inputData;
173 }
174
175 std::vector<double>
177 const auto vectorSize{calculateVectorDimension(input.useTrackInfo)};
178 const auto invalidValue{std::numeric_limits<double>::quiet_NaN()};
179 std::vector<double> inputData(vectorSize, invalidValue);
180 size_t vectorIndex{0};
181 for (unsigned int u=0;u<m_sizeX;u++){
182 for (unsigned int s=0;s<m_sizeY;s++){
183 if (m_useToT){
184 inputData[vectorIndex++] = norm_rawToT(input.matrixOfToT[u][s]);
185 } else {
186 inputData[vectorIndex++] = norm_ToT(input.matrixOfToT[u][s]);
187 }
188 }
189 }
190 for (unsigned int s=0;s<m_sizeY;s++){
191 const double rawPitch(input.vectorOfPitchesY[s]);
192 const double normPitch(norm_pitch(rawPitch,m_addIBL));
193 if (std::isnan(normPitch)){
194 ATH_MSG_ERROR("NaN returned from norm_pitch, rawPitch = "<<rawPitch<<" addIBL = "<<m_addIBL);
195 }
196 inputData[vectorIndex++] = normPitch;
197 }
198 inputData[vectorIndex++] = norm_layerNumber(input.ClusterPixLayer);
199 inputData[vectorIndex++] = norm_layerType(input.ClusterPixBarrelEC);
200 if (input.useTrackInfo){
201 inputData[vectorIndex++] = norm_phi(input.phi);
202 inputData[vectorIndex] = norm_theta(input.theta);
203 } else {
204 inputData[vectorIndex++] = norm_phiBS(input.phi);
205 inputData[vectorIndex++] = norm_thetaBS(input.theta);
206 inputData[vectorIndex] = norm_etaModule(input.etaModule);
207 }
208 return inputData;
209 }
210
213 // we know the size to be
214 // - m_sizeX x m_sizeY pixel ToT values
215 // - m_sizeY pitch sizes in y
216 // - 2 values: detector location
217 // - 2 values: track incidence angles
218 // - optional: eta module
219 const auto vecSize{calculateVectorDimension(input.useTrackInfo)};
220 Eigen::VectorXd valuesVector( vecSize );
221 // Fill it!
222 // Variable names here need to match the ones in the configuration...
223 // ...IN THE SAME ORDER!!!
224 // location in eigen matrix object where next element goes
225 int location(0);
226 for (const auto & xvec: input.matrixOfToT){
227 for (const auto & xyElement : xvec){
228 valuesVector[location++] = xyElement;
229 }
230 }
231 for (const auto & pitch : input.vectorOfPitchesY) {
232 valuesVector[location++] = pitch;
233 }
234 valuesVector[location] = input.ClusterPixLayer;
235 location++;
236 valuesVector[location] = input.ClusterPixBarrelEC;
237 location++;
238 valuesVector[location] = input.phi;
239 location++;
240 valuesVector[location] = input.theta;
241 location++;
242 if (!input.useTrackInfo) {
243 valuesVector[location] = input.etaModule;
244 location++;
245 }
246 // We have only one node for now, so we just store things there.
247 // Format for use with lwtnn
248 std::vector<Eigen::VectorXd> vectorOfEigen;
249 vectorOfEigen.push_back(valuesVector);
250 return vectorOfEigen;
251 }
252
253 std::vector<double>
255 Amg::Vector3D & beamSpotPosition) const{
256 double tanl=0;
257 NNinput input( createInput(pCluster,beamSpotPosition,tanl) );
258 if (!input) return {};
259 // If using old TTrainedNetworks, fetch correct ones for the
260 // without-track situation and call them now.
262 const std::vector<double> & inputData=(this->*m_assembleInput)(input);
264 if (!nn_collection.isValid()) {
265 ATH_MSG_FATAL( "Failed to get trained network collection with key " << m_readKeyWithoutTrack.key() );
266 return {};
267 }
268 return estimateNumberOfParticlesTTN(**nn_collection, inputData);
269 }
270 // Otherwise, prepare lwtnn input map and use new networks.
272 return estimateNumberOfParticlesLWTNN(nnInputVector);
273 }
274
275 std::vector<double>
277 const Trk::Surface& pixelSurface,
278 const Trk::TrackParameters& trackParsAtSurface) const{
279 Amg::Vector3D dummyBS(0,0,0);
280 double tanl=0;
281 NNinput input( createInput(pCluster,dummyBS,tanl) );
282
283 if (!input) return {};
284 addTrackInfoToInput(input,pixelSurface,trackParsAtSurface,tanl);
285 std::vector<double> inputData=(this->*m_assembleInput)(input);
286 // If using old TTrainedNetworks, fetch correct ones for the
287 // with-track situation and call them now.
290 if (!nn_collection.isValid()) {
291 ATH_MSG_FATAL( "Failed to get trained network collection with key " << m_readKeyWithoutTrack.key() );
292 return {};
293 }
294 return estimateNumberOfParticlesTTN(**nn_collection, inputData);
295 }
296 // Otherwise, prepare lwtnn input map and use new networks.
298 return estimateNumberOfParticlesLWTNN(nnInputVector);
299 }
300
301 std::vector<double>
303 const std::vector<double>& inputData) const{
304 ATH_MSG_DEBUG("Using TTN number network");
305 std::vector<double> resultNN_TTN{};
306 if (not (m_nParticleNNId < nn_collection.size())){ //note: m_nParticleNNId is unsigned
307 ATH_MSG_FATAL("NnClusterizationFactory::estimateNumberOfParticlesTTN: Index "<<m_nParticleNNId<< "is out of range.");
308 return resultNN_TTN;
309 }
310 auto *const pNetwork = nn_collection[m_nParticleNNId].get();
311 if (not pNetwork){
312 ATH_MSG_FATAL("NnClusterizationFactory::estimateNumberOfParticlesTTN: nullptr returned for TrainedNetwork");
313 return resultNN_TTN;
314 }
315 // dereference unique_ptr<TTrainedNetwork> then call calculateOutput :
316 resultNN_TTN = (*pNetwork.*m_calculateOutput)(inputData);
317 ATH_MSG_VERBOSE(" TTN Prob of n. particles (1): " << resultNN_TTN[0] <<
318 " (2): " << resultNN_TTN[1] <<
319 " (3): " << resultNN_TTN[2]);
320 return resultNN_TTN;
321 }
322
323
324 std::vector<double>
326 std::vector<double> result(3,0.0);//ok as invalid result?
328 if (!lwtnn_collection.isValid()) {
329 ATH_MSG_FATAL( "Failed to get LWTNN network collection with key " << m_readKeyJSON.key() );
330 return result;
331 }
332 if (lwtnn_collection->empty()){
333 ATH_MSG_FATAL( "LWTNN network collection with key " << m_readKeyJSON.key()<<" is empty." );
334 return result;
335 }
336 ATH_MSG_DEBUG("Using lwtnn number network");
337 // Order of output matches order in JSON config in "outputs"
338 // Only 1 node here, simple compute function
339 Eigen::VectorXd discriminant = lwtnn_collection->at(0)->compute(input);
340 const double & num0 = discriminant[0];
341 const double & num1 = discriminant[1];
342 const double & num2 = discriminant[2];
343 // Get normalized predictions
344 const auto inverseSum = 1./(num0+num1+num2);
345 result[0] = num0 * inverseSum;
346 result[1] = num1 * inverseSum;
347 result[2] = num2 * inverseSum;
348 ATH_MSG_VERBOSE(" LWTNN Prob of n. particles (1): " << result[0] <<
349 " (2): " << result[1] <<
350 " (3): " << result[2]);
351 return result;
352 }
353
354
355 std::vector<Amg::Vector2D>
357 Amg::Vector3D & beamSpotPosition,
358 std::vector<Amg::MatrixX> & errors,
359 int numberSubClusters) const{
360 ATH_MSG_VERBOSE(" Starting to estimate positions...");
361 double tanl=0;
362 NNinput input( createInput(pCluster,beamSpotPosition,tanl) );
363 if (!input){
364 return {};
365 }
366 // If using old TTrainedNetworks, fetch correct ones for the
367 // without-track situation and call them now.
369 const std::vector<double> & inputData=(this->*m_assembleInput)(input);
371 if (!nn_collection.isValid()) {
372 ATH_MSG_FATAL( "Failed to get trained network collection with key " << m_readKeyWithoutTrack.key() );
373 return {};
374 }
375 // *(ReadCondHandle<>) returns a pointer rather than a reference ...
376 return estimatePositionsTTN(**nn_collection, inputData,input,pCluster,numberSubClusters,errors);
377 }
378 // Otherwise, prepare lwtnn input map and use new networks.
380 return estimatePositionsLWTNN(nnInputVector,input,pCluster,numberSubClusters,errors);
381 }
382
383
384 std::vector<Amg::Vector2D>
386 const Trk::Surface& pixelSurface,
387 const Trk::TrackParameters& trackParsAtSurface,
388 std::vector<Amg::MatrixX> & errors,
389 int numberSubClusters) const{
390 ATH_MSG_VERBOSE(" Starting to estimate positions...");
391 Amg::Vector3D dummyBS(0,0,0);
392 double tanl=0;
393 NNinput input( createInput(pCluster, dummyBS, tanl) );
394 if (!input) return {};
395 addTrackInfoToInput(input,pixelSurface,trackParsAtSurface,tanl);
396 // If using old TTrainedNetworks, fetch correct ones for the
397 // without-track situation and call them now.
399 std::vector<double> inputData=(this->*m_assembleInput)(input);
401 if (!nn_collection.isValid()) {
402 ATH_MSG_FATAL( "Failed to get trained network collection with key " << m_readKeyWithTrack.key() );
403 return {};
404 }
405 return estimatePositionsTTN(**nn_collection, inputData,input,pCluster,numberSubClusters,errors);
406 }
407 // Otherwise, prepare lwtnn input map and use new networks.
409 return estimatePositionsLWTNN(nnInputVector,input,pCluster,numberSubClusters,errors);
410 }
411
412 std::vector<Amg::Vector2D>
414 const std::vector<double>& inputData,
415 const NNinput& input,
416 const InDet::PixelCluster& pCluster,
417 int numberSubClusters,
418 std::vector<Amg::MatrixX> & errors) const{
419 bool applyRecentering=(!input.useTrackInfo and m_useRecenteringNNWithouTracks) or (input.useTrackInfo and m_useRecenteringNNWithTracks);
420 std::vector<Amg::Vector2D> allPositions{};
421 const auto endNnIdx = nn_collection.size();
422 if (numberSubClusters>0 and static_cast<unsigned int>(numberSubClusters) < m_maxSubClusters) {
423 const auto subClusterIndex = numberSubClusters-1;
424 // get position network id for the given cluster multiplicity then
425 // dereference unique_ptr<TTrainedNetwork> then call calculateOutput :
426 const auto networkIndex = m_NNId[kPositionNN-1].at(subClusterIndex);
427 //TTrainedNetworkCollection inherits from std::vector
428 if (not(networkIndex < endNnIdx)){
429 ATH_MSG_FATAL("estimatePositionsTTN: Requested collection index, "<< networkIndex << " is out of range.");
430 return allPositions;
431 }
432 auto *const pNetwork = nn_collection[networkIndex].get();
433 std::vector<double> position1P = (*pNetwork.*m_calculateOutput)(inputData);
434 std::vector<Amg::Vector2D> myPosition1=getPositionsFromOutput(position1P,input,pCluster);
435 assert( position1P.size() % 2 == 0);
436 for (unsigned int i=0; i<position1P.size()/2 ; ++i) {
437 ATH_MSG_DEBUG(" Original RAW Estimated positions (" << i << ") x: " << back_posX(position1P[0+i*2],applyRecentering) << " y: " << back_posY(position1P[1+i*2]));
438 ATH_MSG_DEBUG(" Original estimated myPositions (" << i << ") x: " << myPosition1[i][Trk::locX] << " y: " << myPosition1[i][Trk::locY]);
439 }
440 std::vector<double> inputDataNew=inputData;
441 inputDataNew.reserve( inputDataNew.size() + numberSubClusters*2);
442 assert( static_cast<unsigned int>(numberSubClusters*2) <= position1P.size() );
443 for (unsigned int i=0; i<static_cast<unsigned int>(numberSubClusters*2); ++i) {
444 inputDataNew.push_back(position1P[i]);
445 }
446 // get error network id for the given cluster multiplicity then
447 // dereference unique_ptr<TTrainedNetwork> then call calculateOutput :
448 const auto xNetworkIndex = m_NNId[kErrorXNN-1].at(subClusterIndex);
449 const auto yNetworkIndex = m_NNId[kErrorYNN-1].at(subClusterIndex);
450 if ((not (xNetworkIndex < endNnIdx)) or (not (yNetworkIndex < endNnIdx))){
451 ATH_MSG_FATAL("estimatePositionsTTN: A requested collection index, "<< xNetworkIndex << " or "<< yNetworkIndex << "is out of range.");
452 return allPositions;
453 }
454 auto *pxNetwork = nn_collection.at(xNetworkIndex).get();
455 auto *pyNetwork = nn_collection.at(yNetworkIndex).get();
456 //call the selected member function of the TTrainedNetwork
457 std::vector<double> errors1PX = (*pxNetwork.*m_calculateOutput)(inputDataNew);
458 std::vector<double> errors1PY = (*pyNetwork.*m_calculateOutput)(inputDataNew);
459 //
460 std::vector<Amg::MatrixX> errorMatrices1;
461 getErrorMatrixFromOutput(errors1PX,errors1PY,errorMatrices1,numberSubClusters);
462 allPositions.reserve( allPositions.size() + myPosition1.size());
463 errors.reserve( errors.size() + myPosition1.size());
464 for (unsigned int i=0;i<myPosition1.size();i++){
465 allPositions.push_back(myPosition1[i]);
466 errors.push_back(errorMatrices1[i]);
467 }
468 }
469 return allPositions;
470 }
471
472
473 std::vector<Amg::Vector2D>
475 NNinput& rawInput,
476 const InDet::PixelCluster& pCluster,
477 int numberSubClusters,
478 std::vector<Amg::MatrixX> & errors) const {
480 if (not lwtnn_collection.isValid()) {
481 ATH_MSG_FATAL( "Failed to get LWTNN network collection with key " << m_readKeyJSON.key() );
482 return {};
483 }
484 if (lwtnn_collection->empty()){
485 ATH_MSG_FATAL( "estimatePositionsLWTNN: LWTNN network collection with key " << m_readKeyJSON.key()<<" is empty." );
486 return {};
487 }
488 // Need to evaluate the correct network once per cluster we're interested in.
489 // Save the output
490 std::vector<double> positionValues{};
491 std::vector<Amg::MatrixX> errorMatrices;
492 errorMatrices.reserve(numberSubClusters);
493 positionValues.reserve(numberSubClusters * 2);
494 std::size_t outputNode(0);
495 for (int cluster = 1; cluster < numberSubClusters+1; cluster++) {
496 // Check that the network is defined.
497 // If not, we are outside an IOV and should fail
498 const auto pNetwork = lwtnn_collection->find(numberSubClusters);
499 const bool validGraph = (pNetwork != lwtnn_collection->end()) and (pNetwork->second != nullptr);
500 if (not validGraph) {
501 std::string infoMsg ="Acceptable numbers of subclusters for the lwtnn collection:\n ";
502 for (const auto & pair: **lwtnn_collection){
503 infoMsg += std::to_string(pair.first) + "\n ";
504 }
505 infoMsg += "\nNumber of subclusters requested : "+ std::to_string(numberSubClusters);
506 ATH_MSG_DEBUG(infoMsg);
507 ATH_MSG_FATAL( "estimatePositionsLWTNN: No lwtnn network found for the number of clusters.\n"
508 <<" If you are outside the valid range for an lwtnn-based configuration, please run with useNNTTrainedNetworks instead.\n Key = "
509 << m_readKeyJSON.key() );
510 return {};
511 }
512 if(numberSubClusters==1) {
513 outputNode = m_outputNodesPos1;
514 } else if(numberSubClusters==2) {
515 outputNode = m_outputNodesPos2[cluster-1];
516 } else if(numberSubClusters==3) {
517 outputNode = m_outputNodesPos3[cluster-1];
518 } else {
519 ATH_MSG_FATAL( "Cannot evaluate LWTNN networks with " << numberSubClusters << " numberSubClusters" );
520 return {};
521 }
522
523 // Order of output matches order in JSON config in "outputs"
524 // "alpha", "mean_x", "mean_y", "prec_x", "prec_y"
525 // Assume here that 1 particle network is in position 1, 2 at 2, and 3 at 3.
526 Eigen::VectorXd position = lwtnn_collection->at(numberSubClusters)->compute(input, {}, outputNode);
527 ATH_MSG_DEBUG("Testing for numberSubClusters " << numberSubClusters << " and cluster " << cluster);
528 for (int i=0; i<position.rows(); i++) {
529 ATH_MSG_DEBUG(" position " << position[i]);
530 }
531 positionValues.push_back(position[1]); //mean_x
532 positionValues.push_back(position[2]); //mean_y
533 // Fill errors.
534 // Values returned by NN are inverse of variance, and we want variances.
535 const float rawRmsX = std::sqrt(1.0/position[3]); //prec_x
536 const float rawRmsY = std::sqrt(1.0/position[4]); //prec_y
537 // Now convert to real space units
538 const double rmsX = correctedRMSX(rawRmsX);
539 const double rmsY = correctedRMSY(rawRmsY, rawInput.vectorOfPitchesY);
540 ATH_MSG_DEBUG(" Estimated RMS errors (1) x: " << rmsX << ", y: " << rmsY);
541 // Fill matrix
542 Amg::MatrixX erm(2,2);
543 erm.setZero();
544 erm(0,0)=rmsX*rmsX;
545 erm(1,1)=rmsY*rmsY;
546 errorMatrices.push_back(erm);
547 }
548 std::vector<Amg::Vector2D> myPositions = getPositionsFromOutput(positionValues,rawInput,pCluster);
549 ATH_MSG_DEBUG(" Estimated myPositions (1) x: " << myPositions[0][Trk::locX] << " y: " << myPositions[0][Trk::locY]);
550 errors=std::move(errorMatrices);
551 return myPositions;
552 }
553
554 double
556 // This gives location in pixels
557 constexpr double pitch = 0.05;
558 const double corrected = posPixels * pitch;
559 return corrected;
560 }
561
562 double
564 std::vector<float>& pitches) const{
565 double p = posPixels + (m_sizeY - 1) * 0.5;
566 double p_Y = -100;
567 double p_center = -100;
568 double p_actual = 0;
569 for (unsigned int i = 0; i < m_sizeY; i++) {
570 if (p >= i and p <= (i + 1)) p_Y = p_actual + (p - i + 0.5) * pitches.at(i);
571 if (i == (m_sizeY - 1) / 2) p_center = p_actual + 0.5 * pitches.at(i);
572 p_actual += pitches.at(i);
573 }
574 return std::abs(p_Y - p_center);
575 }
576
577 void
579 std::vector<double>& outputY,
580 std::vector<Amg::MatrixX>& errorMatrix,
581 int nParticles) const{
582 int sizeOutputX=outputX.size()/nParticles;
583 int sizeOutputY=outputY.size()/nParticles;
584 double minimumX=-errorHalfIntervalX(nParticles);
585 double maximumX=errorHalfIntervalX(nParticles);
586 double minimumY=-errorHalfIntervalY(nParticles);
587 double maximumY=errorHalfIntervalY(nParticles);
588 //X=0...sizeOutput-1
589 //Y=minimum+(maximum-minimum)/sizeOutput*(X+1./2.)
590 errorMatrix.reserve( errorMatrix.size() + nParticles);
591 for (int i=0;i<nParticles;i++){
592 double sumValuesX=0;
593 for (int u=0;u<sizeOutputX;u++){
594 sumValuesX+=outputX[i*sizeOutputX+u];
595 }
596 double sumValuesY=0;
597 for (int u=0;u<sizeOutputY;u++){
598 sumValuesY+=outputY[i*sizeOutputY+u];
599 }
600 ATH_MSG_VERBOSE(" minimumX: " << minimumX << " maximumX: " << maximumX << " sizeOutputX " << sizeOutputX);
601 ATH_MSG_VERBOSE(" minimumY: " << minimumY << " maximumY: " << maximumY << " sizeOutputY " << sizeOutputY);
602 double RMSx=0;
603 for (int u=0;u<sizeOutputX;u++){
604 RMSx+=outputX[i*sizeOutputX+u]/sumValuesX*std::pow(minimumX+(maximumX-minimumX)/(double)(sizeOutputX-2)*(u-1./2.),2);
605 }
606 RMSx=std::sqrt(RMSx);//computed error!
607 ATH_MSG_VERBOSE(" first Iter RMSx: " << RMSx);
608 double intervalErrorX=3*RMSx;
609 //now recompute between -3*RMSx and +3*RMSx
610 int minBinX=(int)(1+(-intervalErrorX-minimumX)/(maximumX-minimumX)*(double)(sizeOutputX-2));
611 int maxBinX=(int)(1+(intervalErrorX-minimumX)/(maximumX-minimumX)*(double)(sizeOutputX-2));
612 if (maxBinX>sizeOutputX-1) maxBinX=sizeOutputX-1;
613 if (minBinX<0) minBinX=0;
614 ATH_MSG_VERBOSE(" minBinX: " << minBinX << " maxBinX: " << maxBinX );
615 RMSx=0;
616 for (int u=minBinX;u<maxBinX+1;u++){
617 RMSx+=outputX[i*sizeOutputX+u]/sumValuesX*std::pow(minimumX+(maximumX-minimumX)/(double)(sizeOutputX-2)*(u-1./2.),2);
618 }
619 RMSx=std::sqrt(RMSx);//computed error!
620 double RMSy=0;
621 for (int u=0;u<sizeOutputY;u++){
622 RMSy+=outputY[i*sizeOutputY+u]/sumValuesY*std::pow(minimumY+(maximumY-minimumY)/(double)(sizeOutputY-2)*(u-1./2.),2);
623 }
624 RMSy=std::sqrt(RMSy);//computed error!
625 ATH_MSG_VERBOSE("first Iter RMSy: " << RMSy );
626 double intervalErrorY=3*RMSy;
627 //now recompute between -3*RMSy and +3*RMSy
628 int minBinY=(int)(1+(-intervalErrorY-minimumY)/(maximumY-minimumY)*(double)(sizeOutputY-2));
629 int maxBinY=(int)(1+(intervalErrorY-minimumY)/(maximumY-minimumY)*(double)(sizeOutputY-2));
630 if (maxBinY>sizeOutputY-1) maxBinY=sizeOutputY-1;
631 if (minBinY<0) minBinY=0;
632 ATH_MSG_VERBOSE("minBinY: " << minBinY << " maxBinY: " << maxBinY );
633 RMSy=0;
634 for (int u=minBinY;u<maxBinY+1;u++){
635 RMSy+=outputY[i*sizeOutputY+u]/sumValuesY*std::pow(minimumY+(maximumY-minimumY)/(double)(sizeOutputY-2)*(u-1./2.),2);
636 }
637 RMSy=std::sqrt(RMSy);//computed error!
638 ATH_MSG_VERBOSE("Computed error, sigma(X) " << RMSx << " sigma(Y) " << RMSy );
639 Amg::MatrixX erm(2,2);
640 erm.setZero();
641 erm(0,0)=RMSx*RMSx;
642 erm(1,1)=RMSy*RMSy;
643 errorMatrix.push_back(erm);
644 }//end nParticles
645 }//getErrorMatrixFromOutput
646
647
648 std::vector<Amg::Vector2D>
650 const NNinput & input,
651 const InDet::PixelCluster& pCluster) const{
652 ATH_MSG_VERBOSE(" Translating output back into a position " );
653 const InDetDD::SiDetectorElement* element=pCluster.detectorElement();//DEFINE
654 const InDetDD::PixelModuleDesign* design
655 (dynamic_cast<const InDetDD::PixelModuleDesign*>(&element->design()));
656 if (not design){
657 ATH_MSG_ERROR("Dynamic cast failed at line "<<__LINE__<<" of NnClusterizationFactory.cxx.");
658 return {};
659 }
660 int numParticles=output.size()/2;
661 int columnWeightedPosition=input.columnWeightedPosition;
662 int rowWeightedPosition=input.rowWeightedPosition;
663 ATH_MSG_VERBOSE(" REF POS columnWeightedPos: " << columnWeightedPosition << " rowWeightedPos: " << rowWeightedPosition );
664 bool applyRecentering=false;
665 if (m_useRecenteringNNWithouTracks and (not input.useTrackInfo)){
666 applyRecentering=true;
667 }
668 if (m_useRecenteringNNWithTracks and input.useTrackInfo){
669 applyRecentering=true;
670 }
671 std::vector<Amg::Vector2D> positions;
672 for (int u=0;u<numParticles;u++){
673 double posXid{};
674 double posYid{};
675 if(m_doRunI){
676 posXid=back_posX(output[2*u],applyRecentering)+rowWeightedPosition;
677 posYid=back_posY(output[2*u+1])+columnWeightedPosition;
678 }else{
679 posXid=output[2*u]+rowWeightedPosition;
680 posYid=output[2*u+1]+columnWeightedPosition;
681 }
682 ATH_MSG_VERBOSE(" N. particle: " << u << " idx posX " << posXid << " posY " << posYid );
683 //ATLASRECTS-7155 : Pixel Charge Calibration needs investigating
684 const auto & [posXid_int, coercedX]=coerceToIntRange(posXid+0.5);
685 const auto & [posYid_int, coercedY]=coerceToIntRange(posYid+0.5);
686 if (coercedX or coercedY){
687 ATH_MSG_WARNING("X or Y position value has been limited in range; original values are (" << posXid<<", "<<posYid<<")");
688 //we cannot skip these values, it seems client code relies on the size of input vector and output vector being the same
689 }
690 ATH_MSG_VERBOSE(" N. particle: " << u << " TO INTEGER idx posX " << posXid_int << " posY " << posYid_int );
691 InDetDD::SiLocalPosition siLocalPositionDiscrete(design->positionFromColumnRow(posYid_int,posXid_int));
692 InDetDD::SiCellId cellIdOfPositionDiscrete=design->cellIdOfPosition(siLocalPositionDiscrete);
693 if ( not cellIdOfPositionDiscrete.isValid()){
694 ATH_MSG_WARNING(" Cell is outside validity region with index Y: " << posYid_int << " and index X: " << posXid_int << ". Not foreseen... " );
695 }
696 InDetDD::SiDiodesParameters diodeParameters = design->parameters(cellIdOfPositionDiscrete);
697 double pitchY = diodeParameters.width().xEta();
698 double pitchX = diodeParameters.width().xPhi();
699 ATH_MSG_VERBOSE(" Translated weighted position : " << siLocalPositionDiscrete.xPhi()
700 << " Translated weighted position : " << siLocalPositionDiscrete.xEta() );
701 //FOR TEST
702 InDetDD::SiLocalPosition siLocalPositionDiscreteOneRowMoreOneColumnMore(design->positionFromColumnRow(posYid_int+1,posXid_int+1));
703 ATH_MSG_VERBOSE(" Translated weighted position +1col +1row phi: " << siLocalPositionDiscreteOneRowMoreOneColumnMore.xPhi()
704 << " Translated weighted position +1col +1row eta: " << siLocalPositionDiscreteOneRowMoreOneColumnMore.xEta() );
705 ATH_MSG_VERBOSE("PitchY: " << pitchY << " pitchX " << pitchX );
706 InDetDD::SiLocalPosition siLocalPositionAdd(pitchY*(posYid-(double)posYid_int),
707 pitchX*(posXid-(double)posXid_int));
708 double lorentzShift=m_pixelLorentzAngleTool->getLorentzShift(element->identifyHash(), Gaudi::Hive::currentContext());
709 if (input.ClusterPixBarrelEC == 0){
710 if (not input.useTrackInfo){
712 } else {
714 }
715 }
716
718 siLocalPosition(siLocalPositionDiscrete.xEta()+pitchY*(posYid-(double)posYid_int),
719 siLocalPositionDiscrete.xPhi()+pitchX*(posXid-(double)posXid_int)+lorentzShift);
720 ATH_MSG_VERBOSE(" Translated final position phi: " << siLocalPosition.xPhi() << " eta: " << siLocalPosition.xEta() );
721 const auto halfWidth{design->width()*0.5};
722 if (siLocalPositionDiscrete.xPhi() > halfWidth){
723 siLocalPosition=InDetDD::SiLocalPosition(siLocalPositionDiscrete.xEta()+pitchY*(posYid-(double)posYid_int),
724 halfWidth-1e-6);
725 ATH_MSG_WARNING(" Corrected out of boundary cluster from x(phi): " << siLocalPositionDiscrete.xPhi()+pitchX*(posXid-(double)posXid_int)
726 << " to: " << halfWidth-1e-6);
727 } else if (siLocalPositionDiscrete.xPhi() < -halfWidth) {
728 siLocalPosition=InDetDD::SiLocalPosition(siLocalPositionDiscrete.xEta()+pitchY*(posYid-(double)posYid_int),
729 -halfWidth+1e-6);
730 ATH_MSG_WARNING(" Corrected out of boundary cluster from x(phi): " << siLocalPositionDiscrete.xPhi()+pitchX*(posXid-(double)posXid_int)
731 << " to: " << -halfWidth+1e-6);
732 }
733 positions.emplace_back(siLocalPosition);
734 }//iterate over all particles
735 return positions;
736 }
737
738
739 void
741 const Trk::Surface& pixelSurface, // pixelSurface = pcot->associatedSurface();
742 const Trk::TrackParameters& trackParsAtSurface,
743 const double tanl) const {
744 input.useTrackInfo=true;
745 Amg::Vector3D particleDir = trackParsAtSurface.momentum().unit();
746 Amg::Vector3D localIntersection = pixelSurface.transform().inverse().linear() * particleDir;
747 localIntersection *= 0.250/cos(localIntersection.theta());
748 float trackDeltaX = (float)localIntersection.x();
749 float trackDeltaY = (float)localIntersection.y();
750 input.theta=std::atan2(trackDeltaY,0.250);
751 input.phi=std::atan2(trackDeltaX,0.250);
752 ATH_MSG_VERBOSE("Angle phi bef Lorentz corr: " << input.phi );
753 input.phi=std::atan(std::tan(input.phi)-tanl);
754 ATH_MSG_VERBOSE(" From track: angle phi: " << input.phi << " theta: " << input.theta );
755 }
756
757
758 NNinput
760 Amg::Vector3D & beamSpotPosition,
761 double & tanl) const{
762 NNinput input;
763 ATH_MSG_VERBOSE(" Starting creating input from cluster " );
764 const InDetDD::SiDetectorElement* element=pCluster.detectorElement();
765 if (not element) {
766 ATH_MSG_ERROR("Could not get detector element");
767 return input;
768 }
769 const AtlasDetectorID* aid = element->getIdHelper();
770 if (not aid){
771 ATH_MSG_ERROR("Could not get ATLASDetectorID");
772 return input;
773 }
774
776 ATH_MSG_ERROR("Could not get PixelID pointer");
777 return input;
778 }
779 const PixelID* pixelIDp=static_cast<const PixelID*>(aid);
780 const PixelID& pixelID = *pixelIDp;
781 const InDetDD::PixelModuleDesign* design
782 (dynamic_cast<const InDetDD::PixelModuleDesign*>(&element->design()));
783 if (not design){
784 ATH_MSG_ERROR("Dynamic cast failed at line "<<__LINE__<<" of NnClusterizationFactory.cxx.");
785 return input;
786 }
788 const PixelChargeCalibCondData *calibData = *calibDataHandle;
789 const std::vector<Identifier>& rdos = pCluster.rdoList();
790 const size_t rdoSize = rdos.size();
791 ATH_MSG_VERBOSE(" Number of RDOs: " << rdoSize );
792 const std::vector<float>& chList = pCluster.chargeList();
793 const std::vector<int>& totList = pCluster.totList();
794 std::vector<float> chListRecreated{};
795 chListRecreated.reserve(rdoSize);
796 ATH_MSG_VERBOSE(" Number of charges: " << chList.size() );
797 std::vector<int>::const_iterator tot = totList.begin();
798 std::vector<Identifier>::const_iterator rdosBegin = rdos.begin();
799 std::vector<Identifier>::const_iterator rdosEnd = rdos.end();
800 std::vector<int> totListRecreated{};
801 totListRecreated.reserve(rdoSize);
802 std::vector<int>::const_iterator totRecreated = totListRecreated.begin();
803 // Recreate both charge list and ToT list to correct for the IBL ToT overflow (and later for small hits):
804 ATH_MSG_VERBOSE("Charge list is not filled ... re-creating it.");
805 IdentifierHash moduleHash = element->identifyHash(); // wafer hash
806
807 for ( ; rdosBegin!= rdosEnd and tot != totList.end(); ++tot, ++rdosBegin, ++totRecreated ){
808 // recreate the charge: should be a method of the calibSvc
809 int tot0 = *tot;
810 Identifier pixid = *rdosBegin;
811 assert( element->identifyHash() == pixelID.wafer_hash(pixelID.wafer_id(pixid)));
812
813 std::array<InDetDD::PixelDiodeTree::CellIndexType,2> diode_idx
815 pixelID.eta_index(pixid));
816 InDetDD::PixelDiodeTree::DiodeProxy si_param ( design->diodeProxyFromIdx(diode_idx));
817 std::uint32_t feValue = design->getFE(si_param);
818 auto diode_type = design->getDiodeType(si_param);
820 && design->numberOfConnectedCells( design->readoutIdOfCell(InDetDD::SiCellId(diode_idx[0],diode_idx[1])))>1) {
822 }
823
824 float charge = calibData->getCharge(diode_type, moduleHash, feValue, tot0);
825 chListRecreated.push_back(charge);
826 totListRecreated.push_back(tot0);
827 }
828 // reset the rdo iterator
829 rdosBegin = rdos.begin();
830 rdosEnd = rdos.end();
831 // and the tot iterator
832 tot = totList.begin();
833 totRecreated = totListRecreated.begin();
834 // Always use recreated charge and ToT lists:
835 std::vector<float>::const_iterator charge = chListRecreated.begin();
836 std::vector<float>::const_iterator chargeEnd = chListRecreated.end();
837 tot = totListRecreated.begin();
838 std::vector<int>::const_iterator totEnd = totListRecreated.end();
839 InDetDD::SiLocalPosition sumOfWeightedPositions(0,0,0);
840 double sumOfTot=0;
841 int rowMin = 999;
842 int rowMax = 0;
843 int colMin = 999;
844 int colMax = 0;
845 for (; (rdosBegin!= rdosEnd) and (charge != chargeEnd) and (tot != totEnd); ++rdosBegin, ++charge, ++tot){
846 Identifier rId = *rdosBegin;
847 int row = pixelID.phi_index(rId);
848 int col = pixelID.eta_index(rId);
849 InDetDD::SiLocalPosition siLocalPosition (design->positionFromColumnRow(col,row));
850 if (not m_useToT){
851 sumOfWeightedPositions += (*charge)*siLocalPosition;
852 sumOfTot += (*charge);
853 } else {
854 sumOfWeightedPositions += ((double)(*tot))*siLocalPosition;
855 sumOfTot += (double)(*tot);
856 }
857 rowMin = std::min(row, rowMin);
858 rowMax = std::max(row, rowMax);
859 colMin = std::min(col, colMin);
860 colMax = std::max(col, colMax);
861
862 }
863 sumOfWeightedPositions /= sumOfTot;
864 //what you want to know is simple:
865 //just the row and column of this average position!
866 InDetDD::SiCellId cellIdWeightedPosition=design->cellIdOfPosition(sumOfWeightedPositions);
867
868 if (!cellIdWeightedPosition.isValid()){
869 ATH_MSG_WARNING(" Weighted position is on invalid CellID." );
870 }
871 int columnWeightedPosition=cellIdWeightedPosition.etaIndex();
872 int rowWeightedPosition=cellIdWeightedPosition.phiIndex();
873 ATH_MSG_VERBOSE(" weighted pos row: " << rowWeightedPosition << " col: " << columnWeightedPosition );
874 int centralIndexX=(m_sizeX-1)/2;
875 int centralIndexY=(m_sizeY-1)/2;
876 if (std::abs(rowWeightedPosition-rowMin)>centralIndexX or
877 std::abs(rowWeightedPosition-rowMax)>centralIndexX){
878 ATH_MSG_VERBOSE(" Cluster too large rowMin" << rowMin << " rowMax " << rowMax << " centralX " << centralIndexX);
879 return input;
880 }
881 if (std::abs(columnWeightedPosition-colMin)>centralIndexY or
882 std::abs(columnWeightedPosition-colMax)>centralIndexY){
883 ATH_MSG_VERBOSE(" Cluster too large colMin" << colMin << " colMax " << colMax << " centralY " << centralIndexY);
884 return input;
885 }
886 input.matrixOfToT.reserve(m_sizeX);
887 for (unsigned int a=0;a<m_sizeX;a++){
888 input.matrixOfToT.emplace_back(m_sizeY, 0.0);
889 }
890 input.vectorOfPitchesY.assign(m_sizeY, 0.4);
891 rdosBegin = rdos.begin();
892 charge = chListRecreated.begin();
893 chargeEnd = chListRecreated.end();
894 tot = totListRecreated.begin();
895 ATH_MSG_VERBOSE(" Putting together the n. " << rdos.size() << " rdos into a matrix." );
896 Identifier pixidentif=pCluster.identify();
897 input.etaModule=(int)pixelID.eta_module(pixidentif);
898 input.ClusterPixLayer=(int)pixelID.layer_disk(pixidentif);
899 input.ClusterPixBarrelEC=(int)pixelID.barrel_ec(pixidentif);
900 for (;( charge != chargeEnd) and (rdosBegin!= rdosEnd); ++rdosBegin, ++charge, ++tot){
901 Identifier rId = *rdosBegin;
902 unsigned int absrow = pixelID.phi_index(rId)-rowWeightedPosition+centralIndexX;
903 unsigned int abscol = pixelID.eta_index(rId)-columnWeightedPosition+centralIndexY;
904 if (absrow > m_sizeX){
905 ATH_MSG_WARNING(" problem with index: " << absrow << " min: " << 0 << " max: " << m_sizeX);
906 return input;
907 }
908 if (abscol > m_sizeY){
909 ATH_MSG_WARNING(" problem with index: " << abscol << " min: " << 0 << " max: " << m_sizeY);
910 return input;
911 }
912 InDetDD::SiCellId cellId = element->cellIdFromIdentifier(*rdosBegin);
913 InDetDD::SiDiodesParameters diodeParameters = design->parameters(cellId);
914 double pitchY = diodeParameters.width().xEta();
915 if (not m_useToT) {
916 input.matrixOfToT[absrow][abscol]=*charge;
917 } else {
918 input.matrixOfToT[absrow][abscol]=(double)(*tot);
919 // in case to RunI setup to make IBL studies
920 if(m_doRunI){
921 if (m_addIBL and (input.ClusterPixLayer==0) and (input.ClusterPixBarrelEC==0)){
922 input.matrixOfToT[absrow][abscol]*=3;
923 }
924 }else{
925 // for RunII IBL is always present
926 if ( (input.ClusterPixLayer==0) and (input.ClusterPixBarrelEC==0)){
927 input.matrixOfToT[absrow][abscol]*=3;
928 }
929 }
930
931 }
932 if (std::abs(pitchY-0.4)>1e-5){
933 input.vectorOfPitchesY[abscol]=pitchY;
934 }
935 }//end iteration on rdos
936 ATH_MSG_VERBOSE(" eta module: " << input.etaModule );
937 ATH_MSG_VERBOSE(" Layer number: " << input.ClusterPixLayer << " Barrel / endcap: " << input.ClusterPixBarrelEC );
938 input.useTrackInfo=false;
939 const Amg::Vector2D& prdLocPos = pCluster.localPosition();
940 InDetDD::SiLocalPosition centroid(prdLocPos);
941 Amg::Vector3D globalPos = element->globalPosition(centroid);
942 Amg::Vector3D my_track = globalPos-beamSpotPosition;
943 const Amg::Vector3D &my_normal = element->normal();
944 const Amg::Vector3D &my_phiax = element->phiAxis();
945 const Amg::Vector3D &my_etaax = element->etaAxis();
946 float trkphicomp = my_track.dot(my_phiax);
947 float trketacomp = my_track.dot(my_etaax);
948 float trknormcomp = my_track.dot(my_normal);
949 double bowphi = std::atan2(trkphicomp,trknormcomp);
950 double boweta = std::atan2(trketacomp,trknormcomp);
951 tanl = m_pixelLorentzAngleTool->getTanLorentzAngle(element->identifyHash(), Gaudi::Hive::currentContext());
952 if(bowphi > M_PI_2) bowphi -= M_PI;
953 if(bowphi < -M_PI_2) bowphi += M_PI;
954 int readoutside = design->readoutSide();
955 double angle = std::atan(std::tan(bowphi)-readoutside*tanl);
956 input.phi=angle;
957 ATH_MSG_VERBOSE(" Angle theta bef corr: " << boweta );
958 if (boweta>M_PI_2) boweta-=M_PI;
959 if (boweta<-M_PI_2) boweta+=M_PI;
960 input.theta=boweta;
961 ATH_MSG_VERBOSE(" Angle phi: " << angle << " theta: " << boweta );
962 input.rowWeightedPosition=rowWeightedPosition;
963 input.columnWeightedPosition=columnWeightedPosition;
964 ATH_MSG_VERBOSE(" RowWeightedPosition: " << rowWeightedPosition << " ColWeightedPosition: " << columnWeightedPosition );
965 return input;
966 }//end create NNinput function
967
968 size_t
970 return (m_sizeX * m_sizeY) + m_sizeY + (useTrackInfo ? 4 : 5);
971 }
972}//end InDet namespace
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
static Double_t a
double norm_rawToT(const double input)
double norm_pitch(const double input, bool addIBL=false)
double errorHalfIntervalY(const int nParticles)
double norm_layerNumber(const double input)
double norm_thetaBS(const double input)
double norm_layerType(const double input)
double norm_ToT(const double input)
double back_posX(const double input, const bool recenter=false)
double back_posY(const double input)
double norm_phi(const double input)
double norm_phiBS(const double input)
double norm_theta(const double input)
double norm_etaModule(const double input)
double errorHalfIntervalX(const int nParticles)
This is an Identifier helper class for the Pixel subdetector.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
static const Attributes_t empty
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
virtual HelperType helper() const
Type of helper, defaulted to 'Unimplemented'.
This is a "hash" representation of an Identifier.
int readoutSide() const
ReadoutSide.
static constexpr std::array< PixelDiodeTree::CellIndexType, 2 > makeCellIndex(T local_x_idx, T local_y_idx)
Create a 2D cell index from the indices in local-x (phi, row) and local-y (eta, column) direction.
Class used to describe the design of a module (diode segmentation and readout scheme)
virtual SiDiodesParameters parameters(const SiCellId &cellId) const
readout or diode id -> position, size
virtual int numberOfConnectedCells(const SiReadoutCellId &readoutId) const
readout id -> id of connected diodes
PixelReadoutTechnology getReadoutTechnology() const
PixelDiodeTree::DiodeProxy diodeProxyFromIdx(const std::array< PixelDiodeTree::IndexType, 2 > &idx) const
SiLocalPosition positionFromColumnRow(const int column, const int row) const
Given row and column index of a diode, return position of diode center ALTERNATIVE/PREFERED way is to...
virtual SiReadoutCellId readoutIdOfCell(const SiCellId &cellId) const
diode id -> readout id
static InDetDD::PixelDiodeType getDiodeType(const PixelDiodeTree::DiodeProxy &diode_proxy)
virtual SiCellId cellIdOfPosition(const SiLocalPosition &localPos) const
position -> id
virtual double width() const
Method to calculate average width of a module.
static unsigned int getFE(const PixelDiodeTree::DiodeProxy &diode_proxy)
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
int etaIndex() const
Get eta index.
Definition SiCellId.h:114
Class to hold geometrical description of a silicon detector element.
virtual SiCellId cellIdFromIdentifier(const Identifier &identifier) const override final
SiCellId from Identifier.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
Class to handle the position of the centre and the width of a diode or a cluster of diodes Version 1....
const SiLocalPosition & width() const
width of the diodes:
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
double xPhi() const
position along phi direction:
double xEta() const
position along eta direction:
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
HepGeom::Point3D< double > globalPosition(const HepGeom::Point3D< double > &localPos) const
transform a reconstruction local position into a global position (inline):
const AtlasDetectorID * getIdHelper() const
Returns the id helper (inline)
std::vector< double > assembleInputRunII(NNinput &input) const
void addTrackInfoToInput(NNinput &input, const Trk::Surface &pixelSurface, const Trk::TrackParameters &trackParsAtSurface, const double tanl) const
Gaudi::Property< unsigned int > m_maxSubClusters
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
std::vector< double > estimateNumberOfParticlesLWTNN(NnClusterizationFactory::InputVector &input) const
Gaudi::Property< unsigned int > m_sizeX
double correctedRMSY(double posPixels, std::vector< float > &pitches) const
ReturnType(::TTrainedNetwork::* m_calculateOutput)(const InputType &input) const
NNinput createInput(const InDet::PixelCluster &pCluster, Amg::Vector3D &beamSpotPosition, double &tanl) const
virtual StatusCode initialize() override
Gaudi::Property< double > m_correctLorShiftBarrelWithoutTracks
Gaudi::Property< std::size_t > m_outputNodesPos1
Gaudi::Property< std::vector< std::size_t > > m_outputNodesPos2
ToolHandle< ISiLorentzAngleTool > m_pixelLorentzAngleTool
Gaudi::Property< std::vector< std::size_t > > m_outputNodesPos3
std::vector< Amg::Vector2D > estimatePositionsLWTNN(NnClusterizationFactory::InputVector &input, NNinput &rawInput, const InDet::PixelCluster &pCluster, int numberSubClusters, std::vector< Amg::MatrixX > &errors) const
std::vector< double > assembleInputRunI(NNinput &input) const
SG::ReadCondHandleKey< LWTNNCollection > m_readKeyJSON
std::vector< Amg::Vector2D > estimatePositions(const InDet::PixelCluster &pCluster, Amg::Vector3D &beamSpotPosition, std::vector< Amg::MatrixX > &errors, int numberSubClusters) const
Gaudi::Property< std::vector< std::string > > m_nnOrder
Gaudi::Property< double > m_correctLorShiftBarrelWithTracks
Gaudi::Property< bool > m_useTTrainedNetworks
std::vector< double > estimateNumberOfParticlesTTN(const TTrainedNetworkCollection &nn_collection, const std::vector< double > &inputData) const
static constexpr std::array< unsigned int, kNNetworkTypes > m_nParticleGroup
SG::ReadCondHandleKey< TTrainedNetworkCollection > m_readKeyWithoutTrack
std::vector< double >(InDet::NnClusterizationFactory::* m_assembleInput)(NNinput &input) const
std::vector< Eigen::VectorXd > InputVector
NnClusterizationFactory(const std::string &name, const std::string &n, const IInterface *p)
std::vector< Amg::Vector2D > estimatePositionsTTN(const TTrainedNetworkCollection &nn_collection, const std::vector< double > &inputData, const NNinput &input, const InDet::PixelCluster &pCluster, int numberSubClusters, std::vector< Amg::MatrixX > &errors) const
static const std::array< std::regex, kNNetworkTypes > m_nnNames
Gaudi::Property< bool > m_useRecenteringNNWithouTracks
static constexpr std::array< std::string_view, kNNetworkTypes > s_nnTypeNames
InputVector eigenInput(NNinput &input) const
void getErrorMatrixFromOutput(std::vector< double > &outputX, std::vector< double > &outputY, std::vector< Amg::MatrixX > &errorMatrix, int nParticles) const
Gaudi::Property< bool > m_useRecenteringNNWithTracks
std::vector< std::vector< unsigned int > > m_NNId
std::vector< Amg::Vector2D > getPositionsFromOutput(std::vector< double > &output, const NNinput &input, const InDet::PixelCluster &pCluster) const
static double correctedRMSX(double posPixels)
size_t calculateVectorDimension(const bool useTrackInfo) const
Gaudi::Property< unsigned int > m_sizeY
SG::ReadCondHandleKey< TTrainedNetworkCollection > m_readKeyWithTrack
std::vector< double > estimateNumberOfParticles(const InDet::PixelCluster &pCluster, Amg::Vector3D &beamSpotPosition) const
virtual const InDetDD::SiDetectorElement * detectorElement() const override final
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
float getCharge(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE, float ToT) const
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:67
int eta_index(const Identifier &id) const
Definition PixelID.h:645
int layer_disk(const Identifier &id) const
Definition PixelID.h:607
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module) const
For a single crystal.
Definition PixelID.h:360
int barrel_ec(const Identifier &id) const
Values of different levels (failure returns 0)
Definition PixelID.h:600
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition PixelID.h:383
int eta_module(const Identifier &id) const
Definition PixelID.h:632
int phi_index(const Identifier &id) const
Definition PixelID.h:639
std::vector< Double_t > calculateOutputValues(std::vector< Double_t > &input) const
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
Abstract Base Class for tracking surfaces.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
STL class.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Primary Vertex Finder.
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
ParametersBase< TrackParametersDim, Charged > TrackParameters
Helper class to access parameters of a diode.
std::vector< float > vectorOfPitchesY