Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MakeMilleFiles.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MakeMilleFiles.cc
1 #include "MakeMilleFiles.h"
2 
3 #include "Mille.h"
4 
6 
10 #include <trackbase/TrkrDefs.h>
11 #include <trackbase/MvtxDefs.h>
12 #include <trackbase/TpcDefs.h> // for side
13 
20 
22 
25 
27 
29 
30 #include <phool/PHCompositeNode.h>
31 #include <phool/getClass.h>
32 #include <phool/phool.h>
33 
34 #include <TF1.h>
35 
36 #include <cmath>
37 #include <fstream>
38 #include <iostream>
39 #include <map>
40 #include <set>
41 #include <utility>
42 
43 namespace
44 {
46  template <class T>
47  inline constexpr T square(const T& x)
48  {
49  return x * x;
50  }
51 } // namespace
52 
53 //____________________________________________________________________________..
55  : SubsysReco(name)
56  , _mille(nullptr)
57 {
58 }
59 
60 //____________________________________________________________________________..
62 {
63  int ret = GetNodes(topNode);
64  if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
65 
66  // Instantiate Mille and open output data file
67  // _mille = new Mille(data_outfilename.c_str(), false); // write text in data files, rather than binary, for debugging only
68  _mille = new Mille(data_outfilename.c_str(), _binary);
69 
70  // Write the steering file here, and add the data file path to it
71  std::ofstream steering_file(steering_outfilename);
72  steering_file << data_outfilename << std::endl;
73  steering_file << m_constraintFileName << std::endl;
74  steering_file.close();
75 
78  {
79  for(int i=0; i<AlignmentDefs::NGLVTX; i++)
80  {
81  m_constraintFile << " Constraint 0.0" << std::endl;
82  m_constraintFile << " " << AlignmentDefs::glbl_vtx_label[i] << " 1" << std::endl;
83  }
84  }
85  // print grouping setup to log file:
86  std::cout << "MakeMilleFiles::InitRun: Surface groupings are mvtx " << mvtx_group << " intt " << intt_group << " tpc " << tpc_group << " mms " << mms_group << std::endl;
87 
88  return ret;
89 }
90 
91 //____________________________________________________________________________..
93 {
94  // Outline:
95  //
96  // loop over track alignment states
97  // Make any track cuts here to skip undesirable tracks (maybe low pT?)
98  // loop over track states+measurements for each track
99  // for each measurement, performed in trackreco/ActsAlignmentStates.cc
100  // Get measurement value and error
101  // Calculate derivatives and residuals from Acts jacobians
102  // These are stored in a map and unpacked for mille
103  // Call _mille->mille() with arguments obtained from previous iteration:
104  // local pars
105  // array of local derivatives
106  // global pars
107  // array of global derivatives
108  // array of integer global par labels
109  // residual value (float) z = measurement - track state
110  // sigma of measurement
111  // After processing all measurements for this track, call _mille->end() to add buffer to file and reset buffer
112  // After all tracks are processed, file is closed when Mille destructor is called
113  // Note: all units are in the Acts units of mm and GeV to avoid converting matrices
114 
115  if (Verbosity() > 0)
116  {
117  std::cout << PHWHERE << " track map size " << _track_map->size() << std::endl;
118  std::cout << "state map size " << _state_map->size() << std::endl;
119  }
120 
121  Acts::Vector3 eventVertex = Acts::Vector3::Zero();
122  if(m_useEventVertex)
123  {
124  eventVertex = getEventVertex();
125  }
126 
127  ActsPropagator propagator(_tGeometry);
128 
129  for (auto [key, statevec] : *_state_map)
130  {
131  // Check if track was removed from cleaner
132  auto iter = _track_map->find(key);
133  if (iter == _track_map->end())
134  {
135  continue;
136  }
137 
138  SvtxTrack* track = iter->second;
139 
140  if (Verbosity() > 0)
141  {
142  std::cout << std::endl
143  << __LINE__ << ": Processing track itrack: " << key << ": nhits: " << track->size_cluster_keys()
144  << ": Total tracks: " << _track_map->size() << ": phi: " << track->get_phi() << std::endl;
145  }
146 
149  addTrackToMilleFile(statevec);
150 
152  if(m_useEventVertex &&
153  fabs(track->get_z() - eventVertex.z()) < 0.2 &&
154  fabs(track->get_x()) < 0.2 &&
155  fabs(track->get_y()) < 0.2)
156  {
159  eventVertex(0) = 0; eventVertex(1) = 0;
160 
161  auto dcapair = TrackAnalysisUtils::get_dca(track,eventVertex);
162  Acts::Vector2 vtx_residual(-dcapair.first.first, -dcapair.second.first);
163  vtx_residual *= Acts::UnitConstants::cm;
164 
165  float lclvtx_derivative[SvtxAlignmentState::NRES][SvtxAlignmentState::NLOC];
166  bool success = getLocalVtxDerivativesXY(track, propagator,
167  eventVertex, lclvtx_derivative);
168 
169  // The global derivs dimensions are [alpha/beta/gamma](x/y/z)
170  float glblvtx_derivative[SvtxAlignmentState::NRES][3];
171  getGlobalVtxDerivativesXY(track, eventVertex, glblvtx_derivative);
172 
173  if(Verbosity() > 2)
174  {
175  std::cout << "vertex info for trakc " << track->get_id() << " with charge " << track->get_charge() << std::endl;
176  std::cout << "vertex is " << eventVertex.transpose()<<std::endl;
177  std::cout << "vertex residuals " << vtx_residual.transpose()
178  << std::endl;
179  std::cout << "global vtx derivatives " << std::endl;
180  for(int i=0; i<2;i++) {
181  for(int j=0; j<3; j++) {
182  std::cout << glblvtx_derivative[i][j] << ", ";
183  }
184  std::cout << std::endl;
185  }
186  }
187  if(success)
188  {
189  for(int i=0; i<2; i++)
190  {
191  if(!isnan(vtx_residual(i)))
192  {
193  _mille->mille(SvtxAlignmentState::NLOC,lclvtx_derivative[i],
194  AlignmentDefs::NGLVTX,glblvtx_derivative[i],
195  AlignmentDefs::glbl_vtx_label,vtx_residual(i),
196  m_vtxSigma(i));
197  }
198  }
199  }
200  }
201 
203  _mille->end();
204  }
205 
206  if (Verbosity() > 0)
207  {
208  std::cout << "Finished processing mille file " << std::endl;
209  }
210 
212 }
213 
215 {
216  delete _mille;
217  m_constraintFile.close();
218 
220 }
221 
223 {
224  _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
225  if (!_cluster_map)
226  {
227  std::cout << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << std::endl;
229  }
230 
231  _track_map = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
232  if (!_track_map)
233  {
234  std::cout << PHWHERE << " ERROR: Can't find SvtxTrackMap: " << std::endl;
236  }
237 
238  _tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
239  if (!_tGeometry)
240  {
241  std::cout << PHWHERE << "Error, can't find acts tracking geometry" << std::endl;
243  }
244 
245  _state_map = findNode::getClass<SvtxAlignmentStateMap>(topNode, "SvtxAlignmentStateMap");
246  if (!_state_map)
247  {
248  std::cout << PHWHERE << "Error, can't find alignment state map" << std::endl;
250  }
251 
253 }
254 
256  ActsPropagator& propagator,
257  const Acts::Vector3& vertex,
258  float lclvtx_derivative[SvtxAlignmentState::NRES][SvtxAlignmentState::NLOC])
259 {
263  SvtxTrackState* firststate = (*std::next(track->begin_states(),1)).second;
264 
265  TrkrDefs::cluskey ckey = firststate->get_cluskey();
266  auto cluster = _cluster_map->findCluster(ckey);
267  auto surf = _tGeometry->maps().getSurface(ckey, cluster);
268 
269  auto param = propagator.makeTrackParams(firststate,track->get_charge(),surf).value();
270  auto perigee = propagator.makeVertexSurface(vertex);
271  auto actspropagator = propagator.makePropagator();
272 
275 
276  auto result = actspropagator.propagate(param, *perigee, options);
277 
278  if(result.ok())
279  {
280  auto jacobian = *result.value().transportJacobian;
281 
282  Eigen::Matrix<double,2,6> projector = Eigen::Matrix<double,2,6>::Zero();
283  projector(0,0) = 1;
284  projector(1,1) = 1;
285  auto deriv = projector * jacobian;
286  if(Verbosity() > 2)
287  {
288  std::cout << "local vtxderiv " << std::endl << deriv << std::endl;
289  }
290 
291  for(int i=0; i<deriv.rows(); i++)
292  {
293  for(int j=0; j<deriv.cols(); j++)
294  {
295  lclvtx_derivative[i][j] = deriv(i,j);
296  }
297  }
298 
299  return true;
300  }
301 
302  return false;
303 }
304 
306  const Acts::Vector3& vertex,
307  float glblvtx_derivative[SvtxAlignmentState::NRES][3])
308 {
309  Acts::SquareMatrix3 identity = Acts::SquareMatrix3::Identity();
310 
311  Acts::Vector3 projx = Acts::Vector3::Zero();
312  Acts::Vector3 projy = Acts::Vector3::Zero();
313  getProjectionVtxXY(track, vertex, projx, projy);
314 
315  glblvtx_derivative[0][0] = identity.col(0).dot(projx);
316  glblvtx_derivative[0][1] = identity.col(1).dot(projx);
317  glblvtx_derivative[0][2] = identity.col(2).dot(projx);
318  glblvtx_derivative[1][0] = identity.col(0).dot(projy);
319  glblvtx_derivative[1][1] = identity.col(1).dot(projy);
320  glblvtx_derivative[1][2] = identity.col(2).dot(projy);
321 
324  for(int i=0; i<2; i++) {
325  for(int j=0; j<3; j++) {
326  glblvtx_derivative[i][j] *= -1;
327  }
328  }
329 }
331  const Acts::Vector3& vertex,
332  Acts::Vector3& projx,
333  Acts::Vector3& projy)
334 {
335  Acts::Vector3 tangent(track->get_px(), track->get_py(), track->get_pz());
336  Acts::Vector3 normal(track->get_px(), track->get_py(), 0);
337 
338  tangent /= tangent.norm();
339  normal /= normal.norm();
340 
341  Acts::Vector3 localx(1,0,0);
342  Acts::Vector3 localz(0,0,1);
343 
344  Acts::Vector3 xglob = localToGlobalVertex(track, vertex, localx);
345  Acts::Vector3 yglob = localz + vertex;
346 
347  Acts::Vector3 X = (xglob-vertex) / (xglob-vertex).norm();
348  Acts::Vector3 Y = (yglob-vertex) / (yglob-vertex).norm();
349 
350  // see equation 31 of the ATLAS paper (and discussion) for this
351  projx = X - (tangent.dot(X) / tangent.dot(normal)) * normal;
352  projy = Y - (tangent.dot(Y) / tangent.dot(normal)) * normal;
353 
354  return;
355 
356 }
358  const Acts::Vector3& vertex,
359  const Acts::Vector3& localx) const
360 {
361  Acts::Vector3 mom(track->get_px(),
362  track->get_py(),
363  track->get_pz());
364 
365  Acts::Vector3 r = mom.cross(Acts::Vector3(0.,0.,1.));
366  float phi = atan2(r(1), r(0));
368  Acts::RotationMatrix3 rot_T;
369 
370  rot(0,0) = cos(phi);
371  rot(0,1) = -sin(phi);
372  rot(0,2) = 0;
373  rot(1,0) = sin(phi);
374  rot(1,1) = cos(phi);
375  rot(1,2) = 0;
376  rot(2,0) = 0;
377  rot(2,1) = 0;
378  rot(2,2) = 1;
379 
380  rot_T = rot.transpose();
381 
382  Acts::Vector3 pos_R = rot * localx;
383 
384  pos_R += vertex;
385 
386  return pos_R;
387 }
388 
389 
391 {
395  float xsum = 0;
396  float ysum = 0;
397  float zsum = 0;
398  int nacceptedtracks = 0;
399 
400  for( auto [ key, statevec] : *_state_map)
401  {
402  // Check if track was removed from cleaner
403  auto iter = _track_map->find(key);
404  if (iter == _track_map->end())
405  {
406  continue;
407  }
408 
409  SvtxTrack* track = iter->second;
410 
412  xsum += track->get_x();
413  ysum += track->get_y();
414  zsum += track->get_z();
415 
416  nacceptedtracks++;
417  }
418 
419  return Acts::Vector3 (xsum/nacceptedtracks,
420  ysum/nacceptedtracks,
421  zsum/nacceptedtracks);
422 }
423 
425 {
426  for (auto state : statevec)
427  {
428  TrkrDefs::cluskey ckey = state->get_cluster_key();
429 
430  if (Verbosity() > 2)
431  {
432  std::cout << "adding state for ckey " << ckey << " with hitsetkey "
433  << (int) TrkrDefs::getHitSetKeyFromClusKey(ckey) << std::endl;
434  }
435  // The global alignment parameters are given initial values of zero by default, we do not specify them
436  // We identify the global alignment parameters for this surface
437 
438  TrkrCluster* cluster = _cluster_map->findCluster(ckey);
439  const unsigned int layer = TrkrDefs::getLayer(ckey);
440  const unsigned int trkrid = TrkrDefs::getTrkrId(ckey);
441  const SvtxAlignmentState::ResidualVector residual = state->get_residual();
442  const Acts::Vector3 global = _tGeometry->getGlobalPosition(ckey, cluster);
443 
444  // need standard deviation of measurements
445  SvtxAlignmentState::ResidualVector clus_sigma = SvtxAlignmentState::ResidualVector::Zero();
446 
447  double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]);
448  auto para_errors = _ClusErrPara.get_clusterv5_modified_error(cluster, clusRadius, ckey);
449  double phierror = sqrt(para_errors.first);
450  double zerror = sqrt(para_errors.second);
451  clus_sigma(1) = zerror * Acts::UnitConstants::cm;
452  clus_sigma(0) = phierror * Acts::UnitConstants::cm;
453 
454 
455  if (std::isnan(clus_sigma(0)) ||
456  std::isnan(clus_sigma(1)))
457  {
458  continue;
459  }
460 
461  auto surf = _tGeometry->maps().getSurface(ckey, cluster);
462 
463  int glbl_label[SvtxAlignmentState::NGL];
464  if (layer < 3)
465  {
467  }
468  else if(layer > 2 && layer < 7)
469  {
471  }
472  else if (layer < 55)
473  {
475  }
476  else if (layer < 57)
477  {
479  }
480 
481  if (Verbosity() > 1)
482  {
483  std::cout << std::endl;
484  }
485 
487  for (int i = 0; i < SvtxAlignmentState::NRES; ++i)
488  {
489  // Add the measurement separately for each coordinate direction to Mille
490  float glbl_derivative[SvtxAlignmentState::NGL];
491  for (int j = 0; j < SvtxAlignmentState::NGL; ++j)
492  {
493  glbl_derivative[j] = state->get_global_derivative_matrix()(i, j);
494 
495  if (is_layer_fixed(layer) ||
497  {
498  glbl_derivative[j] = 0.;
499  }
500 
501  if(trkrid == TrkrDefs::mvtxId)
502  {
503  // need stave to get clamshell
504  auto stave = MvtxDefs::getStaveId(ckey);
505  auto clamshell = AlignmentDefs::getMvtxClamshell(layer, stave);
507  is_mvtx_layer_fixed(layer,clamshell) )
508  {
509  glbl_derivative[j] = 0;
510  }
511  }
512  else if(trkrid == TrkrDefs::inttId)
513  {
515  is_layer_fixed(layer) )
516  {
517  glbl_derivative[j] = 0;
518  }
519  }
520  if(trkrid == TrkrDefs::tpcId)
521  {
522  auto sector = TpcDefs::getSectorId(ckey);
523  auto side = TpcDefs::getSide(ckey);
525  is_tpc_sector_fixed(layer, sector, side) ||
526  is_layer_fixed(layer))
527  {
528  glbl_derivative[j] = 0.0;
529  }
530  }
531  }
532 
533  float lcl_derivative[SvtxAlignmentState::NLOC];
534  for (int j = 0; j < SvtxAlignmentState::NLOC; ++j)
535  {
536  lcl_derivative[j] = state->get_local_derivative_matrix()(i, j);
537 
539  {
540  lcl_derivative[j] = 0.;
541  }
542  }
543  if (Verbosity() > 2)
544  {
545  std::cout << "coordinate " << i << " has residual " << residual(i) << " and clus_sigma " << clus_sigma(i) << std::endl
546  << "global deriv " << std::endl;
547 
548  for (int k = 0; k < SvtxAlignmentState::NGL; k++)
549  {
550  if (glbl_derivative[k] > 0 || glbl_derivative[k] < 0)
551  std::cout << "NONZERO GLOBAL DERIVATIVE" << std::endl;
552  std::cout << glbl_derivative[k] << ", ";
553  }
554  std::cout << std::endl
555  << "local deriv " << std::endl;
556  for (int k = 0; k < SvtxAlignmentState::NLOC; k++)
557  {
558  std::cout << lcl_derivative[k] << ", ";
559  }
560  std::cout << std::endl;
561  }
562 
563  if (clus_sigma(i) < 1.0) // discards crazy clusters
564  {
565  if (Verbosity() > 3)
566  {
567  std::cout << "ckey " << ckey << " and layer " << layer << " buffers:" << std::endl;
568  AlignmentDefs::printBuffers(i, residual, clus_sigma, lcl_derivative, glbl_derivative, glbl_label);
569  }
570  float errinf = 1.0;
571  if (m_layerMisalignment.find(layer) != m_layerMisalignment.end())
572  {
573  errinf = m_layerMisalignment.find(layer)->second;
574  }
575 
576  _mille->mille(SvtxAlignmentState::NLOC, lcl_derivative, SvtxAlignmentState::NGL, glbl_derivative, glbl_label, residual(i), errinf * clus_sigma(i));
577  }
578  }
579  }
580 
581 
582  return;
583 }
584 
586 {
587  bool ret = false;
588  auto it = fixed_layers.find(layer);
589  if (it != fixed_layers.end())
590  ret = true;
591 
592  return ret;
593 }
594 void MakeMilleFiles::set_layers_fixed(unsigned int minlayer,
595  unsigned int maxlayer)
596 {
597  for (unsigned int i = minlayer; i < maxlayer; i++)
598  {
599  fixed_layers.insert(i);
600  }
601 }
603 {
604  fixed_layers.insert(layer);
605 }
606 
607 bool MakeMilleFiles::is_mvtx_layer_fixed(unsigned int layer, unsigned int clamshell)
608 {
609  bool ret = false;
610 
611  std::pair pair = std::make_pair(layer,clamshell);
612  auto it = fixed_mvtx_layers.find(pair);
613  if(it != fixed_mvtx_layers.end())
614  ret = true;
615 
616  return ret;
617 }
618 void MakeMilleFiles::set_mvtx_layer_fixed(unsigned int layer, unsigned int clamshell)
619 {
620  fixed_mvtx_layers.insert(std::make_pair(layer,clamshell));
621 }
622 bool MakeMilleFiles::is_layer_param_fixed(unsigned int layer, unsigned int param, std::set<std::pair<unsigned int, unsigned int>>& param_fixed)
623 {
624  bool ret = false;
625  std::pair<unsigned int, unsigned int> pair = std::make_pair(layer, param);
626  auto it = param_fixed.find(pair);
627  if (it != param_fixed.end())
628  ret = true;
629 
630  return ret;
631 }
632 
633 void MakeMilleFiles::set_layer_gparam_fixed(unsigned int layer, unsigned int param)
634 {
635  fixed_layer_gparams.insert(std::make_pair(layer,param));
636 }
637 void MakeMilleFiles::set_layer_lparam_fixed(unsigned int layer, unsigned int param)
638 {
639  fixed_layer_lparams.insert(std::make_pair(layer,param));
640 }
641 bool MakeMilleFiles::is_tpc_sector_fixed(unsigned int layer, unsigned int sector, unsigned int side)
642  {
643  bool ret = false;
644  unsigned int region = AlignmentDefs::getTpcRegion(layer);
645  unsigned int subsector = region * 24 + side * 12 + sector;
646  auto it = fixed_sectors.find(subsector);
647  if(it != fixed_sectors.end())
648  ret = true;
649 
650  return ret;
651  }