Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHTpcResiduals.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHTpcResiduals.cc
1 #include "PHTpcResiduals.h"
3 
6 #include <phool/getClass.h>
7 #include <phool/phool.h>
8 #include <phool/PHDataNode.h>
9 #include <phool/PHNode.h>
10 #include <phool/PHNodeIterator.h>
11 #include <phool/PHObject.h>
12 #include <phool/PHTimer.h>
13 
15 
16 #include <trackbase/TpcDefs.h>
17 #include <trackbase/TrkrCluster.h>
22 
24 
26 
31 
32 #pragma GCC diagnostic push
33 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
35 #pragma GCC diagnostic pop
36 
39 
41 
42 
43 #include <cmath>
44 #include <TFile.h>
45 #include <TTree.h>
46 #include <TH1.h>
47 #include <TH2.h>
48 
49 #include <iostream>
50 #include <sstream>
51 
52 namespace
53 {
54 
55  // square
56  template<class T> inline constexpr T square( const T& x ) { return x*x; }
57 
58  // radius
59  template<class T> T get_r( const T& x, const T& y ) { return std::sqrt( square(x) + square(y) ); }
60 
61  template<class T> inline constexpr T deltaPhi(const T& phi)
62  {
63  if (phi > M_PI)
64  return phi - 2. * M_PI;
65  else if (phi <= -M_PI)
66  return phi + 2.* M_PI;
67  else
68  return phi;
69  }
70 
72 
73  inline constexpr double get_sector_phi( int isec )
74  { return isec*M_PI/6; }
75 
76  // specify bins for which one will save histograms
77  static const std::vector<float> phi_rec = { get_sector_phi(9) };
78  static const std::vector<float> z_rec = { 5. };
79 
81  std::vector<TrkrDefs::cluskey> get_cluster_keys( SvtxTrack* track )
82  {
83  std::vector<TrkrDefs::cluskey> out;
84  for( const auto& seed: { track->get_silicon_seed(), track->get_tpc_seed() } )
85  {
86  if( seed )
87  { std::copy( seed->begin_cluster_keys(), seed->end_cluster_keys(), std::back_inserter( out ) ); }
88  }
89  return out;
90  }
91 
93  template<int type>
94  int count_clusters( const std::vector<TrkrDefs::cluskey>& keys )
95  {
96  return std::count_if( keys.begin(), keys.end(),
97  []( const TrkrDefs::cluskey& key ) { return TrkrDefs::getTrkrId(key) == type; } );
98  }
99 
100 }
101 
102 //___________________________________________________________________________________
104  : SubsysReco(name)
105  , m_matrix_container( new TpcSpaceChargeMatrixContainerv1 )
106 {}
107 
108 //___________________________________________________________________________________
110 {
111 
112  // configuration printout
113  std::cout << "PHTpcResiduals::Init - m_maxTAlpha: " << m_maxTAlpha << std::endl;
114  std::cout << "PHTpcResiduals::Init - m_maxTBeta: " << m_maxTBeta << std::endl;
115  std::cout << "PHTpcResiduals::Init - m_maxResidualDrphi: " << m_maxResidualDrphi << " cm" << std::endl;
116  std::cout << "PHTpcResiduals::Init - m_maxResidualDz: " << m_maxResidualDz << " cm" << std::endl;
117  std::cout << "PHTpcResiduals::Init - m_minPt: " << m_minPt << " GeV/c" << std::endl;
118 
119  // reset counters
120  m_total_tracks = 0;
121  m_accepted_tracks = 0;
122 
123  m_total_clusters = 0;
125 
127 }
128 
129 //___________________________________________________________________________________
131 {
132  if(getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
134 
137 
139 }
140 
141 //___________________________________________________________________________________
143 {
144  const auto returnVal = processTracks(topNode);
145  ++m_event;
146 
147  return returnVal;
148 }
149 
150 //___________________________________________________________________________________
152 {
153  std::cout << "PHTpcResiduals::End - writing matrices to " << m_outputfile << std::endl;
154 
155  // save matrix container in output file
156  if( m_matrix_container )
157  {
158  std::unique_ptr<TFile> outputfile( TFile::Open( m_outputfile.c_str(), "RECREATE" ) );
159  outputfile->cd();
160  m_matrix_container->Write( "TpcSpaceChargeMatrixContainer" );
161  }
162 
163  // print counters
164  std::cout
165  << "PHTpcResiduals::End -"
166  << " track statistics total: " << m_total_tracks
167  << " accepted: " << m_accepted_tracks
168  << " fraction: " << 100.*m_accepted_tracks/m_total_tracks << "%"
169  << std::endl;
170 
171  std::cout
172  << "PHTpcResiduals::End -"
173  << " cluster statistics total: " << m_total_clusters
174  << " accepted: " << m_accepted_clusters << " fraction: "
176  << std::endl;
177 
179 }
180 
181 //___________________________________________________________________________________
183 {
184 
185  if( Verbosity() )
186  { std::cout << "PHTpcResiduals::processTracks - proto track size " << m_trackMap->size() <<std::endl; }
187 
188  for(const auto &[trackKey, track] : *m_trackMap)
189  {
190  if(Verbosity() > 1)
191  { std::cout << "PHTpcResiduals::processTracks - Processing track key " << trackKey << std::endl; }
192 
193  ++m_total_tracks;
194  if(checkTrack(track))
195  {
197  processTrack(track);
198  }
199  }
200 
202 }
203 
204 //___________________________________________________________________________________
206 {
207  if(Verbosity() > 2)
208  { std::cout << "PHTpcResiduals::checkTrack - pt: " << track->get_pt() << std::endl; }
209 
210  if(track->get_pt() < m_minPt)
211  { return false; }
212 
213  // ignore tracks with too few mvtx, intt and micromegas hits
214  const auto cluster_keys( get_cluster_keys( track ) );
215  if( count_clusters<TrkrDefs::mvtxId>(cluster_keys) < 2 ) return false;
216  if( count_clusters<TrkrDefs::inttId>(cluster_keys) < 2 ) return false;
217  if( m_useMicromegas && count_clusters<TrkrDefs::micromegasId>(cluster_keys) < 2 ) return false;
218 
219 
220  return true;
221 
222 }
223 
224 //___________________________________________________________________________________
226 {
227  Acts::Vector3 momentum(track->get_px(),
228  track->get_py(),
229  track->get_pz());
230  double trackQ = track->get_charge() * Acts::UnitConstants::e;
231  double p = track->get_p();
232 
233  /* get acts covariance matrix from track parameters */
234  const auto cov = m_transformer.rotateSvtxTrackCovToActs( track );
235 
236  /* get position from track parameters */
238  track->get_y() * Acts::UnitConstants::cm,
239  track->get_z() * Acts::UnitConstants::cm);
240 
241  const auto perigee = Acts::Surface::makeShared<Acts::PerigeeSurface>(position);
242  const auto actsFourPos = Acts::Vector4(position(0), position(1), position(2), 10 * Acts::UnitConstants::ns);
243 
245  actsFourPos, momentum,
246  trackQ/p, cov,
248 
249 }
250 
252 {
253 
254  if(Verbosity() > 1)
255  {
256  std::cout << "PHTpcResiduals::processTrack -"
257  << " track momentum: " << track->get_p()
258  << " position: (" << track->get_x() << ", " << track->get_y() << ", " << track->get_z() << ")"
259  << std::endl;
260  }
261  ActsPropagator propagator(m_tGeometry);
262 
263  // create ACTS parameters from track parameters at origin
264  auto trackParams = makeTrackParams(track);
265 
266  // store crossing. It is used in calculating cluster's global position
267  m_crossing = track->get_crossing();
268  assert( m_crossing != SHRT_MAX );
269 
270  for( const auto& cluskey:get_cluster_keys( track ) )
271  {
272  // increment counter
274 
275  // make sure cluster is from TPC
276  const auto detId = TrkrDefs::getTrkrId(cluskey);
277  if(detId != TrkrDefs::tpcId) continue;
278 
279  const auto cluster = m_clusterContainer->findCluster(cluskey);
280  const auto surface = m_tGeometry->maps().getSurface( cluskey, cluster );
281  auto result = propagator.propagateTrack(trackParams, surface);
282 
283  // skip if propagation failed
284  if(!result.ok())
285  {
286  if( Verbosity() > 1 )
287  {
288  std::cout << "Starting track params position/momentum: "
289  << trackParams.position(m_tGeometry->geometry().geoContext).transpose()
290  << std::endl
291  << std::endl
292  << "Track params phi/eta "
293  << std::atan2(trackParams.momentum().y(),
294  trackParams.momentum().x())
295  << " and "
296  << std::atanh(trackParams.momentum().z()/trackParams.momentum().norm())
297  << std::endl;
298  }
299 
300  continue;
301  }
302 
303  // get extrapolated track state, convert to sPHENIX and add to track
304  auto& [pathLength, trackStateParams] = result.value();
306 
307  if(Verbosity() > 1)
308  {
309  std::cout << "PHTpcResiduals::processTrack -"
310  << " path length: " << pathLength
311  << " track momentum : "
312  << trackParams.momentum()
313  << " propagator momentum : "
314  << trackStateParams.momentum()
315  << std::endl;
316  }
317 
318 
319  addTrackState( track, cluskey, pathLength, trackStateParams );
320 
321  // calculate residuals with respect to cluster
322  // Get all the relevant information for residual calculation
323  const auto globClusPos = getGlobalPosition(cluskey, cluster, m_crossing);
324  const double clusR = get_r(globClusPos(0),globClusPos(1));
325  const double clusPhi = std::atan2(globClusPos(1), globClusPos(0));
326  const double clusZ = globClusPos(2);
327 
328  // cluster errors
329  double clusRPhiErr = 0;
330  double clusZErr = 0;
331 
332  clusRPhiErr = cluster->getRPhiError();
333  clusZErr = cluster->getZError();
334 
335 
336  if(Verbosity() > 3)
337  {
338  std::cout << "PHTpcResiduals::processTrack -"
339  << " cluskey: " << cluskey
340  << " clusR: " << clusR
341  << " clusPhi: " << clusPhi << "+/-" << clusRPhiErr
342  << " clusZ: " << clusZ << "+/-" << clusZErr
343  << std::endl;
344  }
345 
346  /*
347  * as instructed by Christof, it should not be necessary to cut on small
348  * cluster errors any more with clusters of version 4 or higher
349  */
350 
351  const auto globalStatePos = trackStateParams.position(m_tGeometry->geometry().getGeoContext());
352  const auto globalStateMom = trackStateParams.momentum();
353  const auto globalStateCov = *trackStateParams.covariance();
354 
355  const double trackRPhiErr = std::sqrt(globalStateCov(Acts::eBoundLoc0, Acts::eBoundLoc0))/Acts::UnitConstants::cm;
356  const double trackZErr = sqrt(globalStateCov(Acts::eBoundLoc1, Acts::eBoundLoc1))/Acts::UnitConstants::cm;
357 
358  const double globStateX = globalStatePos.x()/Acts::UnitConstants::cm;
359  const double globStateY = globalStatePos.y()/Acts::UnitConstants::cm;
360  const double globStateZ = globalStatePos.z()/Acts::UnitConstants::cm;
361 
362  const double trackR = std::sqrt(square(globStateX) + square(globStateY));
363 
364  const double dr = clusR - trackR;
365  const double trackDrDt = (globStateX * globalStateMom(0) + globStateY * globalStateMom(1)) / trackR;
366  const double trackDxDr = globalStateMom(0) / trackDrDt;
367  const double trackDyDr = globalStateMom(1) / trackDrDt;
368  const double trackDzDr = globalStateMom(2) / trackDrDt;
369 
370  const double trackX = globStateX + dr * trackDxDr;
371  const double trackY = globStateY + dr * trackDyDr;
372  const double trackZ = globStateZ + dr * trackDzDr;
373  const double trackPhi = std::atan2(trackY, trackX);
374 
375  if(Verbosity() > 2)
376  {
377  std::cout << "PHTpcResiduals::processTrack -"
378  << " trackR: " << trackR
379  << " dr: " << dr
380  << " trackDrDt: " << trackDrDt
381  << " trackDxDr: " << trackDxDr
382  << " trackDyDr: " << trackDyDr
383  << " trackDzDr: " << trackDzDr
384  << " trackPhi: " << trackPhi << "+/-" << trackRPhiErr
385  << " track position: (" << trackX << ", " << trackY << ", " << trackZ << ")"
386  << std::endl;
387  }
388 
389  const double erp = square(clusRPhiErr) + square(trackRPhiErr);
390  const double ez = square(clusZErr) + square(trackZErr);
391 
392  // Calculate residuals
393  const double drphi = clusR * deltaPhi(clusPhi - trackPhi);
394  const double dz = clusZ - trackZ;
395 
396  if(Verbosity() > 3)
397  {
398  std::cout << "PHTpcResiduals::processTrack -"
399  << " drphi: " << drphi
400  << " dz: " << dz
401  << std::endl;
402  }
403 
404  const double trackPPhi = -trackStateParams.momentum()(0) * std::sin(trackPhi) + trackStateParams.momentum()(1) * std::cos(trackPhi);
405  const double trackPR = trackStateParams.momentum()(0) * std::cos(trackPhi) + trackStateParams.momentum()(1) * std::sin(trackPhi);
406  const double trackPZ = trackStateParams.momentum()(2);
407 
408  const double trackAlpha = -trackPPhi / trackPR;
409  const double trackBeta = -trackPZ / trackPR;
410 
411  if(Verbosity() > 3)
412  {
413  std::cout
414  << "PHTpcResiduals::processTrack -"
415  << " trackPPhi: " << trackPPhi
416  << " trackPR: " << trackPR
417  << " trackPZ: " << trackPZ
418  << " trackAlpha: " << trackAlpha
419  << " trackBeta: " << trackBeta
420  << std::endl;
421  }
422 
423  // get cell index
424  const auto index = getCell(globClusPos);
425  if(Verbosity() > 3)
426  { std::cout << "Bin index found is " << index << std::endl; }
427 
428  if(index < 0 ) continue;
429 
430  if(Verbosity() > 3)
431  {
432  std::cout << "PHTpcResiduals::processTrack - layer: " << (int) TrkrDefs::getLayer(cluskey) << std::endl;
433  std::cout << "PHTpcResiduals::processTrack -"
434  << " cluster: (" << clusR << ", " << clusR*clusPhi << ", " << clusZ << ")"
435  << " (" << clusRPhiErr << ", " << clusZErr << ")"
436  << std::endl;
437 
438  std::cout << "PHTpcResiduals::processTrack -"
439  << " track: (" << trackR << ", " << clusR*trackPhi << ", " << trackZ << ")"
440  << " (" << trackAlpha << ", " << trackBeta << ")"
441  << " (" << trackRPhiErr << ", " << trackZErr << ")"
442  << std::endl;
443  std::cout << std::endl;
444  }
445 
446  // check track angles and residuals agains cuts
447  if(std::abs(trackAlpha) > m_maxTAlpha || std::abs(drphi) > m_maxResidualDrphi)
448  { continue; }
449 
450  if(std::abs(trackBeta) > m_maxTBeta || std::abs(dz) > m_maxResidualDz)
451  { continue; }
452 
453  // Fill distortion matrices
454  m_matrix_container->add_to_lhs(index, 0, 0, 1./erp );
455  m_matrix_container->add_to_lhs(index, 0, 1, 0 );
456  m_matrix_container->add_to_lhs(index, 0, 2, trackAlpha/erp );
457 
458  m_matrix_container->add_to_lhs(index, 1, 0, 0 );
459  m_matrix_container->add_to_lhs(index, 1, 1, 1./ez );
460  m_matrix_container->add_to_lhs(index, 1, 2, trackBeta/ez );
461 
462  m_matrix_container->add_to_lhs(index, 2, 0, trackAlpha/erp );
463  m_matrix_container->add_to_lhs(index, 2, 1, trackBeta/ez );
464  m_matrix_container->add_to_lhs(index, 2, 2, square(trackAlpha)/erp + square(trackBeta)/ez );
465 
466  m_matrix_container->add_to_rhs(index, 0, drphi/erp );
467  m_matrix_container->add_to_rhs(index, 1, dz/ez );
468  m_matrix_container->add_to_rhs(index, 2, trackAlpha*drphi/erp + trackBeta*dz/ez );
469 
470  // update entries in cell
471  m_matrix_container->add_to_entries(index);
472 
473  // increment number of accepted clusters
475 
476  }
477 
478 }
479 
480 //_______________________________________________________________________________________________________
481 void PHTpcResiduals::addTrackState( SvtxTrack* track, TrkrDefs::cluskey key, float pathlength, const Acts::BoundTrackParameters& params )
482 {
483 
484  /* this is essentially a copy of the code from trackbase_historic/ActsTransformations::fillSvtxTrackStates */
485 
486  // create track state
487  SvtxTrackState_v1 state( pathlength );
488 
489  // save global position
490  const auto global = params.position(m_tGeometry->geometry().getGeoContext());
491  state.set_x(global.x() / Acts::UnitConstants::cm);
492  state.set_y(global.y() / Acts::UnitConstants::cm);
493  state.set_z(global.z() / Acts::UnitConstants::cm);
494 
495  // save momentum
496  const auto momentum = params.momentum();
497  state.set_px(momentum.x());
498  state.set_py(momentum.y());
499  state.set_pz(momentum.z());
500 
501  // covariance
502  const auto globalCov = m_transformer.rotateActsCovToSvtxTrack(params);
503  for (int i = 0; i < 6; ++i)
504  for (int j = 0; j < 6; ++j)
505  { state.set_error(i, j, globalCov(i,j)); }
506 
508 
509  track->insert_state(&state);
510 }
511 
512 //_______________________________________________________________________________
514 {
515 
516  // get grid dimensions from matrix container
517  int phibins = 0;
518  int rbins = 0;
519  int zbins = 0;
520  m_matrix_container->get_grid_dimensions( phibins, rbins, zbins );
521 
522  // phi
523  float phi = std::atan2(loc(1), loc(0));
524  while( phi < m_phiMin ) phi += 2.*M_PI;
525  while( phi >= m_phiMax ) phi -= 2.*M_PI;
526  const int iphi = phibins * (phi - m_phiMin) / (m_phiMax - m_phiMin);
527 
528  // r
529  const auto r = get_r( loc(0), loc(1) );
530  if( r < m_rMin || r >= m_rMax ) return -1;
531  const int ir = rbins * (r - m_rMin) / (m_rMax - m_rMin);
532 
533  // z
534  const auto z = loc(2);
535  if( z < m_zMin || z >= m_zMax ) return -1;
536  const int iz = zbins * (z - m_zMin) / (m_zMax - m_zMin);
537 
538  // get index from matrix container
539  return m_matrix_container->get_cell_index( iphi, ir, iz );
540 
541 }
542 
543 //_______________________________________________________________________________
546 
547 //_______________________________________________________________________________
549 {
550  m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode,"TRKR_CLUSTER");
551  if(!m_clusterContainer)
552  {
553  std::cout << PHWHERE << "No TRKR_CLUSTER node on node tree. Exiting." << std::endl;
555  }
556 
557  m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
558  if(!m_tGeometry)
559  {
560  std::cout << "ActsTrackingGeometry not on node tree. Exiting." << std::endl;
562  }
563 
564  m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxSiliconMMTrackMap");
565  if (!m_trackMap)
566  {
567  std::cout << PHWHERE << "SvtxSiliconMMTrackMap not on node tree. Exiting." << std::endl;
569  }
570 
571  // tpc distortion corrections
572  m_dcc_static = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainerStatic");
573  m_dcc_average = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainerAverage");
574  m_dcc_fluctuation = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,"TpcDistortionCorrectionContainerFluctuation");
575 
577 }
578 
579 //_________________________________________________________________________________
581 {
582  // get global position from Acts transform
583  auto globalPosition = m_tGeometry->getGlobalPosition(key, cluster);
584 
585  // for the TPC calculate the proper z based on crossing and side
586  const auto trkrid = TrkrDefs::getTrkrId(key);
587  if(trkrid == TrkrDefs::tpcId)
588  {
589  const auto side = TpcDefs::getSide(key);
590  globalPosition.z() = m_clusterCrossingCorrection.correctZ(globalPosition.z(), side, crossing);
591 
592  // apply distortion corrections
593  if(m_dcc_static)
594  {
595  globalPosition = m_distortionCorrection.get_corrected_position( globalPosition, m_dcc_static );
596  }
597 
598  if(m_dcc_average)
599  {
600  globalPosition = m_distortionCorrection.get_corrected_position( globalPosition, m_dcc_average );
601  }
602 
603  if(m_dcc_fluctuation)
604  {
605  globalPosition = m_distortionCorrection.get_corrected_position( globalPosition, m_dcc_fluctuation );
606  }
607  }
608 
609  return globalPosition;
610 }
611 
612 void PHTpcResiduals::setGridDimensions(const int phiBins, const int rBins, const int zBins)
613 { m_matrix_container->set_grid_dimensions( phiBins, rBins, zBins ); }
614