Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:20:52

0001 
0002 #include "TrackResiduals.h"
0003 
0004 #include <trackbase/ClusterErrorPara.h>
0005 #include <trackbase/InttDefs.h>
0006 #include <trackbase/MvtxDefs.h>
0007 #include <trackbase/TpcDefs.h>
0008 #include <trackbase/TrackFitUtils.h>
0009 #include <trackbase/TrkrCluster.h>
0010 #include <trackbase/TrkrClusterContainer.h>
0011 #include <trackbase/TrkrHit.h>
0012 #include <trackbase/TrkrHitSet.h>
0013 #include <trackbase/TrkrHitSetContainer.h>
0014 #include <trackbase/TrkrClusterIterationMap.h>
0015 #include <g4detectors/PHG4CylinderGeomContainer.h>
0016 #include <g4detectors/PHG4TpcGeom.h>
0017 #include <g4detectors/PHG4TpcGeomContainer.h>
0018 
0019 #include <globalvertex/MbdVertex.h>
0020 #include <globalvertex/MbdVertexMap.h>
0021 
0022 #include <intt/CylinderGeomIntt.h>
0023 #include <intt/CylinderGeomInttHelper.h>
0024 
0025 #include <mbd/MbdPmtContainer.h>
0026 #include <mbd/MbdPmtHit.h>
0027 
0028 #include <micromegas/CylinderGeomMicromegas.h>
0029 #include <micromegas/MicromegasDefs.h>
0030 
0031 #include <mvtx/CylinderGeom_Mvtx.h>
0032 #include <mvtx/CylinderGeom_MvtxHelper.h>
0033 
0034 #include <trackbase_historic/ActsTransformations.h>
0035 #include <trackbase_historic/SvtxAlignmentState.h>
0036 #include <trackbase_historic/SvtxAlignmentStateMap.h>
0037 #include <trackbase_historic/SvtxTrack.h>
0038 #include <trackbase_historic/SvtxTrackMap.h>
0039 #include <trackbase_historic/TrackAnalysisUtils.h>
0040 #include <trackbase_historic/TrackSeed.h>
0041 #include <trackbase_historic/TrackSeedContainer.h>
0042 #include <trackbase_historic/TrackSeedHelper.h>
0043 
0044 #include <tpc/LaserEventInfo.h>
0045 
0046 #include <ffarawobjects/Gl1Packet.h>
0047 #include <ffarawobjects/Gl1RawHit.h>
0048 
0049 #include <globalvertex/GlobalVertex.h>
0050 #include <globalvertex/GlobalVertexMap.h>
0051 #include <globalvertex/SvtxVertex.h>
0052 #include <globalvertex/SvtxVertexMap.h>
0053 
0054 #include <fun4all/Fun4AllReturnCodes.h>
0055 #include <fun4all/Fun4AllServer.h>
0056 
0057 #include <phool/PHCompositeNode.h>
0058 #include <phool/PHNodeIterator.h>
0059 #include <phool/getClass.h>
0060 
0061 #include <TSystem.h>
0062 
0063 #include <cmath>
0064 #include <algorithm>
0065 #include <limits>
0066 
0067 namespace
0068 {
0069   template <class T>
0070   inline T square(const T& t)
0071   {
0072     return t * t;
0073   }
0074   template <class T>
0075   inline T r(const T& x, const T& y)
0076   {
0077     return std::sqrt(square(x) + square(y));
0078   }
0079 
0080   std::vector<TrkrDefs::cluskey> get_cluster_keys(SvtxTrack* track)
0081   {
0082     std::vector<TrkrDefs::cluskey> out;
0083 
0084     if(!track)
0085       {
0086     return out;
0087       }
0088     
0089     for (const auto& seed : {track->get_silicon_seed(), track->get_tpc_seed()})
0090     {
0091       if (seed)
0092       {
0093         std::copy(seed->begin_cluster_keys(), seed->end_cluster_keys(), std::back_inserter(out));
0094       }
0095     }
0096 
0097     return out;
0098   }
0099 }  // namespace
0100 
0101 //____________________________________________________________________________..
0102 TrackResiduals::TrackResiduals(const std::string& name)
0103   : SubsysReco(name)
0104 {
0105 }
0106 
0107 //____________________________________________________________________________..
0108 int TrackResiduals::InitRun(PHCompositeNode* topNode)
0109 {
0110   m_outfile = new TFile(m_outfileName.c_str(), "RECREATE");
0111   createBranches();
0112 
0113   // global position wrapper
0114   m_globalPositionWrapper.loadNodes(topNode);
0115   m_globalPositionWrapper.set_suppressCrossing(m_convertSeeds);
0116   // clusterMover needs the correct radii of the TPC layers
0117   auto *tpccellgeo = findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0118   m_clusterMover.initialize_geometry(tpccellgeo);
0119   m_clusterMover.set_verbosity(0);
0120 
0121   auto *se = Fun4AllServer::instance();
0122   m_runnumber = se->RunNumber();
0123 
0124   return Fun4AllReturnCodes::EVENT_OK;
0125 }
0126 void TrackResiduals::clearClusterStateVectors()
0127 {
0128   m_cluskeys.clear();
0129   m_clusphisize.clear();
0130   m_cluszsize.clear();
0131   m_idealsurfcenterx.clear();
0132   m_idealsurfcentery.clear();
0133   m_idealsurfcenterz.clear();
0134   m_idealsurfnormx.clear();
0135   m_clstave.clear();
0136   m_clchip.clear();
0137   m_clladderz.clear();
0138   m_clladderphi.clear();
0139   m_clsector.clear();
0140   m_clside.clear();
0141   m_idealsurfnormy.clear();
0142   m_idealsurfnormz.clear();
0143   m_missurfcenterx.clear();
0144   m_missurfcentery.clear();
0145   m_missurfcenterz.clear();
0146   m_missurfnormx.clear();
0147   m_missurfnormy.clear();
0148   m_missurfnormz.clear();
0149   m_clusgxideal.clear();
0150   m_clusgyideal.clear();
0151   m_clusgzideal.clear();
0152   m_missurfalpha.clear();
0153   m_missurfbeta.clear();
0154   m_missurfgamma.clear();
0155   m_idealsurfalpha.clear();
0156   m_idealsurfbeta.clear();
0157   m_idealsurfgamma.clear();
0158 
0159   m_statelxglobderivdx.clear();
0160   m_statelxglobderivdy.clear();
0161   m_statelxglobderivdz.clear();
0162   m_statelxglobderivdalpha.clear();
0163   m_statelxglobderivdbeta.clear();
0164   m_statelxglobderivdgamma.clear();
0165 
0166   m_statelxlocderivd0.clear();
0167   m_statelxlocderivz0.clear();
0168   m_statelxlocderivphi.clear();
0169   m_statelxlocderivtheta.clear();
0170   m_statelxlocderivqop.clear();
0171 
0172   m_statelzglobderivdx.clear();
0173   m_statelzglobderivdy.clear();
0174   m_statelzglobderivdz.clear();
0175   m_statelzglobderivdalpha.clear();
0176   m_statelzglobderivdbeta.clear();
0177   m_statelzglobderivdgamma.clear();
0178 
0179   m_statelzlocderivd0.clear();
0180   m_statelzlocderivz0.clear();
0181   m_statelzlocderivphi.clear();
0182   m_statelzlocderivtheta.clear();
0183   m_statelzlocderivqop.clear();
0184 
0185   m_clusedge.clear();
0186   m_clusoverlap.clear();
0187   m_cluslx.clear();
0188   m_cluslz.clear();
0189   m_cluselx.clear();
0190   m_cluselz.clear();
0191   m_clusgr.clear();
0192   m_clusgx.clear();
0193   m_clusgy.clear();
0194   m_clusgz.clear();
0195   m_clusgxunmoved.clear();
0196   m_clusgyunmoved.clear();
0197   m_clusgzunmoved.clear();
0198   m_clusAdc.clear();
0199   m_clusMaxAdc.clear();
0200   m_cluslayer.clear();
0201 
0202   m_statelx.clear();
0203   m_statelz.clear();
0204   m_stateelx.clear();
0205   m_stateelz.clear();
0206   m_stategx.clear();
0207   m_stategy.clear();
0208   m_stategz.clear();
0209   m_statepx.clear();
0210   m_statepy.clear();
0211   m_statepz.clear();
0212   m_statepl.clear();
0213 }
0214 //____________________________________________________________________________..
0215 int TrackResiduals::process_event(PHCompositeNode* topNode)
0216 {
0217   auto *trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trackMapName);
0218   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
0219   auto *geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0220   auto *hitmap = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
0221   auto *tpcGeom =
0222       findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0223   auto *mvtxGeom = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
0224   auto *inttGeom = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
0225   auto *mmGeom = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MICROMEGAS_FULL");
0226 
0227   if (!mmGeom)
0228   {
0229     mmGeom = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MICROMEGAS");
0230   }
0231   if (!trackmap || !clustermap || !geometry || (!hitmap && m_doHits))
0232   {
0233     std::cout << "Missing node, can't continue" << std::endl;
0234     return Fun4AllReturnCodes::ABORTEVENT;
0235   }
0236   auto *gl1 = findNode::getClass<Gl1RawHit>(topNode, "GL1RAWHIT");
0237   if (gl1)
0238   {
0239     m_bco = gl1->get_bco();
0240     auto lbshift = m_bco << 24U;
0241     m_bcotr = lbshift >> 24U;
0242   }
0243   else
0244   {
0245     Gl1Packet* gl1PacketInfo = findNode::getClass<Gl1Packet>(topNode, "GL1RAWHIT");
0246     if (!gl1PacketInfo)
0247     {
0248       m_bco = std::numeric_limits<uint64_t>::quiet_NaN();
0249       m_bcotr = std::numeric_limits<uint64_t>::quiet_NaN();
0250     }
0251     m_firedTriggers.clear();
0252 
0253     if (gl1PacketInfo)
0254     {
0255       m_gl1BunchCrossing = gl1PacketInfo->getBunchNumber();
0256       uint64_t triggervec = gl1PacketInfo->getScaledVector();
0257       m_bco = gl1PacketInfo->getBCO();
0258       auto lbshift = m_bco << 24U;
0259       m_bcotr = lbshift >> 24U;
0260       for (int i = 0; i < 64; i++)
0261       {
0262         bool trig_decision = ((triggervec & 0x1U) == 0x1U);
0263         if (trig_decision)
0264         {
0265           m_firedTriggers.push_back(i);
0266         }
0267         triggervec = (triggervec >> 1U) & 0xffffffffU;
0268       }
0269     }
0270   }
0271   
0272   m_mbdvtxz = std::numeric_limits<float>::quiet_NaN();
0273 
0274   MbdVertexMap *mbdvertexmap = findNode::getClass<MbdVertexMap>(topNode, "MbdVertexMap");
0275   if(mbdvertexmap)
0276   {
0277     for (auto & it : *mbdvertexmap)
0278     {
0279       MbdVertex* mbdvertex = it.second;
0280       if (mbdvertex)
0281       {
0282         m_mbdvtxz = mbdvertex->get_z();
0283       }
0284     }
0285   }
0286   MbdPmtContainer* bbcpmts = findNode::getClass<MbdPmtContainer>(topNode, "MbdPmtContainer");
0287   m_totalmbd = 0;
0288   if (bbcpmts)
0289   {
0290     int nPMTs = bbcpmts->get_npmt();
0291     for (int i = 0; i < nPMTs; i++)
0292     {
0293       m_totalmbd += bbcpmts->get_pmt(i)->get_q();
0294     }
0295   }
0296   else
0297   {
0298     if (Verbosity() > 0)
0299     {
0300       std::cout << "TrackResiduals::process_event: Could not find MbdPmtContainer," << std::endl;
0301     }
0302   }
0303 
0304   m_ntpcclus = 0;
0305   if (Verbosity() > 1)
0306   {
0307     std::cout << "Track map size is " << trackmap->size() << std::endl;
0308   }
0309 
0310   if (m_doHits)
0311   {
0312     fillHitTree(hitmap, geometry, tpcGeom, mvtxGeom, inttGeom, mmGeom);
0313   }
0314 
0315   if (m_doClusters)
0316   {
0317     fillClusterTree(clustermap, geometry);
0318   }
0319 
0320   if (m_convertSeeds)
0321   {
0322     fillResidualTreeSeeds(topNode);
0323   }
0324   else
0325   {
0326     fillResidualTreeKF(topNode);
0327   }
0328 
0329   if (m_doVertex)
0330   {
0331     fillVertexTree(topNode);
0332   }
0333   if (m_doEventTree)
0334   {
0335     fillEventTree(topNode);
0336   }
0337   m_event++;
0338   clearClusterStateVectors();
0339   return Fun4AllReturnCodes::EVENT_OK;
0340 }
0341 
0342 
0343 void TrackResiduals::fillFailedSeedTree(PHCompositeNode* topNode, std::set<unsigned int>& tpc_seed_ids)
0344 {
0345   auto *tpcseedmap = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
0346   auto *trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trackMapName);
0347   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
0348   auto *geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0349   auto *silseedmap = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
0350   auto *svtxseedmap = findNode::getClass<TrackSeedContainer>(topNode, "SvtxTrackSeedContainer");
0351   auto *tpcGeo = findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0352 
0353   if (!tpcseedmap || !trackmap || !clustermap || !silseedmap || !svtxseedmap || !geometry)
0354   {
0355     std::cout << "Missing node, can't continue" << std::endl;
0356     return;
0357   }
0358 
0359   for (const auto& seed : *svtxseedmap)
0360   {
0361     if (!seed)
0362     {
0363       continue;
0364     }
0365     m_trackid = svtxseedmap->find(seed);
0366     auto tpcseedindex = seed->get_tpc_seed_index();
0367     if (tpc_seed_ids.find(tpcseedindex) != tpc_seed_ids.end())
0368     {
0369       continue;
0370     }
0371     auto siliconseedindex = seed->get_silicon_seed_index();
0372     auto *tpcseed = tpcseedmap->get(tpcseedindex);
0373     auto *silseed = silseedmap->get(siliconseedindex);
0374 
0375     int crossing = SHRT_MAX;
0376     if (silseed)
0377     {
0378       const auto si_pos = TrackSeedHelper::get_xyz(silseed);
0379       m_silseedx = si_pos.x();
0380       m_silseedy = si_pos.y();
0381       m_silseedz = si_pos.z();
0382       crossing = silseed->get_crossing();
0383     }
0384     else
0385     {
0386       const auto tpc_pos = TrackSeedHelper::get_xyz(tpcseed);
0387       m_tpcseedx = tpc_pos.x();
0388       m_tpcseedy = tpc_pos.y();
0389       m_tpcseedz = tpc_pos.z();
0390     }
0391 
0392     if (m_zeroField)
0393     {
0394       float pt = fabs(1. / tpcseed->get_qOverR()) * (0.3 / 100) * 0.01;
0395       float phi = tpcseed->get_phi();
0396       m_tpcseedpx = pt * std::cos(phi);
0397       m_tpcseedpy = pt * std::sin(phi);
0398       m_tpcseedpz = pt * std::cosh(tpcseed->get_eta()) * std::cos(tpcseed->get_theta());
0399     }
0400     else
0401     {
0402       m_tpcseedpx = tpcseed->get_px();
0403       m_tpcseedpy = tpcseed->get_py();
0404       m_tpcseedpz = tpcseed->get_pz();
0405     }
0406     m_tpcseedcharge = tpcseed->get_qOverR() > 0 ? 1 : -1;
0407     float layerThicknesses[4] = {0.0, 0.0, 0.0, 0.0};
0408     // These are randomly chosen layer thicknesses for the TPC, to get the
0409     // correct region thicknesses in an easy to pass way to the helper fxn
0410     layerThicknesses[0] = tpcGeo->GetLayerCellGeom(7)->get_thickness();
0411     layerThicknesses[1] = tpcGeo->GetLayerCellGeom(8)->get_thickness();
0412     layerThicknesses[2] = tpcGeo->GetLayerCellGeom(27)->get_thickness();
0413     layerThicknesses[3] = tpcGeo->GetLayerCellGeom(50)->get_thickness();
0414     
0415     m_dedx = TrackAnalysisUtils::calc_dedx(tpcseed, clustermap, geometry, layerThicknesses);
0416     m_nmaps = 0;
0417     m_nmapsstate = 0;
0418     m_nintt = 0;
0419     m_ninttstate = 0;
0420     m_ntpc = 0;
0421     m_ntpcstate = 0;
0422     m_nmms = 0;
0423     m_nmmsstate = 0;
0424     clearClusterStateVectors();
0425     for (auto *tseed : {silseed, tpcseed})
0426     {
0427       if (!tseed)
0428       {
0429         continue;
0430       }
0431       for (auto it = tseed->begin_cluster_keys(); it != tseed->end_cluster_keys(); ++it)
0432       {
0433         auto ckey = *it;
0434         auto *cluster = clustermap->findCluster(ckey);
0435         const Acts::Vector3 global = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(ckey, cluster, crossing);
0436         const auto local = geometry->getLocalCoords(ckey, cluster);
0437         m_cluslx.push_back(local.x());
0438         m_cluslz.push_back(local.y());
0439         m_clusgx.push_back(global.x());
0440         m_clusgy.push_back(global.y());
0441         m_clusgz.push_back(global.z());
0442         float cr = r(global.x(), global.y());
0443         if (global.y() < 0)
0444         {
0445           cr = -cr;
0446         }
0447         m_clusgr.push_back(cr);
0448         auto detid = TrkrDefs::getTrkrId(ckey);
0449         if (detid == TrkrDefs::TrkrId::mvtxId)
0450         {
0451           m_nmaps++;
0452         }
0453         else if (detid == TrkrDefs::TrkrId::inttId)
0454         {
0455           m_nintt++;
0456         }
0457         else if (detid == TrkrDefs::TrkrId::tpcId)
0458         {
0459           m_ntpc++;
0460         }
0461         else if (detid == TrkrDefs::TrkrId::micromegasId)
0462         {
0463           m_nmms++;
0464         }
0465       }
0466     }
0467     m_failedfits->Fill();
0468   }
0469 }
0470 void TrackResiduals::fillVertexTree(PHCompositeNode* topNode)
0471 {
0472   auto *svtxvertexmap = findNode::getClass<SvtxVertexMap>(topNode, "SvtxVertexMap");
0473   auto *trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trackMapName);
0474   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
0475   if (svtxvertexmap)
0476   {
0477     m_nvertices = svtxvertexmap->size();
0478     clearClusterStateVectors();
0479 
0480     for (const auto& [key, vertex] : *svtxvertexmap)
0481     {
0482       m_vertexid = key;
0483       m_vertex_crossing = vertex->get_beam_crossing();
0484       m_vx = vertex->get_x();
0485       m_vy = vertex->get_y();
0486       m_vz = vertex->get_z();
0487       m_ntracks = vertex->size_tracks();
0488 
0489       for (auto it = vertex->begin_tracks(); it != vertex->end_tracks(); ++it)
0490       {
0491         auto id = *it;
0492         auto *track = trackmap->find(id)->second;
0493         if (!track)
0494         {
0495           continue;
0496         }
0497         for (const auto& ckey : get_cluster_keys(track))
0498         {
0499           TrkrCluster* cluster = clustermap->findCluster(ckey);
0500 
0501           Acts::Vector3 clusglob = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, track->get_crossing());
0502 
0503           m_clusgx.push_back(clusglob.x());
0504           m_clusgy.push_back(clusglob.y());
0505           m_clusgz.push_back(clusglob.z());
0506           float clusr = r(clusglob.x(), clusglob.y());
0507           if (clusglob.y() < 0)
0508           {
0509             clusr = -clusr;
0510           }
0511           m_clusgr.push_back(clusr);
0512         }
0513       }
0514 
0515       m_vertextree->Fill();
0516     }
0517   }
0518 }
0519 
0520 float TrackResiduals::convertTimeToZ(ActsGeometry* geometry, TrkrDefs::cluskey cluster_key, TrkrCluster* cluster)
0521 {
0522   // must convert local Y from cluster average time of arival to local cluster z position
0523   Acts::Vector2 local = geometry->getLocalCoords(cluster_key, cluster);
0524   float z = local(1);
0525 
0526   return z;
0527 }
0528 void TrackResiduals::circleFitClusters(
0529     std::vector<TrkrDefs::cluskey>& keys,
0530     TrkrClusterContainer* clusters,
0531     const short int& crossing)
0532 {
0533   std::vector<Acts::Vector3> clusPos;
0534   std::vector<Acts::Vector3> global_vec;
0535   for (auto& key : keys)
0536   {
0537     auto *cluster = clusters->findCluster(key);
0538     const Acts::Vector3 pos = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing);
0539     clusPos.push_back(pos);
0540   }
0541   TrackFitUtils::position_vector_t yzpoints;
0542   TrackFitUtils::position_vector_t xypoints;
0543 
0544   for (auto& pos : clusPos)
0545   {
0546     float clusr = r(pos.x(), pos.y());
0547     // exclude silicon and tpot clusters for now
0548     if (std::fabs(clusr) > 80 || (m_linefitTPCOnly && std::fabs(clusr) < 20.))
0549     {
0550       continue;
0551     }
0552     xypoints.emplace_back(pos.x(), pos.y());
0553     yzpoints.emplace_back(pos.z(), pos.y());
0554     global_vec.push_back(pos);
0555   }
0556 
0557   auto xyparams = TrackFitUtils::line_fit(xypoints);
0558   auto yzLineParams = TrackFitUtils::line_fit(yzpoints);
0559   auto fitpars = TrackFitUtils::fitClusters(global_vec, keys, false);
0560   // auto fitpars = TrackFitUtils::fitClusters(global_vec, keys, !m_linefitTPCOnly);
0561   m_xyint = std::get<1>(xyparams);
0562   m_xyslope = std::get<0>(xyparams);
0563   m_yzint = std::get<1>(yzLineParams);
0564   m_yzslope = std::get<0>(yzLineParams);
0565   if (!fitpars.empty())
0566   {
0567     m_R = fitpars[0];
0568     m_X0 = fitpars[1];
0569     m_Y0 = fitpars[2];
0570     m_rzslope = fitpars[3];
0571     m_rzint = fitpars[4];
0572   }
0573   else
0574   {
0575     m_R = std::numeric_limits<float>::quiet_NaN();
0576     m_X0 = std::numeric_limits<float>::quiet_NaN();
0577     m_Y0 = std::numeric_limits<float>::quiet_NaN();
0578     m_rzslope = std::numeric_limits<float>::quiet_NaN();
0579     m_rzint = std::numeric_limits<float>::quiet_NaN();
0580   }
0581 }
0582 
0583 void TrackResiduals::lineFitClusters(std::vector<TrkrDefs::cluskey>& keys,
0584                                      TrkrClusterContainer* clusters,
0585                                      const short int& crossing)
0586 {
0587   std::vector<Acts::Vector3> clusPos;
0588   for (auto& key : keys)
0589   {
0590     auto *cluster = clusters->findCluster(key);
0591     const Acts::Vector3 pos = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing);
0592     clusPos.push_back(pos);
0593   }
0594   TrackFitUtils::position_vector_t xypoints;
0595   TrackFitUtils::position_vector_t rzpoints;
0596   TrackFitUtils::position_vector_t yzpoints;
0597   for (auto& pos : clusPos)
0598   {
0599     float clusr = r(pos.x(), pos.y());
0600     if (pos.y() < 0)
0601     {
0602       clusr *= -1;
0603     }
0604 
0605     // exclude 1d tpot clusters for now
0606 
0607     if (std::fabs(clusr) > 80 || (m_linefitTPCOnly && std::fabs(clusr) < 20.))
0608     {
0609       continue;
0610     }
0611 
0612     rzpoints.emplace_back(pos.z(), clusr);
0613     xypoints.emplace_back(pos.x(), pos.y());
0614     yzpoints.emplace_back(pos.z(), pos.y());
0615   }
0616 
0617   auto xyparams = TrackFitUtils::line_fit(xypoints);
0618   auto rzparams = TrackFitUtils::line_fit(rzpoints);
0619   auto yzparams = TrackFitUtils::line_fit(yzpoints);
0620   m_xyint = std::get<1>(xyparams);
0621   m_xyslope = std::get<0>(xyparams);
0622   m_rzint = std::get<1>(rzparams);
0623   m_rzslope = std::get<0>(rzparams);
0624   m_yzint = std::get<1>(yzparams);
0625   m_yzslope = std::get<0>(yzparams);
0626 }
0627 
0628 void TrackResiduals::fillClusterTree(TrkrClusterContainer* clusters,
0629                                      ActsGeometry* geometry)
0630 {
0631   if (clusters->size() < m_min_cluster_size)
0632   {
0633     return;
0634   }
0635   for (const auto& det : {TrkrDefs::TrkrId::mvtxId, TrkrDefs::TrkrId::inttId,
0636                     TrkrDefs::TrkrId::tpcId, TrkrDefs::TrkrId::micromegasId})
0637   {
0638     for (const auto& hitsetkey : clusters->getHitSetKeys(det))
0639     {
0640       m_scluslayer = TrkrDefs::getLayer(hitsetkey);
0641       auto range = clusters->getClusters(hitsetkey);
0642       for (auto iter = range.first; iter != range.second; ++iter)
0643       {
0644         auto key = iter->first;
0645         auto *cluster = clusters->findCluster(key);
0646         Acts::Vector3 glob;
0647         // NOT IMPLEMENTED YET
0648         // if (TrkrDefs::getTrkrId(key) == TrkrDefs::tpcId)
0649         // {
0650         //   glob = geometry->getGlobalPosition(key, cluster);  // corrections make no sense if crossing is not known
0651         // }
0652         // else
0653         // {
0654         //   glob = geometry->getGlobalPosition(key, cluster);
0655         // }
0656         glob = geometry->getGlobalPosition(key, cluster);
0657         m_sclusgx = glob.x();
0658         m_sclusgy = glob.y();
0659         m_sclusgz = glob.z();
0660         m_sclusgr = r(m_sclusgx, m_sclusgy);
0661         m_sclusphi = atan2(glob.y(), glob.x());
0662         m_scluseta = acos(glob.z() / std::sqrt(square(glob.x()) + square(glob.y()) + square(glob.z())));
0663         m_adc = cluster->getAdc();
0664         m_clusmaxadc = cluster->getMaxAdc();
0665         m_scluslx = cluster->getLocalX();
0666         m_scluslz = cluster->getLocalY();
0667         auto para_errors = m_clusErrPara.get_clusterv5_modified_error(cluster, m_sclusgr, key);
0668         m_phisize = cluster->getPhiSize();
0669         m_zsize = cluster->getZSize();
0670         m_scluselx = std::sqrt(para_errors.first);
0671         m_scluselz = std::sqrt(para_errors.second);
0672 
0673         //! Fill relevant geom info that is specific to subsystem
0674         switch (det)
0675         {
0676         case TrkrDefs::TrkrId::mvtxId:
0677           m_staveid = MvtxDefs::getStaveId(key);
0678           m_chipid = MvtxDefs::getChipId(key);
0679           m_strobeid = MvtxDefs::getStrobeId(key);
0680 
0681           m_ladderzid = std::numeric_limits<int>::quiet_NaN();
0682           m_ladderphiid = std::numeric_limits<int>::quiet_NaN();
0683           m_timebucket = std::numeric_limits<int>::quiet_NaN();
0684           m_clussector = std::numeric_limits<int>::quiet_NaN();
0685           m_side = std::numeric_limits<int>::quiet_NaN();
0686           m_segtype = std::numeric_limits<int>::quiet_NaN();
0687           m_tileid = std::numeric_limits<int>::quiet_NaN();
0688           break;
0689         case TrkrDefs::TrkrId::inttId:
0690           m_ladderzid = InttDefs::getLadderZId(key);
0691           m_ladderphiid = InttDefs::getLadderPhiId(key);
0692           m_timebucket = InttDefs::getTimeBucketId(key);
0693 
0694           m_staveid = std::numeric_limits<int>::quiet_NaN();
0695           m_chipid = std::numeric_limits<int>::quiet_NaN();
0696           m_strobeid = std::numeric_limits<int>::quiet_NaN();
0697           m_clussector = std::numeric_limits<int>::quiet_NaN();
0698           m_side = std::numeric_limits<int>::quiet_NaN();
0699           m_segtype = std::numeric_limits<int>::quiet_NaN();
0700           m_tileid = std::numeric_limits<int>::quiet_NaN();
0701           break;
0702         case TrkrDefs::TrkrId::tpcId:
0703           m_clussector = TpcDefs::getSectorId(key);
0704           m_side = TpcDefs::getSide(key);
0705 
0706           m_staveid = std::numeric_limits<int>::quiet_NaN();
0707           m_chipid = std::numeric_limits<int>::quiet_NaN();
0708           m_strobeid = std::numeric_limits<int>::quiet_NaN();
0709           m_ladderzid = std::numeric_limits<int>::quiet_NaN();
0710           m_ladderphiid = std::numeric_limits<int>::quiet_NaN();
0711           m_timebucket = std::numeric_limits<int>::quiet_NaN();
0712           m_segtype = std::numeric_limits<int>::quiet_NaN();
0713           m_tileid = std::numeric_limits<int>::quiet_NaN();
0714           break;
0715         case TrkrDefs::TrkrId::micromegasId:
0716           m_segtype = (int) MicromegasDefs::getSegmentationType(key);
0717           m_tileid = MicromegasDefs::getTileId(key);
0718 
0719           m_staveid = std::numeric_limits<int>::quiet_NaN();
0720           m_chipid = std::numeric_limits<int>::quiet_NaN();
0721           m_strobeid = std::numeric_limits<int>::quiet_NaN();
0722           m_ladderzid = std::numeric_limits<int>::quiet_NaN();
0723           m_ladderphiid = std::numeric_limits<int>::quiet_NaN();
0724           m_timebucket = std::numeric_limits<int>::quiet_NaN();
0725           m_clussector = std::numeric_limits<int>::quiet_NaN();
0726           m_side = std::numeric_limits<int>::quiet_NaN();
0727           break;
0728         default:
0729           break;
0730         }
0731 
0732         m_clustree->Fill();
0733       }
0734     }
0735   }
0736 }
0737 
0738 //____________________________________________________________________________..
0739 int TrackResiduals::End(PHCompositeNode* /*unused*/)
0740 {
0741   m_outfile->cd();
0742   m_tree->Write();
0743   if (m_doClusters)
0744   {
0745     m_clustree->Write();
0746   }
0747   if (m_doHits)
0748   {
0749     m_hittree->Write();
0750   }
0751   if (m_doVertex)
0752   {
0753     m_vertextree->Write();
0754   }
0755   if (m_doFailedSeeds)
0756   {
0757     m_failedfits->Write();
0758   }
0759   if (m_doEventTree)
0760   {
0761     m_eventtree->Write();
0762   }
0763   m_outfile->Close();
0764 
0765   return Fun4AllReturnCodes::EVENT_OK;
0766 }
0767 void TrackResiduals::fillHitTree(TrkrHitSetContainer* hitmap,
0768                                  ActsGeometry* geometry,
0769                                  PHG4TpcGeomContainer* tpcGeom,
0770                                  PHG4CylinderGeomContainer* mvtxGeom,
0771                                  PHG4CylinderGeomContainer* inttGeom,
0772                                  PHG4CylinderGeomContainer* mmGeom)
0773 {
0774   if (!tpcGeom || !mvtxGeom || !inttGeom || !mmGeom)
0775   {
0776     std::cout << PHWHERE << "missing hit map, can't continue with hit tree"
0777               << std::endl;
0778     return;
0779   }
0780   TrkrHitSetContainer::ConstRange all_hitsets = hitmap->getHitSets();
0781   for (TrkrHitSetContainer::ConstIterator hitsetiter = all_hitsets.first;
0782        hitsetiter != all_hitsets.second;
0783        ++hitsetiter)
0784   {
0785     m_hitsetkey = hitsetiter->first;
0786     TrkrHitSet* hitset = hitsetiter->second;
0787 
0788     m_hitlayer = TrkrDefs::getLayer(m_hitsetkey);
0789     auto det = TrkrDefs::getTrkrId(m_hitsetkey);
0790     //! Fill relevant geom info that is specific to subsystem
0791     switch (det)
0792     {
0793     case TrkrDefs::TrkrId::mvtxId:
0794     {
0795       m_staveid = MvtxDefs::getStaveId(m_hitsetkey);
0796       m_chipid = MvtxDefs::getChipId(m_hitsetkey);
0797       m_strobeid = MvtxDefs::getStrobeId(m_hitsetkey);
0798 
0799       m_ladderzid = std::numeric_limits<int>::quiet_NaN();
0800       m_ladderphiid = std::numeric_limits<int>::quiet_NaN();
0801       m_timebucket = std::numeric_limits<int>::quiet_NaN();
0802       m_sector = std::numeric_limits<int>::quiet_NaN();
0803       m_side = std::numeric_limits<int>::quiet_NaN();
0804       m_segtype = std::numeric_limits<int>::quiet_NaN();
0805       m_tileid = std::numeric_limits<int>::quiet_NaN();
0806       break;
0807     }
0808     case TrkrDefs::TrkrId::inttId:
0809     {
0810       m_ladderzid = InttDefs::getLadderZId(m_hitsetkey);
0811       m_ladderphiid = InttDefs::getLadderPhiId(m_hitsetkey);
0812       m_timebucket = InttDefs::getTimeBucketId(m_hitsetkey);
0813 
0814       m_staveid = std::numeric_limits<int>::quiet_NaN();
0815       m_chipid = std::numeric_limits<int>::quiet_NaN();
0816       m_strobeid = std::numeric_limits<int>::quiet_NaN();
0817       m_sector = std::numeric_limits<int>::quiet_NaN();
0818       m_side = std::numeric_limits<int>::quiet_NaN();
0819       m_segtype = std::numeric_limits<int>::quiet_NaN();
0820       m_tileid = std::numeric_limits<int>::quiet_NaN();
0821       break;
0822     }
0823     case TrkrDefs::TrkrId::tpcId:
0824     {
0825       m_sector = TpcDefs::getSectorId(m_hitsetkey);
0826       m_side = TpcDefs::getSide(m_hitsetkey);
0827 
0828       m_staveid = std::numeric_limits<int>::quiet_NaN();
0829       m_chipid = std::numeric_limits<int>::quiet_NaN();
0830       m_strobeid = std::numeric_limits<int>::quiet_NaN();
0831       m_ladderzid = std::numeric_limits<int>::quiet_NaN();
0832       m_ladderphiid = std::numeric_limits<int>::quiet_NaN();
0833       m_timebucket = std::numeric_limits<int>::quiet_NaN();
0834       m_segtype = std::numeric_limits<int>::quiet_NaN();
0835       m_tileid = std::numeric_limits<int>::quiet_NaN();
0836 
0837       break;
0838     }
0839     case TrkrDefs::TrkrId::micromegasId:
0840     {
0841       m_segtype = (int) MicromegasDefs::getSegmentationType(m_hitsetkey);
0842       m_tileid = MicromegasDefs::getTileId(m_hitsetkey);
0843 
0844       m_staveid = std::numeric_limits<int>::quiet_NaN();
0845       m_chipid = std::numeric_limits<int>::quiet_NaN();
0846       m_strobeid = std::numeric_limits<int>::quiet_NaN();
0847       m_ladderzid = std::numeric_limits<int>::quiet_NaN();
0848       m_ladderphiid = std::numeric_limits<int>::quiet_NaN();
0849       m_timebucket = std::numeric_limits<int>::quiet_NaN();
0850       m_sector = std::numeric_limits<int>::quiet_NaN();
0851       m_side = std::numeric_limits<int>::quiet_NaN();
0852       break;
0853     }
0854     default:
0855       break;
0856     }
0857 
0858     // Got all stave/ladder/sector/tile info, now get the actual hit info
0859     auto hitrangei = hitset->getHits();
0860     for (TrkrHitSet::ConstIterator hitr = hitrangei.first;
0861          hitr != hitrangei.second;
0862          ++hitr)
0863     {
0864       auto hitkey = hitr->first;
0865       auto *hit = hitr->second;
0866       m_adc = hit->getAdc();
0867 
0868       switch (det)
0869       {
0870       case TrkrDefs::TrkrId::mvtxId:
0871       {
0872         m_row = MvtxDefs::getRow(hitkey);
0873         m_col = MvtxDefs::getCol(hitkey);
0874         auto *layergeom = dynamic_cast<CylinderGeom_Mvtx*>(mvtxGeom->GetLayerGeom(m_hitlayer));
0875         auto local_coords = layergeom->get_local_coords_from_pixel(m_row, m_col);
0876         TVector2 local;
0877         local.SetX(local_coords.X());
0878         local.SetY(local_coords.Z());
0879         auto surf = geometry->maps().getSiliconSurface(m_hitsetkey);
0880         auto glob = CylinderGeom_MvtxHelper::get_world_from_local_coords(surf, geometry, local);
0881         m_hitgx = glob.X();
0882         m_hitgy = glob.Y();
0883         m_hitgz = glob.Z();
0884 
0885         m_segtype = std::numeric_limits<int>::quiet_NaN();
0886         m_tileid = std::numeric_limits<int>::quiet_NaN();
0887         m_strip = std::numeric_limits<int>::quiet_NaN();
0888         m_hitpad = std::numeric_limits<int>::quiet_NaN();
0889         m_hittbin = std::numeric_limits<int>::quiet_NaN();
0890 
0891         m_zdriftlength = std::numeric_limits<float>::quiet_NaN();
0892         break;
0893       }
0894       case TrkrDefs::TrkrId::inttId:
0895       {
0896         m_row = InttDefs::getRow(hitkey);
0897         m_col = InttDefs::getCol(hitkey);
0898         auto *geom = dynamic_cast<CylinderGeomIntt*>(inttGeom->GetLayerGeom(m_hitlayer));
0899         double local_hit_loc[3] = {0, 0, 0};
0900         geom->find_strip_center_localcoords(m_ladderzid, m_row, m_col, local_hit_loc);
0901         auto surf = geometry->maps().getSiliconSurface(m_hitsetkey);
0902         TVector2 local;
0903         local.SetX(local_hit_loc[1]);
0904         local.SetY(local_hit_loc[2]);
0905         auto glob = CylinderGeomInttHelper::get_world_from_local_coords(surf, geometry, local);
0906 
0907         m_hitgx = glob.X();
0908         m_hitgy = glob.Y();
0909         m_hitgz = glob.Z();
0910         m_segtype = std::numeric_limits<int>::quiet_NaN();
0911         m_tileid = std::numeric_limits<int>::quiet_NaN();
0912         m_strip = std::numeric_limits<int>::quiet_NaN();
0913         m_hitpad = std::numeric_limits<int>::quiet_NaN();
0914         m_hittbin = std::numeric_limits<int>::quiet_NaN();
0915         m_zdriftlength = std::numeric_limits<float>::quiet_NaN();
0916         break;
0917       }
0918       case TrkrDefs::TrkrId::tpcId:
0919       {
0920         m_row = std::numeric_limits<int>::quiet_NaN();
0921         m_col = std::numeric_limits<int>::quiet_NaN();
0922         m_segtype = std::numeric_limits<int>::quiet_NaN();
0923         m_tileid = std::numeric_limits<int>::quiet_NaN();
0924         m_strip = std::numeric_limits<int>::quiet_NaN();
0925 
0926         m_hitpad = TpcDefs::getPad(hitkey);
0927         m_hittbin = TpcDefs::getTBin(hitkey);
0928 
0929         auto *geoLayer = tpcGeom->GetLayerCellGeom(m_hitlayer);
0930         auto phi = geoLayer->get_phicenter(m_hitpad, m_side);
0931         auto radius = geoLayer->get_radius();
0932         float AdcClockPeriod = geoLayer->get_zstep();
0933         auto glob = geometry->getGlobalPositionTpc(m_hitsetkey, hitkey, phi, radius, AdcClockPeriod);
0934         m_hitgx = glob.x();
0935         m_hitgy = glob.y();
0936         m_hitgz = glob.z();
0937 
0938         break;
0939       }
0940       case TrkrDefs::TrkrId::micromegasId:
0941       {
0942         auto *const layergeom = dynamic_cast<CylinderGeomMicromegas*>(mmGeom->GetLayerGeom(m_hitlayer));
0943         m_strip = MicromegasDefs::getStrip(hitkey);
0944         const auto global_coord = layergeom->get_world_coordinates(m_tileid, geometry, m_strip);
0945         m_hitgx = global_coord.X();
0946         m_hitgy = global_coord.Y();
0947         m_hitgz = global_coord.Z();
0948         m_row = std::numeric_limits<int>::quiet_NaN();
0949         m_col = std::numeric_limits<int>::quiet_NaN();
0950         m_segtype = std::numeric_limits<int>::quiet_NaN();
0951         m_tileid = std::numeric_limits<int>::quiet_NaN();
0952         m_hitpad = std::numeric_limits<int>::quiet_NaN();
0953         m_hittbin = std::numeric_limits<int>::quiet_NaN();
0954 
0955         m_zdriftlength = std::numeric_limits<float>::quiet_NaN();
0956       }
0957       default:
0958         break;
0959       }
0960 
0961       m_hittree->Fill();
0962     }
0963   }
0964 }
0965 
0966 void TrackResiduals::fillClusterBranchesKF(TrkrDefs::cluskey ckey, SvtxTrack* track,
0967                                            const std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>>& global,
0968                                            PHCompositeNode* topNode)
0969 {
0970   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
0971   auto *geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0972 
0973   auto global_moved = global;  // if use transient transforms for distortion correction
0974   if (m_use_clustermover)
0975   {
0976     // move the corrected cluster positions back to the original readout surface
0977     global_moved = m_clusterMover.processTrack(global);
0978   }
0979 
0980   ActsTransformations transformer;
0981   TrkrCluster* cluster = clustermap->findCluster(ckey);
0982 
0983   // loop over global vectors and get this cluster
0984   Acts::Vector3 clusglob(0, 0, 0);
0985   for (const auto& pair : global)
0986   {
0987     auto thiskey = pair.first;
0988     clusglob = pair.second;
0989     if (thiskey == ckey)
0990     {
0991       break;
0992     }
0993   }
0994 
0995   Acts::Vector3 clusglob_moved(0, 0, 0);
0996   for (const auto& pair : global_moved)
0997   {
0998     auto thiskey = pair.first;
0999     clusglob_moved = pair.second;
1000     if (thiskey == ckey)
1001     {
1002       break;
1003     }
1004   }
1005 
1006   unsigned int layer = TrkrDefs::getLayer(ckey);
1007 
1008   if (Verbosity() > 1)
1009   {
1010     std::cout << "Called :fillClusterBranchesKF for ckey " << ckey << " layer " << layer << " trackid " << track->get_id() << " clusglob x " << clusglob(0) << " y " << clusglob(1) << " z " << clusglob(2) << std::endl;
1011   }
1012 
1013   switch (TrkrDefs::getTrkrId(ckey))
1014   {
1015   case TrkrDefs::mvtxId:
1016     m_clstave.push_back(MvtxDefs::getStaveId(ckey));
1017     m_clchip.push_back(MvtxDefs::getChipId(ckey));
1018     m_nmaps++;
1019     break;
1020   case TrkrDefs::inttId:
1021     m_clladderz.push_back(InttDefs::getLadderZId(ckey));
1022     m_clladderphi.push_back(InttDefs::getLadderPhiId(ckey));
1023     m_nintt++;
1024     break;
1025   case TrkrDefs::tpcId:
1026     m_ntpc++;
1027     m_clsector.push_back(TpcDefs::getSectorId(ckey));
1028     m_clside.push_back(TpcDefs::getSide(ckey));
1029     break;
1030   case TrkrDefs::micromegasId:
1031     m_nmms++;
1032     m_tileid = MicromegasDefs::getTileId(ckey);
1033     break;
1034   default:
1035     std::cout << PHWHERE << " unknown key " << ckey << std::endl;
1036     gSystem->Exit(1);
1037     exit(1);
1038   }
1039 
1040   SvtxTrackState* state = nullptr;
1041 
1042   // the track states from the Acts fit are fitted to fully corrected clusters, and are on the surface
1043   for (auto state_iter = track->begin_states();
1044        state_iter != track->end_states();
1045        ++state_iter)
1046   {
1047     SvtxTrackState* tstate = state_iter->second;
1048     auto stateckey = tstate->get_cluskey();
1049     if (stateckey == ckey)
1050     {
1051       state = tstate;
1052       break;
1053     }
1054   }
1055 
1056   if (!state)
1057   {
1058     if (Verbosity() > 1)
1059     {
1060       std::cout << "   no state for cluster " << ckey << "  in layer " << layer << std::endl;
1061     }
1062   }
1063   else
1064   {
1065     switch (TrkrDefs::getTrkrId(ckey))
1066     {
1067     case TrkrDefs::mvtxId:
1068       m_nmapsstate++;
1069       break;
1070     case TrkrDefs::inttId:
1071       m_ninttstate++;
1072       break;
1073     case TrkrDefs::tpcId:
1074       m_ntpcstate++;
1075       break;
1076     case TrkrDefs::micromegasId:
1077       m_nmmsstate++;
1078       break;
1079     default:
1080       std::cout << PHWHERE << " unknown key " << ckey << std::endl;
1081       gSystem->Exit(1);
1082       exit(1);
1083     }
1084   }
1085 
1086   m_cluskeys.push_back(ckey);
1087 
1088   //! have cluster and state, fill vectors
1089   m_clusedge.push_back(cluster->getEdge());
1090   m_clusoverlap.push_back(cluster->getOverlap());
1091 
1092   // get new local coords from moved cluster
1093   Surface surf = geometry->maps().getSurface(ckey, cluster);
1094   Surface surf_ideal = geometry->maps().getSurface(ckey, cluster);  // Unchanged by distortion corrections
1095   // if this is a TPC cluster, the crossing correction may have moved it across the central membrane, check the surface
1096   auto trkrid = TrkrDefs::getTrkrId(ckey);
1097   if (trkrid == TrkrDefs::tpcId)
1098   {
1099     TrkrDefs::hitsetkey hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
1100     TrkrDefs::subsurfkey new_subsurfkey = 0;
1101     surf = geometry->get_tpc_surface_from_coords(hitsetkey, clusglob_moved, new_subsurfkey);
1102   }
1103   if (!surf)
1104   {
1105     if (Verbosity() > 2)
1106     {
1107       std::cout << " Failed to find surface for cluskey " << ckey << std::endl;
1108     }
1109     return;
1110   }
1111 
1112   // get local coordinates
1113   Acts::Vector2 loc;
1114   loc = geometry->getLocalCoords(ckey, cluster, m_crossing);
1115   if (m_use_clustermover)
1116   {
1117     // in this case we get local coords from transform of corrected global coords
1118     clusglob_moved *= Acts::UnitConstants::cm;  // we want mm for transformations
1119     Acts::Vector3 normal = surf->normal(geometry->geometry().getGeoContext(),
1120                                         Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1));
1121     auto local = surf->globalToLocal(geometry->geometry().getGeoContext(),
1122                                      clusglob_moved, normal);
1123     if (local.ok())
1124     {
1125       loc = local.value() / Acts::UnitConstants::cm;
1126     }
1127     else
1128     {
1129       // otherwise take the manual calculation for the TPC
1130       // doing it this way just avoids the bounds check that occurs in the surface class method
1131       Acts::Vector3 loct = surf->transform(geometry->geometry().getGeoContext()).inverse() * clusglob_moved;  // global is in mm
1132       loct /= Acts::UnitConstants::cm;
1133 
1134       loc(0) = loct(0);
1135       loc(1) = loct(1);
1136     }
1137     clusglob_moved /= Acts::UnitConstants::cm;  // we want cm for the tree
1138   }
1139 
1140   m_cluslx.push_back(loc.x());
1141   m_cluslz.push_back(loc.y());
1142 
1143   if (Verbosity() > 2)
1144   {
1145     std::cout << "Trackresiduals cluster (cm): localX " << loc.x() << " localY " << loc.y() << std::endl
1146               << " global.x " << clusglob_moved(0) << " global.y " << clusglob_moved(1) << " global.z " << clusglob_moved(2) << std::endl;
1147   }
1148 
1149   float clusr = r(clusglob_moved.x(), clusglob_moved.y());
1150   auto para_errors = m_clusErrPara.get_clusterv5_modified_error(cluster,
1151                                                                 clusr, ckey);
1152   m_cluselx.push_back(sqrt(para_errors.first));
1153   m_cluselz.push_back(sqrt(para_errors.second));
1154   m_clusgx.push_back(clusglob_moved.x());
1155   m_clusgy.push_back(clusglob_moved.y());
1156   m_clusgr.push_back(clusglob_moved.y() > 0 ? clusr : -1 * clusr);
1157   m_clusgz.push_back(clusglob_moved.z());
1158   m_clusgxunmoved.push_back(clusglob.x());
1159   m_clusgyunmoved.push_back(clusglob.y());
1160   m_clusgzunmoved.push_back(clusglob.z());
1161   m_clusAdc.push_back(cluster->getAdc());
1162   m_clusMaxAdc.push_back(cluster->getMaxAdc());
1163   m_cluslayer.push_back(TrkrDefs::getLayer(ckey));
1164   m_clusphisize.push_back(cluster->getPhiSize());
1165   m_cluszsize.push_back(cluster->getZSize());
1166 
1167   auto misaligncenter = surf->center(geometry->geometry().getGeoContext());
1168   auto misalignnorm = -1 * surf->normal(geometry->geometry().getGeoContext(), Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1));
1169   auto misrot = surf->transform(geometry->geometry().getGeoContext()).rotation();
1170 
1171   float mgamma = atan2(-misrot(1, 0), misrot(0, 0));
1172   float mbeta = -asin(misrot(0, 1));
1173   float malpha = atan2(misrot(1, 1), misrot(2, 1));
1174 
1175   //! Switch to get ideal transforms
1176   alignmentTransformationContainer::use_alignment = false;
1177   auto idealcenter = surf_ideal->center(geometry->geometry().getGeoContext());  //mm
1178   auto idealnorm = -1 * surf_ideal->normal(geometry->geometry().getGeoContext(), Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1));
1179 
1180   if(Verbosity() > 3 && layer == 44)
1181     {
1182       std::vector<double> surfbounds = surf_ideal->bounds().values();  // mm
1183       std::cout << "resids: layer " << layer << " ideal center z " << idealcenter.z() << " mm " << std::endl;
1184       std::cout << " surface bounds " << surfbounds[0] << "  " << surfbounds[1] << " mm " << std::endl;
1185       alignmentTransformationContainer::use_alignment = false;
1186       Acts::Transform3 transform = surf_ideal->transform(geometry->geometry().getGeoContext());
1187       std::cout << "Ideal transform is:" << std::endl;
1188       std::cout << transform.matrix() << std::endl;
1189       alignmentTransformationContainer::use_alignment = true;
1190       Acts::Transform3 transform1 = surf_ideal->transform(geometry->geometry().getGeoContext());
1191       std::cout << "Alignment transform is:" << std::endl;
1192       std::cout << transform1.matrix() << std::endl;
1193 
1194     }
1195   
1196   // replace the corrected moved cluster local position with the readout position from ideal geometry for now
1197   // This allows us to see the distortion corrections by subtracting this uncorrected position
1198   // revisit this when looking at the alignment case
1199   //  Acts::Vector3 ideal_local(loc.x(), loc.y(), 0.0);
1200   auto nominal_loc = geometry->getLocalCoords(ckey, cluster);
1201   Acts::Vector3 ideal_local(nominal_loc.x(), nominal_loc.y(), 0.0);
1202   Acts::Vector3 ideal_glob = surf_ideal->transform(geometry->geometry().getGeoContext()) * (ideal_local * Acts::UnitConstants::cm);
1203   auto idealrot = surf_ideal->transform(geometry->geometry().getGeoContext()).rotation();
1204 
1205   //! These calculations are taken from the wikipedia page for Euler angles,
1206   //! under the Tait-Bryan angle explanation. Formulas for the angles
1207   //! calculated from the rotation matrices depending on what order the
1208   //! rotation matrix is constructed are given
1209   //! They need to be modified to conform to the Acts basis of (x,z,y), for
1210   //! which the wiki page expects (x,y,z). This includes swapping the sign
1211   //! of some elements to account for the permutation
1212   //! https://en.wikipedia.org/wiki/Euler_angles#Conversion_to_other_orientation_representations
1213   float igamma = atan2(-idealrot(1, 0), idealrot(0, 0));
1214   float ibeta = -asin(idealrot(0, 1));
1215   float ialpha = atan2(idealrot(1, 1), idealrot(2, 1));
1216 
1217   alignmentTransformationContainer::use_alignment = true;
1218 
1219   idealcenter /= Acts::UnitConstants::cm;
1220   misaligncenter /= Acts::UnitConstants::cm;
1221   ideal_glob /= Acts::UnitConstants::cm;
1222 
1223   m_idealsurfalpha.push_back(ialpha);
1224   m_idealsurfbeta.push_back(ibeta);
1225   m_idealsurfgamma.push_back(igamma);
1226   m_missurfalpha.push_back(malpha);
1227   m_missurfbeta.push_back(mbeta);
1228   m_missurfgamma.push_back(mgamma);
1229 
1230   m_idealsurfcenterx.push_back(idealcenter.x());
1231   m_idealsurfcentery.push_back(idealcenter.y());
1232   m_idealsurfcenterz.push_back(idealcenter.z());
1233   m_idealsurfnormx.push_back(idealnorm.x());
1234   m_idealsurfnormy.push_back(idealnorm.y());
1235   m_idealsurfnormz.push_back(idealnorm.z());
1236   m_missurfcenterx.push_back(misaligncenter.x());
1237   m_missurfcentery.push_back(misaligncenter.y());
1238   m_missurfcenterz.push_back(misaligncenter.z());
1239   m_missurfnormx.push_back(misalignnorm.x());
1240   m_missurfnormy.push_back(misalignnorm.y());
1241   m_missurfnormz.push_back(misalignnorm.z());
1242   m_clusgxideal.push_back(ideal_glob.x());
1243   m_clusgyideal.push_back(ideal_glob.y());
1244   m_clusgzideal.push_back(ideal_glob.z());
1245 
1246   if (state)
1247   {
1248     Acts::Vector3 stateglob(state->get_x(), state->get_y(), state->get_z());
1249     Acts::Vector2 stateloc(state->get_localX(), state->get_localY());
1250 
1251     if (Verbosity() > 2)
1252     {
1253       std::cout << "Trackresiduals state (cm): localX " << stateloc(0) << " localY " << stateloc(1) << std::endl
1254                 << " stateglobx " << stateglob(0) << " stategloby " << stateglob(1) << " stateglobz " << stateglob(2) << std::endl;
1255     }
1256 
1257     const auto actscov =
1258         transformer.rotateSvtxTrackCovToActs(state);
1259 
1260     m_statelx.push_back(stateloc(0));
1261     m_statelz.push_back(stateloc(1));
1262     m_stateelx.push_back(std::sqrt(actscov(Acts::eBoundLoc0, Acts::eBoundLoc0)) / Acts::UnitConstants::cm);
1263     m_stateelz.push_back(std::sqrt(actscov(Acts::eBoundLoc1, Acts::eBoundLoc1)) / Acts::UnitConstants::cm);
1264     m_stategx.push_back(state->get_x());
1265     m_stategy.push_back(state->get_y());
1266     m_stategz.push_back(state->get_z());
1267     m_statepx.push_back(state->get_px());
1268     m_statepy.push_back(state->get_py());
1269     m_statepz.push_back(state->get_pz());
1270     m_statepl.push_back(state->get_pathlength());
1271   }
1272   else
1273   {
1274     // cluster has no corresponding state, set state variables to NaNs
1275     m_statelx.push_back(std::numeric_limits<float>::quiet_NaN());
1276     m_statelz.push_back(std::numeric_limits<float>::quiet_NaN());
1277     m_stategx.push_back(std::numeric_limits<float>::quiet_NaN());
1278     m_stategy.push_back(std::numeric_limits<float>::quiet_NaN());
1279     m_stategz.push_back(std::numeric_limits<float>::quiet_NaN());
1280     m_statepx.push_back(std::numeric_limits<float>::quiet_NaN());
1281     m_statepy.push_back(std::numeric_limits<float>::quiet_NaN());
1282     m_statepz.push_back(std::numeric_limits<float>::quiet_NaN());
1283     m_statepl.push_back(std::numeric_limits<float>::quiet_NaN());
1284   }
1285 
1286   if (Verbosity() > 2)
1287   {
1288     if (ideal_glob(2) > 0)
1289     {
1290       double xideal = ideal_glob.x();
1291       double yideal = ideal_glob.y();
1292       double zideal = ideal_glob.z();
1293 
1294       double xunmoved = clusglob.x();
1295       double yunmoved = clusglob.y();
1296       double zunmoved = clusglob.z();
1297 
1298       double xmoved = clusglob_moved.x();
1299       double ymoved = clusglob_moved.y();
1300       double zmoved = clusglob_moved.z();
1301 
1302       double this_radius_ideal = sqrt((xideal * xideal) + (yideal * yideal));
1303       double this_radius_unmoved = sqrt((xunmoved * xunmoved) + (yunmoved * yunmoved));
1304 
1305       double this_phi_unmoved = atan2(yunmoved, xunmoved);
1306       double this_phi_ideal = atan2(yideal, xideal);
1307       double this_phi_moved = atan2(ymoved, xmoved);
1308 
1309       std::cout << " global:  unmoved " << xunmoved << "  " << yunmoved << "  " << zunmoved << " this_phi " << this_phi_unmoved << " radius_unmoved " << this_radius_unmoved
1310                 << " r*phi " << this_radius_ideal * this_phi_unmoved << std::endl;
1311       std::cout << "              global: ideal " << xideal << "  " << yideal << "  " << zideal << " this_phi_ideal " << this_phi_ideal << " radius_ideal " << this_radius_ideal
1312                 << " r*phi " << this_radius_ideal * this_phi_ideal << std::endl;
1313       std::cout << "              global: moved " << xmoved << "  " << ymoved << "  " << zmoved << " phi_moved " << this_phi_moved
1314                 << " r*phi " << this_radius_ideal * this_phi_moved << std::endl;
1315       std::cout << "                        d_radius " << this_radius_unmoved - this_radius_ideal << " clusgz " << zideal << " r*dphi " << this_radius_ideal * (this_phi_unmoved - this_phi_ideal) << std::endl;
1316     }
1317   }
1318 }
1319 
1320 void TrackResiduals::fillClusterBranchesSeeds(TrkrDefs::cluskey ckey,  // SvtxTrack* track,
1321                                               const std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>>& global,
1322                                               PHCompositeNode* topNode)
1323 {
1324   // The input map global contains the corrected cluster positions - NOT moved back to the surfacer.
1325   // When filling the residualtree:
1326   //    clusgx etc are the corrected - but not moved back to the surface - cluster positions
1327   //    clugxideal etc are the completely uncorrected cluster positions - they do not even have crossing corrections
1328   // CircleFitClusters is called in this method. It applies TOF, crossing, and all distortion corrections before fitting
1329   //    stategx etc are at the intersection point of the helical fit with the cluster surface
1330 
1331   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
1332   auto *geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1333 
1334   auto global_moved = global;
1335   if (m_use_clustermover)
1336   {
1337     // move the corrected cluster positions back to the original readout surface
1338     global_moved = m_clusterMover.processTrack(global);
1339   }
1340 
1341   TrkrCluster* cluster = clustermap->findCluster(ckey);
1342 
1343   // loop over global vectors and get this cluster
1344   Acts::Vector3 clusglob(0, 0, 0);
1345   for (const auto& pair : global)
1346   {
1347     auto thiskey = pair.first;
1348     clusglob = pair.second;
1349     if (thiskey == ckey)
1350     {
1351       break;
1352     }
1353   }
1354   Acts::Vector3 clusglob_moved(0, 0, 0);
1355   for (const auto& pair : global_moved)
1356   {
1357     auto thiskey = pair.first;
1358     clusglob_moved = pair.second;
1359     if (thiskey == ckey)
1360     {
1361       break;
1362     }
1363   }
1364 
1365   switch (TrkrDefs::getTrkrId(ckey))
1366   {
1367   case TrkrDefs::mvtxId:
1368     m_nmaps++;
1369     m_clstave.push_back(MvtxDefs::getStaveId(ckey));
1370     m_clchip.push_back(MvtxDefs::getChipId(ckey));
1371     m_clladderz.push_back(-1);
1372     m_clladderphi.push_back(-1);
1373     m_clsector.push_back(-1);
1374     m_clside.push_back(-1);
1375     break;
1376   case TrkrDefs::inttId:
1377     m_clstave.push_back(-1);
1378     m_clchip.push_back(-1);
1379     m_clladderz.push_back(InttDefs::getLadderZId(ckey));
1380     m_clladderphi.push_back(InttDefs::getLadderPhiId(ckey));
1381     m_clsector.push_back(-1);
1382     m_clside.push_back(-1);
1383     m_nintt++;
1384     break;
1385   case TrkrDefs::tpcId:
1386     m_ntpc++;
1387     m_clstave.push_back(-1);
1388     m_clchip.push_back(-1);
1389     m_clladderz.push_back(-1);
1390     m_clladderphi.push_back(-1);
1391     m_clsector.push_back(TpcDefs::getSectorId(ckey));
1392     m_clside.push_back(TpcDefs::getSide(ckey));
1393     break;
1394   case TrkrDefs::micromegasId:
1395     m_nmms++;
1396     m_tileid = MicromegasDefs::getTileId(ckey);
1397     m_clstave.push_back(-1);
1398     m_clchip.push_back(-1);
1399     m_clladderz.push_back(-1);
1400     m_clladderphi.push_back(-1);
1401     m_clsector.push_back(-1);
1402     m_clside.push_back(-1);
1403     break;
1404   default:
1405     std::cout << PHWHERE << " unknown key " << ckey << std::endl;
1406     gSystem->Exit(1);
1407     exit(1);
1408   }
1409 
1410   m_cluskeys.push_back(ckey);
1411 
1412   if (Verbosity() > 1)
1413   {
1414     std::cout << "Called fillClusterBranchesSeeds for ckey " << ckey << " clusglob x " << clusglob(0) << " y " << clusglob(1) << " z " << clusglob(2) << std::endl;
1415   }
1416 
1417   //! have cluster and state, fill vectors
1418   m_clusedge.push_back(cluster->getEdge());
1419   m_clusoverlap.push_back(cluster->getOverlap());
1420 
1421   // This is the nominal position of the cluster in local coords, completely uncorrected - is that what we want?
1422   auto loc = geometry->getLocalCoords(ckey, cluster);
1423 
1424   m_cluslx.push_back(loc.x());
1425   m_cluslz.push_back(loc.y());
1426 
1427   float clusr = r(clusglob_moved.x(), clusglob_moved.y());
1428   auto para_errors = m_clusErrPara.get_clusterv5_modified_error(cluster,
1429                                                                 clusr, ckey);
1430   m_cluselx.push_back(sqrt(para_errors.first));
1431   m_cluselz.push_back(sqrt(para_errors.second));
1432   m_clusgx.push_back(clusglob_moved.x());
1433   m_clusgy.push_back(clusglob_moved.y());
1434   m_clusgr.push_back(clusglob_moved.y() > 0 ? clusr : -1 * clusr);
1435   m_clusgz.push_back(clusglob_moved.z());
1436   m_clusgxunmoved.push_back(clusglob.x());
1437   m_clusgyunmoved.push_back(clusglob.y());
1438   m_clusgzunmoved.push_back(clusglob.z());
1439   m_clusAdc.push_back(cluster->getAdc());
1440   m_clusMaxAdc.push_back(cluster->getMaxAdc());
1441   m_cluslayer.push_back(TrkrDefs::getLayer(ckey));
1442   m_clusphisize.push_back(cluster->getPhiSize());
1443   m_cluszsize.push_back(cluster->getZSize());
1444 
1445   if (Verbosity() > 1)
1446   {
1447     std::cout << "Track state/clus in layer "
1448               << (unsigned int) TrkrDefs::getLayer(ckey) << " with pos "
1449               << clusglob.transpose() << std::endl;
1450   }
1451 
1452   auto surf = geometry->maps().getSurface(ckey, cluster);
1453 
1454   auto misaligncenter = surf->center(geometry->geometry().getGeoContext());
1455   auto misalignnorm = -1 * surf->normal(geometry->geometry().getGeoContext(), Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1));
1456   auto misrot = surf->transform(geometry->geometry().getGeoContext()).rotation();
1457 
1458   float mgamma = atan2(-misrot(1, 0), misrot(0, 0));
1459   float mbeta = -asin(misrot(0, 1));
1460   float malpha = atan2(misrot(1, 1), misrot(2, 1));
1461 
1462   //! Switch to get ideal transforms
1463   alignmentTransformationContainer::use_alignment = false;
1464   auto idealcenter = surf->center(geometry->geometry().getGeoContext());
1465   auto idealnorm = -1 * surf->normal(geometry->geometry().getGeoContext(), Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1));
1466   Acts::Vector3 ideal_local(loc.x(), loc.y(), 0.0);
1467   Acts::Vector3 ideal_glob = surf->transform(geometry->geometry().getGeoContext()) * (ideal_local * Acts::UnitConstants::cm);
1468   auto idealrot = surf->transform(geometry->geometry().getGeoContext()).rotation();
1469 
1470   //! These calculations are taken from the wikipedia page for Euler angles,
1471   //! under the Tait-Bryan angle explanation. Formulas for the angles
1472   //! calculated from the rotation matrices depending on what order the
1473   //! rotation matrix is constructed are given
1474   //! They need to be modified to conform to the Acts basis of (x,z,y), for
1475   //! which the wiki page expects (x,y,z). This includes swapping the sign
1476   //! of some elements to account for the permutation
1477   //! https://en.wikipedia.org/wiki/Euler_angles#Conversion_to_other_orientation_representations
1478   float igamma = atan2(-idealrot(1, 0), idealrot(0, 0));
1479   float ibeta = -asin(idealrot(0, 1));
1480   float ialpha = atan2(idealrot(1, 1), idealrot(2, 1));
1481 
1482   alignmentTransformationContainer::use_alignment = true;
1483 
1484   idealcenter /= Acts::UnitConstants::cm;
1485   misaligncenter /= Acts::UnitConstants::cm;
1486   ideal_glob /= Acts::UnitConstants::cm;
1487 
1488   m_idealsurfalpha.push_back(ialpha);
1489   m_idealsurfbeta.push_back(ibeta);
1490   m_idealsurfgamma.push_back(igamma);
1491   m_missurfalpha.push_back(malpha);
1492   m_missurfbeta.push_back(mbeta);
1493   m_missurfgamma.push_back(mgamma);
1494 
1495   m_idealsurfcenterx.push_back(idealcenter.x());
1496   m_idealsurfcentery.push_back(idealcenter.y());
1497   m_idealsurfcenterz.push_back(idealcenter.z());
1498   m_idealsurfnormx.push_back(idealnorm.x());
1499   m_idealsurfnormy.push_back(idealnorm.y());
1500   m_idealsurfnormz.push_back(idealnorm.z());
1501   m_missurfcenterx.push_back(misaligncenter.x());
1502   m_missurfcentery.push_back(misaligncenter.y());
1503   m_missurfcenterz.push_back(misaligncenter.z());
1504   m_missurfnormx.push_back(misalignnorm.x());
1505   m_missurfnormy.push_back(misalignnorm.y());
1506   m_missurfnormz.push_back(misalignnorm.z());
1507   m_clusgxideal.push_back(ideal_glob.x());
1508   m_clusgyideal.push_back(ideal_glob.y());
1509   m_clusgzideal.push_back(ideal_glob.z());
1510 
1511   if (m_zeroField)
1512   {
1513     fillStatesWithLineFit(ckey, cluster, geometry);
1514   }
1515   else
1516   {
1517     fillStatesWithCircleFit(ckey, cluster, clusglob, geometry);
1518   }
1519 
1520   //! skip filling the state information if a state is not there
1521   //! or we just ran the seeding. Fill with Nans to maintain the
1522   //! 1-to-1 mapping between cluster/state vectors
1523   m_statepx.push_back(std::numeric_limits<float>::quiet_NaN());
1524   m_statepy.push_back(std::numeric_limits<float>::quiet_NaN());
1525   m_statepz.push_back(std::numeric_limits<float>::quiet_NaN());
1526   m_statepl.push_back(std::numeric_limits<float>::quiet_NaN());
1527   return;
1528 }
1529 
1530 void TrackResiduals::fillStatesWithCircleFit(const TrkrDefs::cluskey& key,
1531                                              TrkrCluster* cluster, Acts::Vector3& glob, ActsGeometry* geometry)
1532 {
1533   auto surf = geometry->maps().getSurface(key, cluster);
1534   std::vector<float> fitpars;
1535   fitpars.push_back(m_R);
1536   fitpars.push_back(m_X0);
1537   fitpars.push_back(m_Y0);
1538   fitpars.push_back(m_rzslope);
1539   fitpars.push_back(m_rzint);
1540 
1541   auto intersection = TrackFitUtils::get_helix_surface_intersection(surf, fitpars, glob, geometry);
1542   m_stategx.push_back(intersection.x());
1543   m_stategy.push_back(intersection.y());
1544   m_stategz.push_back(intersection.z());
1545 
1546   auto result = surf->globalToLocal(geometry->geometry().getGeoContext(), intersection, Acts::Vector3(1, 1, 1));
1547   if (result.ok())
1548   {
1549     auto loc = result.value() / Acts::UnitConstants::cm;
1550     m_statelx.push_back(loc.x());
1551     m_statelz.push_back(loc.y());
1552   }
1553   else
1554   {
1555     auto local = (surf->transform(geometry->geometry().getGeoContext())).inverse() * (intersection * Acts::UnitConstants::cm);
1556     local /= Acts::UnitConstants::cm;
1557     m_statelx.push_back(local.x());
1558     m_statelz.push_back(local.y());
1559   }
1560 }
1561 void TrackResiduals::fillStatesWithLineFit(const TrkrDefs::cluskey& key,
1562                                            TrkrCluster* cluster, ActsGeometry* geometry)
1563 {
1564   auto intersection = TrackFitUtils::surface_3Dline_intersection(key, cluster, geometry, m_xyslope,
1565                                                                  m_xyint, m_yzslope, m_yzint);
1566 
1567   auto surf = geometry->maps().getSurface(key, cluster);
1568   Acts::Vector3 surfnorm = surf->normal(geometry->geometry().getGeoContext(), Acts::Vector3(1, 1, 1), Acts::Vector3(1, 1, 1));
1569   if (!std::isnan(intersection.x()))
1570   {
1571     auto locstateres = surf->globalToLocal(geometry->geometry().getGeoContext(),
1572                                            intersection * Acts::UnitConstants::cm,
1573                                            surfnorm);
1574     if (locstateres.ok())
1575     {
1576       Acts::Vector2 loc = locstateres.value() / Acts::UnitConstants::cm;
1577       m_statelx.push_back(loc(0));
1578       m_statelz.push_back(loc(1));
1579     }
1580     else
1581     {
1582       Acts::Vector3 loct = surf->transform(geometry->geometry().getGeoContext()).inverse() * (intersection * Acts::UnitConstants::cm);
1583       loct /= Acts::UnitConstants::cm;
1584       m_statelx.push_back(loct(0));
1585       m_statelz.push_back(loct(1));
1586     }
1587     m_stategx.push_back(intersection.x());
1588     m_stategy.push_back(intersection.y());
1589     m_stategz.push_back(intersection.z());
1590   }
1591   else
1592   {
1593     //! otherwise the line is parallel to the surface, should not happen if
1594     //! we have a cluster on the surface but just fill the state vecs with nan
1595     m_statelx.push_back(std::numeric_limits<float>::quiet_NaN());
1596     m_statelz.push_back(std::numeric_limits<float>::quiet_NaN());
1597     m_stategx.push_back(std::numeric_limits<float>::quiet_NaN());
1598     m_stategy.push_back(std::numeric_limits<float>::quiet_NaN());
1599     m_stategz.push_back(std::numeric_limits<float>::quiet_NaN());
1600   }
1601 }
1602 void TrackResiduals::createBranches()
1603 {
1604   if (m_doEventTree)
1605   {
1606     m_eventtree = new TTree("eventtree", "A tree with all hits");
1607     m_eventtree->Branch("run", &m_runnumber, "m_runnumber/I");
1608     m_eventtree->Branch("segment", &m_segment, "m_segment/I");
1609     m_eventtree->Branch("event", &m_event, "m_event/I");
1610     m_eventtree->Branch("gl1bco", &m_bco, "m_bco/I");
1611     m_eventtree->Branch("nmvtx", &m_nmvtx_all, "m_nmvtx_all/I");
1612     m_eventtree->Branch("nintt", &m_nintt_all, "m_nintt_all/I");
1613     m_eventtree->Branch("nhittpc0", &m_ntpc_hits0, "m_ntpc_hits0/I");
1614     m_eventtree->Branch("nhittpc1", &m_ntpc_hits1, "m_ntpc_hits1/I");
1615     m_eventtree->Branch("nclustpc0", &m_ntpc_clus0, "m_ntpc_clus0/I");
1616     m_eventtree->Branch("nclustpc1", &m_ntpc_clus1, "m_ntpc_clus1/I");
1617     m_eventtree->Branch("nmms", &m_nmms_all, "m_nmms_all/I");
1618     m_eventtree->Branch("nsiseed", &m_nsiseed, "m_nsiseed/I");
1619     m_eventtree->Branch("ntpcseed", &m_ntpcseed, "m_ntpcseed/I");
1620     m_eventtree->Branch("ntracks", &m_ntracks_all, "m_ntracks_all/I");
1621     m_eventtree->Branch("mbdcharge",&m_totalmbd, "m_totalmbd/F");
1622     m_eventtree->Branch("ntpcClusSector", &m_ntpc_clus_sector);
1623   }
1624 
1625   m_failedfits = new TTree("failedfits", "tree with seeds from failed Acts fits");
1626   m_failedfits->Branch("run", &m_runnumber, "m_runnumber/I");
1627   m_failedfits->Branch("segment", &m_segment, "m_segment/I");
1628   m_failedfits->Branch("trackid", &m_trackid, "m_trackid/I");
1629   m_failedfits->Branch("event", &m_event, "m_event/I");
1630   m_failedfits->Branch("silseedx", &m_silseedx, "m_silseedx/F");
1631   m_failedfits->Branch("silseedy", &m_silseedy, "m_silseedy/F");
1632   m_failedfits->Branch("silseedz", &m_silseedz, "m_silseedz/F");
1633   m_failedfits->Branch("tpcseedx", &m_tpcseedx, "m_tpcseedx/F");
1634   m_failedfits->Branch("tpcseedy", &m_tpcseedy, "m_tpcseedy/F");
1635   m_failedfits->Branch("tpcseedz", &m_tpcseedz, "m_tpcseedz/F");
1636   m_failedfits->Branch("tpcseedpx", &m_tpcseedpx, "m_tpcseedpx/F");
1637   m_failedfits->Branch("tpcseedpy", &m_tpcseedpy, "m_tpcseedpy/F");
1638   m_failedfits->Branch("tpcseedpz", &m_tpcseedpz, "m_tpcseedpz/F");
1639   m_failedfits->Branch("tpcseedcharge", &m_tpcseedcharge, "m_tpcseedcharge/I");
1640   m_failedfits->Branch("dedx", &m_dedx, "m_dedx/F");
1641   m_failedfits->Branch("nmaps", &m_nmaps, "m_nmaps/I");
1642   m_failedfits->Branch("nintt", &m_nintt, "m_nintt/I");
1643   m_failedfits->Branch("ntpc", &m_ntpc, "m_ntpc/I");
1644   m_failedfits->Branch("nmms", &m_nmms, "m_nmms/I");
1645   m_failedfits->Branch("gx", &m_clusgx);
1646   m_failedfits->Branch("gy", &m_clusgy);
1647   m_failedfits->Branch("gz", &m_clusgz);
1648   m_failedfits->Branch("gr", &m_clusgr);
1649   m_failedfits->Branch("lx", &m_cluslx);
1650   m_failedfits->Branch("lz", &m_cluslz);
1651 
1652   m_vertextree = new TTree("vertextree", "tree with vertices");
1653   m_vertextree->Branch("run", &m_runnumber, "m_runnumber/I");
1654   m_vertextree->Branch("segment", &m_segment, "m_segment/I");
1655   m_vertextree->Branch("event", &m_event, "m_event/I");
1656   m_vertextree->Branch("firedTriggers", &m_firedTriggers);
1657   m_vertextree->Branch("gl1BunchCrossing", &m_gl1BunchCrossing, "m_gl1BunchCrossing/l");
1658   m_vertextree->Branch("gl1bco", &m_bco, "m_bco/l");
1659   m_vertextree->Branch("trbco", &m_bcotr, "m_bcotr/l");
1660   m_vertextree->Branch("vertexid", &m_vertexid);
1661   m_vertextree->Branch("vertex_crossing", &m_vertex_crossing, "m_vertex_crossing/I");
1662   m_vertextree->Branch("mbdzvtx", &m_mbdvtxz, "m_mbdvtxz/F");
1663   m_vertextree->Branch("vx", &m_vx, "m_vx/F");
1664   m_vertextree->Branch("vy", &m_vy, "m_vy/F");
1665   m_vertextree->Branch("vz", &m_vz, "m_vz/F");
1666   m_vertextree->Branch("ntracks", &m_ntracks, "m_ntracks/I");
1667   m_vertextree->Branch("nvertices", &m_nvertices, "m_nvertices/I");
1668   m_vertextree->Branch("gx", &m_clusgx);
1669   m_vertextree->Branch("gy", &m_clusgy);
1670   m_vertextree->Branch("gz", &m_clusgz);
1671   m_vertextree->Branch("gr", &m_clusgr);
1672   m_vertextree->Branch("mbdcharge", &m_totalmbd, "m_totalmbd/F");
1673 
1674   m_hittree = new TTree("hittree", "A tree with all hits");
1675   m_hittree->Branch("run", &m_runnumber, "m_runnumber/I");
1676   m_hittree->Branch("segment", &m_segment, "m_segment/I");
1677   m_hittree->Branch("event", &m_event, "m_event/I");
1678   m_hittree->Branch("gl1bco", &m_bco, "m_bco/l");
1679   m_hittree->Branch("hitsetkey", &m_hitsetkey, "m_hitsetkey/i");
1680   m_hittree->Branch("gx", &m_hitgx, "m_hitgx/F");
1681   m_hittree->Branch("gy", &m_hitgy, "m_hitgy/F");
1682   m_hittree->Branch("gz", &m_hitgz, "m_hitgz/F");
1683   m_hittree->Branch("layer", &m_hitlayer, "m_hitlayer/I");
1684   m_hittree->Branch("sector", &m_sector, "m_sector/I");
1685   m_hittree->Branch("side", &m_side, "m_side/I");
1686   m_hittree->Branch("stave", &m_staveid, "m_staveid/I");
1687   m_hittree->Branch("chip", &m_chipid, "m_chipid/I");
1688   m_hittree->Branch("strobe", &m_strobeid, "m_strobeid/I");
1689   m_hittree->Branch("ladderz", &m_ladderzid, "m_ladderzid/I");
1690   m_hittree->Branch("ladderphi", &m_ladderphiid, "m_ladderphiid/I");
1691   m_hittree->Branch("timebucket", &m_timebucket, "m_timebucket/I");
1692   m_hittree->Branch("pad", &m_hitpad, "m_hitpad/I");
1693   m_hittree->Branch("tbin", &m_hittbin, "m_hittbin/I");
1694   m_hittree->Branch("col", &m_col, "m_col/I");
1695   m_hittree->Branch("row", &m_row, "m_row/I");
1696   m_hittree->Branch("segtype", &m_segtype, "m_segtype/I");
1697   m_hittree->Branch("tile", &m_tileid, "m_tileid/I");
1698   m_hittree->Branch("strip", &m_strip, "m_strip/I");
1699   m_hittree->Branch("adc", &m_adc, "m_adc/F");
1700   m_hittree->Branch("zdriftlength", &m_zdriftlength, "m_zdriftlength/F");
1701   m_hittree->Branch("mbdcharge",&m_totalmbd, "m_totalmbd/F");
1702 
1703   m_clustree = new TTree("clustertree", "A tree with all clusters");
1704   m_clustree->Branch("run", &m_runnumber, "m_runnumber/I");
1705   m_clustree->Branch("segment", &m_segment, "m_segment/I");
1706   m_clustree->Branch("event", &m_event, "m_event/I");
1707   m_clustree->Branch("gl1bco", &m_bco, "m_bco/l");
1708   m_clustree->Branch("lx", &m_scluslx, "m_scluslx/F");
1709   m_clustree->Branch("lz", &m_scluslz, "m_scluslz/F");
1710   m_clustree->Branch("gx", &m_sclusgx, "m_sclusgx/F");
1711   m_clustree->Branch("gy", &m_sclusgy, "m_sclusgy/F");
1712   m_clustree->Branch("gz", &m_sclusgz, "m_sclusgz/F");
1713   m_clustree->Branch("phi", &m_sclusphi, "m_sclusphi/F");
1714   m_clustree->Branch("eta", &m_scluseta, "m_scluseta/F");
1715   m_clustree->Branch("adc", &m_adc, "m_adc/F");
1716   m_clustree->Branch("phisize", &m_phisize, "m_phisize/I");
1717   m_clustree->Branch("zsize", &m_zsize, "m_zsize/I");
1718   m_clustree->Branch("erphi", &m_scluselx, "m_scluselx/F");
1719   m_clustree->Branch("ez", &m_scluselz, "m_scluselz/F");
1720   m_clustree->Branch("maxadc", &m_clusmaxadc, "m_clusmaxadc/F");
1721   m_clustree->Branch("sector", &m_clussector, "m_clussector/I");
1722   m_clustree->Branch("side", &m_side, "m_side/I");
1723   m_clustree->Branch("stave", &m_staveid, "m_staveid/I");
1724   m_clustree->Branch("chip", &m_chipid, "m_chipid/I");
1725   m_clustree->Branch("strobe", &m_strobeid, "m_strobeid/I");
1726   m_clustree->Branch("ladderz", &m_ladderzid, "m_ladderzid/I");
1727   m_clustree->Branch("ladderphi", &m_ladderphiid, "m_ladderphiid/I");
1728   m_clustree->Branch("timebucket", &m_timebucket, "m_timebucket/I");
1729   m_clustree->Branch("segtype", &m_segtype, "m_segtype/I");
1730   m_clustree->Branch("tile", &m_tileid, "m_tileid/I");
1731 
1732   m_tree = new TTree("residualtree", "A tree with track, cluster, and state info");
1733   m_tree->Branch("run", &m_runnumber, "m_runnumber/I");
1734   m_tree->Branch("segment", &m_segment, "m_segment/I");
1735   m_tree->Branch("event", &m_event, "m_event/I");
1736   m_tree->Branch("mbdcharge",&m_totalmbd, "m_totalmbd/F");
1737   m_tree->Branch("mbdzvtx", &m_mbdvtxz, "m_mbdvtxz/F");
1738   m_tree->Branch("firedTriggers", &m_firedTriggers);
1739   m_tree->Branch("gl1BunchCrossing", &m_gl1BunchCrossing, "m_gl1BunchCrossing/l");
1740   m_tree->Branch("trackid", &m_trackid, "m_trackid/I");
1741   m_tree->Branch("tpcid", &m_tpcid, "m_tpcid/I");
1742   m_tree->Branch("silid", &m_silid, "m_silid/I");
1743   m_tree->Branch("gl1bco", &m_bco, "m_bco/l");
1744   m_tree->Branch("crossing", &m_crossing, "m_crossing/I");
1745   m_tree->Branch("crossing_estimate", &m_crossing_estimate, "m_crossing_estimate/I");
1746   m_tree->Branch("silseedit",&m_silseedit, "m_silseedit/I");
1747   m_tree->Branch("silseedx", &m_silseedx, "m_silseedx/F");
1748   m_tree->Branch("silseedy", &m_silseedy, "m_silseedy/F");
1749   m_tree->Branch("silseedz", &m_silseedz, "m_silseedz/F");
1750   m_tree->Branch("silseedpx", &m_silseedpx, "m_silseedpx/F");
1751   m_tree->Branch("silseedpy", &m_silseedpy, "m_silseedpy/F");
1752   m_tree->Branch("silseedpz", &m_silseedpz, "m_silseedpz/F");
1753   m_tree->Branch("silseedphi", &m_silseedphi, "m_silseedphi/F");
1754   m_tree->Branch("silseedeta", &m_silseedeta, "m_silseedeta/F");
1755   m_tree->Branch("silseedcharge", &m_silseedcharge, "m_silseedcharge/I");
1756   m_tree->Branch("tpcseedx", &m_tpcseedx, "m_tpcseedx/F");
1757   m_tree->Branch("tpcseedy", &m_tpcseedy, "m_tpcseedy/F");
1758   m_tree->Branch("tpcseedz", &m_tpcseedz, "m_tpcseedz/F");
1759   m_tree->Branch("tpcseedpx", &m_tpcseedpx, "m_tpcseedpx/F");
1760   m_tree->Branch("tpcseedpy", &m_tpcseedpy, "m_tpcseedpy/F");
1761   m_tree->Branch("tpcseedpz", &m_tpcseedpz, "m_tpcseedpz/F");
1762   m_tree->Branch("tpcseedphi", &m_tpcseedphi, "m_tpcseedphi/F");
1763   m_tree->Branch("tpcseedeta", &m_tpcseedeta, "m_tpcseedeta/F");
1764   m_tree->Branch("tpcseedcharge", &m_tpcseedcharge, "m_tpcseedcharge/I");
1765   m_tree->Branch("dedx", &m_dedx, "m_dedx/F");
1766   m_tree->Branch("tracklength", &m_tracklength, "m_tracklength/F");
1767   m_tree->Branch("px", &m_px, "m_px/F");
1768   m_tree->Branch("py", &m_py, "m_py/F");
1769   m_tree->Branch("pz", &m_pz, "m_pz/F");
1770   m_tree->Branch("pt", &m_pt, "m_pt/F");
1771   m_tree->Branch("eta", &m_eta, "m_eta/F");
1772   m_tree->Branch("phi", &m_phi, "m_phi/F");
1773   m_tree->Branch("deltapt", &m_deltapt, "m_deltapt/F");
1774   m_tree->Branch("charge", &m_charge, "m_charge/I");
1775   m_tree->Branch("quality", &m_quality, "m_quality/F");
1776   m_tree->Branch("ndf", &m_ndf, "m_ndf/F");
1777   m_tree->Branch("nhits", &m_nhits, "m_nhits/I");
1778   m_tree->Branch("nmaps", &m_nmaps, "m_nmaps/I");
1779   m_tree->Branch("nmapsstate", &m_nmapsstate, "m_nmapsstate/I");
1780   m_tree->Branch("nintt", &m_nintt, "m_nintt/I");
1781   m_tree->Branch("ninttstate", &m_ninttstate, "m_ninttstate/I");
1782   m_tree->Branch("ntpc", &m_ntpc, "m_ntpc/I");
1783   m_tree->Branch("ntpcstate", &m_ntpcstate, "m_ntpcstate/I");
1784   m_tree->Branch("nmms", &m_nmms, "m_nmms/I");
1785   m_tree->Branch("nmmsstate", &m_nmmsstate, "m_nmmsstate/I");
1786   m_tree->Branch("tile", &m_tileid, "m_tileid/I");
1787   m_tree->Branch("vertexid", &m_vertexid);
1788   m_tree->Branch("vertex_crossing", &m_vertex_crossing, "m_vertex_crossing/I");
1789   m_tree->Branch("vx", &m_vx, "m_vx/F");
1790   m_tree->Branch("vy", &m_vy, "m_vy/F");
1791   m_tree->Branch("vz", &m_vz, "m_vz/F");
1792   m_tree->Branch("vertex_ntracks", &m_vertex_ntracks, "m_vertex_ntracks/I");
1793   m_tree->Branch("pcax", &m_pcax, "m_pcax/F");
1794   m_tree->Branch("pcay", &m_pcay, "m_pcay/F");
1795   m_tree->Branch("pcaz", &m_pcaz, "m_pcaz/F");
1796   m_tree->Branch("rzslope", &m_rzslope, "m_rzslope/F");
1797   m_tree->Branch("xyslope", &m_xyslope, "m_xyslope/F");
1798   m_tree->Branch("yzslope", &m_yzslope, "m_yzslope/F");
1799   m_tree->Branch("rzint", &m_rzint, "m_rzint/F");
1800   m_tree->Branch("xyint", &m_xyint, "m_xyint/F");
1801   m_tree->Branch("yzint", &m_yzint, "m_yzint/F");
1802   m_tree->Branch("R", &m_R, "m_R/F");
1803   m_tree->Branch("X0", &m_X0, "m_X0/F");
1804   m_tree->Branch("Y0", &m_Y0, "m_Y0/F");
1805   m_tree->Branch("dcaxy", &m_dcaxy, "m_dcaxy/F");
1806   m_tree->Branch("dcaz", &m_dcaz, "m_dcaz/F");
1807 
1808   m_tree->Branch("cluslayer", &m_cluslayer);
1809   m_tree->Branch("clusstave", &m_clstave);
1810   m_tree->Branch("cluschip", &m_clchip);
1811   m_tree->Branch("clusladderz", &m_clladderz);
1812   m_tree->Branch("clusladderphi", &m_clladderphi);
1813   m_tree->Branch("clussector", &m_clsector);
1814   m_tree->Branch("clusside", &m_clside);
1815   m_tree->Branch("cluskeys", &m_cluskeys);
1816   m_tree->Branch("clusedge", &m_clusedge);
1817   m_tree->Branch("clusoverlap", &m_clusoverlap);
1818   m_tree->Branch("cluslx", &m_cluslx);
1819   m_tree->Branch("cluslz", &m_cluslz);
1820   m_tree->Branch("cluselx", &m_cluselx);
1821   m_tree->Branch("cluselz", &m_cluselz);
1822   m_tree->Branch("clusgx", &m_clusgx);
1823   m_tree->Branch("clusgy", &m_clusgy);
1824   m_tree->Branch("clusgz", &m_clusgz);
1825   m_tree->Branch("clusgr", &m_clusgr);
1826   if (m_doAlignment)
1827   {
1828     m_tree->Branch("clusgxunmoved", &m_clusgxunmoved);
1829     m_tree->Branch("clusgyunmoved", &m_clusgyunmoved);
1830     m_tree->Branch("clusgzunmoved", &m_clusgzunmoved);
1831   }
1832   m_tree->Branch("clusAdc", &m_clusAdc);
1833   m_tree->Branch("clusMaxAdc", &m_clusMaxAdc);
1834   m_tree->Branch("clusphisize", &m_clusphisize);
1835   m_tree->Branch("cluszsize", &m_cluszsize);
1836 
1837   if (m_doAlignment)
1838   {
1839     m_tree->Branch("idealsurfcenterx", &m_idealsurfcenterx);
1840     m_tree->Branch("idealsurfcentery", &m_idealsurfcentery);
1841     m_tree->Branch("idealsurfcenterz", &m_idealsurfcenterz);
1842     m_tree->Branch("idealsurfnormx", &m_idealsurfnormx);
1843     m_tree->Branch("idealsurfnormy", &m_idealsurfnormy);
1844     m_tree->Branch("idealsurfnormz", &m_idealsurfnormz);
1845     m_tree->Branch("missurfcenterx", &m_missurfcenterx);
1846     m_tree->Branch("missurfcentery", &m_missurfcentery);
1847     m_tree->Branch("missurfcenterz", &m_missurfcenterz);
1848     m_tree->Branch("missurfnormx", &m_missurfnormx);
1849     m_tree->Branch("missurfnormy", &m_missurfnormy);
1850     m_tree->Branch("missurfnormz", &m_missurfnormz);
1851     m_tree->Branch("clusgxideal", &m_clusgxideal);
1852     m_tree->Branch("clusgyideal", &m_clusgyideal);
1853     m_tree->Branch("clusgzideal", &m_clusgzideal);
1854     m_tree->Branch("missurfalpha", &m_missurfalpha);
1855     m_tree->Branch("missurfbeta", &m_missurfbeta);
1856     m_tree->Branch("missurfgamma", &m_missurfgamma);
1857     m_tree->Branch("idealsurfalpha", &m_idealsurfalpha);
1858     m_tree->Branch("idealsurfbeta", &m_idealsurfbeta);
1859     m_tree->Branch("idealsurfgamma", &m_idealsurfgamma);
1860   }
1861 
1862   m_tree->Branch("statelx", &m_statelx);
1863   m_tree->Branch("statelz", &m_statelz);
1864   m_tree->Branch("stateelx", &m_stateelx);
1865   m_tree->Branch("stateelz", &m_stateelz);
1866   m_tree->Branch("stategx", &m_stategx);
1867   m_tree->Branch("stategy", &m_stategy);
1868   m_tree->Branch("stategz", &m_stategz);
1869   m_tree->Branch("statepx", &m_statepx);
1870   m_tree->Branch("statepy", &m_statepy);
1871   m_tree->Branch("statepz", &m_statepz);
1872   m_tree->Branch("statepl", &m_statepl);
1873 
1874   if (m_doAlignment)
1875   {
1876     m_tree->Branch("statelxglobderivdx", &m_statelxglobderivdx);
1877     m_tree->Branch("statelxglobderivdy", &m_statelxglobderivdy);
1878     m_tree->Branch("statelxglobderivdz", &m_statelxglobderivdz);
1879     m_tree->Branch("statelxglobderivdalpha", &m_statelxglobderivdalpha);
1880     m_tree->Branch("statelxglobderivdbeta", &m_statelxglobderivdbeta);
1881     m_tree->Branch("statelxglobderivdgamma", &m_statelxglobderivdgamma);
1882 
1883     m_tree->Branch("statelxlocderivd0", &m_statelxlocderivd0);
1884     m_tree->Branch("statelxlocderivz0", &m_statelxlocderivz0);
1885     m_tree->Branch("statelxlocderivphi", &m_statelxlocderivphi);
1886     m_tree->Branch("statelxlocderivtheta", &m_statelxlocderivtheta);
1887     m_tree->Branch("statelxlocderivqop", &m_statelxlocderivqop);
1888 
1889     m_tree->Branch("statelzglobderivdx", &m_statelzglobderivdx);
1890     m_tree->Branch("statelzglobderivdy", &m_statelzglobderivdy);
1891     m_tree->Branch("statelzglobderivdz", &m_statelzglobderivdz);
1892     m_tree->Branch("statelzglobderivdalpha", &m_statelzglobderivdalpha);
1893     m_tree->Branch("statelzglobderivdbeta", &m_statelzglobderivdbeta);
1894     m_tree->Branch("statelzglobderivdgamma", &m_statelzglobderivdgamma);
1895 
1896     m_tree->Branch("statelzlocderivd0", &m_statelzlocderivd0);
1897     m_tree->Branch("statelzlocderivz0", &m_statelzlocderivz0);
1898     m_tree->Branch("statelzlocderivphi", &m_statelzlocderivphi);
1899     m_tree->Branch("statelzlocderivtheta", &m_statelzlocderivtheta);
1900     m_tree->Branch("statelzlocderivqop", &m_statelzlocderivqop);
1901   }
1902 }
1903 
1904 void TrackResiduals::fillResidualTreeKF(PHCompositeNode* topNode)
1905 {
1906   auto *silseedmap = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
1907   auto *tpcseedmap = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
1908   auto *tpcGeom =
1909       findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
1910   auto *trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trackMapName);
1911   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
1912   auto *vertexmap = findNode::getClass<SvtxVertexMap>(topNode, "SvtxVertexMap");
1913   auto *alignmentmap = findNode::getClass<SvtxAlignmentStateMap>(topNode, m_alignmentMapName);
1914   auto *geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1915   std::set<unsigned int> tpc_seed_ids;
1916   for (const auto& [key, track] : *trackmap)
1917   {
1918     if (!track)
1919     {
1920       continue;
1921     }
1922     m_trackid = track->get_id();
1923 
1924     m_crossing = track->get_crossing();
1925     m_crossing_estimate = SHRT_MAX;
1926     m_px = track->get_px();
1927     m_py = track->get_py();
1928     m_pz = track->get_pz();
1929 
1930     m_pt = std::sqrt(square(m_px) + square(m_py));
1931     m_eta = std::atanh(m_pz / std::sqrt(square(m_pt) + square(m_pz)));
1932     m_phi = std::atan2(m_py, m_px);
1933     float CVxx = track->get_error(3, 3);
1934     float CVxy = track->get_error(3, 4);
1935     float CVyy = track->get_error(4, 4);
1936     m_deltapt = std::sqrt((CVxx * square(m_px) + 2 * CVxy * m_px * m_py + CVyy * square(m_py)) / (square(m_px) + square(m_py)));
1937 
1938     m_charge = track->get_charge();
1939     m_quality = track->get_quality();
1940     m_chisq = track->get_chisq();
1941     m_ndf = track->get_ndf();
1942 
1943     m_nmaps = 0;
1944     m_nmapsstate = 0;
1945     m_nintt = 0;
1946     m_ninttstate = 0;
1947     m_ntpc = 0;
1948     m_ntpcstate = 0;
1949     m_nmms = 0;
1950     m_nmmsstate = 0;
1951     m_silid = std::numeric_limits<unsigned int>::quiet_NaN();
1952     m_tpcid = std::numeric_limits<unsigned int>::quiet_NaN();
1953     m_silseedx = std::numeric_limits<float>::quiet_NaN();
1954     m_silseedy = std::numeric_limits<float>::quiet_NaN();
1955     m_silseedz = std::numeric_limits<float>::quiet_NaN();
1956     m_silseedpx = std::numeric_limits<float>::quiet_NaN();
1957     m_silseedpy = std::numeric_limits<float>::quiet_NaN();
1958     m_silseedpz = std::numeric_limits<float>::quiet_NaN();
1959     m_silseedphi = std::numeric_limits<float>::quiet_NaN();
1960     m_silseedeta = std::numeric_limits<float>::quiet_NaN();
1961     m_silseedcharge = std::numeric_limits<int>::quiet_NaN();
1962     m_tpcseedx = std::numeric_limits<float>::quiet_NaN();
1963     m_tpcseedy = std::numeric_limits<float>::quiet_NaN();
1964     m_tpcseedz = std::numeric_limits<float>::quiet_NaN();
1965     m_tpcseedpx = std::numeric_limits<float>::quiet_NaN();
1966     m_tpcseedpy = std::numeric_limits<float>::quiet_NaN();
1967     m_tpcseedpz = std::numeric_limits<float>::quiet_NaN();
1968     m_tpcseedphi = std::numeric_limits<float>::quiet_NaN();
1969     m_tpcseedeta = std::numeric_limits<float>::quiet_NaN();
1970     m_tpcseedcharge = std::numeric_limits<int>::quiet_NaN();
1971 
1972     m_pcax = track->get_x();
1973     m_pcay = track->get_y();
1974     m_pcaz = track->get_z();
1975     m_dcaxy = std::numeric_limits<float>::quiet_NaN();
1976     m_dcaz = std::numeric_limits<float>::quiet_NaN();
1977     m_vertexid = track->get_vertex_id();
1978     if (vertexmap)
1979     {
1980       auto vertexit = vertexmap->find(m_vertexid);
1981       if (vertexit != vertexmap->end())
1982       {
1983         auto *vertex = vertexit->second;
1984         m_vx = vertex->get_x();
1985         m_vy = vertex->get_y();
1986         m_vz = vertex->get_z();
1987         m_vertex_ntracks = vertex->size_tracks();
1988         Acts::Vector3 v(m_vx, m_vy, m_vz);
1989         auto dcapair = TrackAnalysisUtils::get_dca(track, v);
1990         m_dcaxy = dcapair.first.first;
1991         m_dcaz = dcapair.second.first;
1992       }
1993     }
1994 
1995     auto *tpcseed = track->get_tpc_seed();
1996     if (tpcseed)
1997     {
1998       m_tpcid = tpcseedmap->find(tpcseed);
1999       tpc_seed_ids.insert(tpcseedmap->find(tpcseed));
2000     }
2001     auto *silseed = track->get_silicon_seed();
2002     if (silseed)
2003     {
2004       m_silid = silseedmap->find(silseed);
2005 
2006       const auto si_pos = TrackSeedHelper::get_xyz(silseed);
2007       m_silseedx = si_pos.x();
2008       m_silseedy = si_pos.y();
2009       m_silseedz = si_pos.z();
2010       m_silseedpx = silseed->get_px();
2011       m_silseedpy = silseed->get_py();
2012       m_silseedpz = silseed->get_pz();
2013       m_silseedphi = silseed->get_phi();
2014       m_silseedeta = silseed->get_eta();
2015       m_silseedcharge = silseed->get_qOverR() > 0 ? 1 : -1;
2016     }
2017     if (tpcseed)
2018     {
2019       const auto tpc_pos = TrackSeedHelper::get_xyz(tpcseed);
2020       m_tpcseedx = tpc_pos.x();
2021       m_tpcseedy = tpc_pos.y();
2022       m_tpcseedz = tpc_pos.z();
2023       m_tpcseedpx = tpcseed->get_px();
2024       m_tpcseedpy = tpcseed->get_py();
2025       m_tpcseedpz = tpcseed->get_pz();
2026       m_tpcseedphi = tpcseed->get_phi();
2027       m_tpcseedeta = tpcseed->get_eta();
2028       m_tpcseedcharge = tpcseed->get_qOverR() > 0 ? 1 : -1;
2029     }
2030     if (tpcseed)
2031     {
2032       float layerThicknesses[4] = {0.0, 0.0, 0.0, 0.0};
2033       // These are randomly chosen layer thicknesses for the TPC, to get the
2034       // correct region thicknesses in an easy to pass way to the helper fxn
2035       layerThicknesses[0] = tpcGeom->GetLayerCellGeom(7)->get_thickness();
2036       layerThicknesses[1] = tpcGeom->GetLayerCellGeom(8)->get_thickness();
2037       layerThicknesses[2] = tpcGeom->GetLayerCellGeom(27)->get_thickness();
2038       layerThicknesses[3] = tpcGeom->GetLayerCellGeom(50)->get_thickness();
2039 
2040       m_dedx = TrackAnalysisUtils::calc_dedx(tpcseed, clustermap, geometry, layerThicknesses);
2041     }
2042 
2043     if (tpcseed)
2044     {
2045       m_tpcseedpx = tpcseed->get_px();
2046       m_tpcseedpy = tpcseed->get_py();
2047       m_tpcseedpz = tpcseed->get_pz();
2048     }
2049     else if (silseed)
2050     {
2051       m_silseedpx = silseed->get_px();
2052       m_silseedpy = silseed->get_py();
2053       m_silseedpz = silseed->get_pz();
2054     }
2055 
2056     clearClusterStateVectors();
2057     if (Verbosity() > 1)
2058     {
2059       std::cout << "Track " << key << " has cluster/states"
2060                 << std::endl;
2061     }
2062 
2063     // get the fully corrected cluster global positions
2064     std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> global_raw;
2065     for (const auto& ckey : get_cluster_keys(track))
2066     {
2067       auto *cluster = clustermap->findCluster(ckey);
2068 
2069       // Fully correct the cluster positions for the crossing and all distortions
2070       Acts::Vector3 global = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(ckey, cluster, m_crossing);
2071 
2072       // add the global positions to a vector to give to the cluster mover
2073       global_raw.emplace_back(ckey, global);
2074     }
2075 
2076     // move the cluster positions back to the original readout surface in the fillClusterBranchesKF method
2077 
2078     if (!m_doAlignment)
2079     {
2080       for (const auto& ckey : get_cluster_keys(track))
2081       {
2082         fillClusterBranchesKF(ckey, track, global_raw, topNode);
2083       }
2084     }
2085 
2086     m_nhits = m_nmaps + m_nintt + m_ntpc + m_nmms;
2087 
2088     if (m_doAlignment)
2089     {
2090       /// repopulate with info that is going into alignment
2091       clearClusterStateVectors();
2092 
2093       if (alignmentmap && alignmentmap->find(key) != alignmentmap->end())
2094       {
2095         auto& statevec = alignmentmap->find(key)->second;
2096 
2097         for (auto& state : statevec)
2098         {
2099           auto ckey = state->get_cluster_key();
2100 
2101           fillClusterBranchesKF(ckey, track, global_raw, topNode);
2102 
2103           const auto& globderivs = state->get_global_derivative_matrix();
2104           const auto& locderivs = state->get_local_derivative_matrix();
2105 
2106           m_statelxglobderivdalpha.push_back(globderivs(0, 0));
2107           m_statelxglobderivdbeta.push_back(globderivs(0, 1));
2108           m_statelxglobderivdgamma.push_back(globderivs(0, 2));
2109           m_statelxglobderivdx.push_back(globderivs(0, 3));
2110           m_statelxglobderivdy.push_back(globderivs(0, 4));
2111           m_statelxglobderivdz.push_back(globderivs(0, 5));
2112 
2113           m_statelzglobderivdalpha.push_back(globderivs(1, 0));
2114           m_statelzglobderivdbeta.push_back(globderivs(1, 1));
2115           m_statelzglobderivdgamma.push_back(globderivs(1, 2));
2116           m_statelzglobderivdx.push_back(globderivs(1, 3));
2117           m_statelzglobderivdy.push_back(globderivs(1, 4));
2118           m_statelzglobderivdz.push_back(globderivs(1, 5));
2119 
2120           m_statelxlocderivd0.push_back(locderivs(0, 0));
2121           m_statelxlocderivz0.push_back(locderivs(0, 1));
2122           m_statelxlocderivphi.push_back(locderivs(0, 2));
2123           m_statelxlocderivtheta.push_back(locderivs(0, 3));
2124           m_statelxlocderivqop.push_back(locderivs(0, 4));
2125 
2126           m_statelzlocderivd0.push_back(locderivs(1, 0));
2127           m_statelzlocderivz0.push_back(locderivs(1, 1));
2128           m_statelzlocderivphi.push_back(locderivs(1, 2));
2129           m_statelzlocderivtheta.push_back(locderivs(1, 3));
2130           m_statelzlocderivqop.push_back(locderivs(1, 4));
2131         }
2132       }
2133     }
2134 
2135     if (m_nmms > 0 || !m_doMicromegasOnly)
2136     {
2137       m_tree->Fill();
2138     }
2139 
2140   }  // end loop over tracks
2141 
2142   if (m_doFailedSeeds)
2143   {
2144     fillFailedSeedTree(topNode, tpc_seed_ids);
2145   }
2146 }
2147 void TrackResiduals::fillEventTree(PHCompositeNode* topNode)
2148 {
2149   auto *silseedmap = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
2150   auto *tpcseedmap = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
2151   auto *trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trackMapName);
2152   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
2153   auto *hitmap = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
2154 
2155   m_ntpc_hits0 = 0;
2156   m_ntpc_hits1 = 0;
2157   m_ntpc_clus0 = 0;
2158   m_ntpc_clus1 = 0;
2159   m_nmvtx_all = 0;
2160   m_nintt_all = 0;
2161   m_nmms_all = 0;
2162   m_nsiseed = 0;
2163   m_ntpcseed = 0;
2164   m_ntpc_clus_sector.resize(24, 0);
2165   m_nsiseed = silseedmap->size();
2166   m_ntpcseed = tpcseedmap->size();
2167   m_ntracks_all = trackmap->size();
2168 
2169   // Hits
2170   if (m_doHits)
2171   {
2172     TrkrHitSetContainer::ConstRange tpc_hitsets = hitmap->getHitSets(TrkrDefs::TrkrId::tpcId);
2173     for (TrkrHitSetContainer::ConstIterator hitsetiter = tpc_hitsets.first;
2174          hitsetiter != tpc_hitsets.second;
2175          ++hitsetiter)
2176     {
2177       TrkrDefs::hitsetkey hitsetkey = hitsetiter->first;
2178       TrkrHitSet* hitset = hitsetiter->second;
2179 
2180       int thisside = TpcDefs::getSide(hitsetkey);
2181       if (thisside == 0)
2182       {
2183         m_ntpc_hits0 += hitset->size();
2184       }
2185       if (thisside == 1)
2186       {
2187         m_ntpc_hits1 += hitset->size();
2188       }
2189     }
2190   }
2191   for (const auto& det : {TrkrDefs::TrkrId::mvtxId, TrkrDefs::TrkrId::inttId,
2192                     TrkrDefs::TrkrId::tpcId, TrkrDefs::TrkrId::micromegasId})
2193   {
2194     for (const auto& hitsetkey : clustermap->getHitSetKeys(det))
2195     {
2196       auto range = clustermap->getClusters(hitsetkey);
2197       int nclus = std::distance(range.first, range.second);
2198       int tpcside = TrkrDefs::getZElement(hitsetkey);
2199       int sector = TpcDefs::getSectorId(hitsetkey);
2200 
2201       switch (det)
2202       {
2203       case TrkrDefs::TrkrId::mvtxId:
2204         m_nmvtx_all += nclus;
2205         break;
2206       case TrkrDefs::TrkrId::inttId:
2207         m_nintt_all += nclus;
2208         break;
2209       case TrkrDefs::TrkrId::tpcId:
2210         if(tpcside == 1)
2211         {
2212           sector += 12;
2213         }
2214         m_ntpc_clus_sector[sector] += nclus;
2215         if (tpcside == 0)
2216         {
2217           m_ntpc_clus0 += nclus;
2218         }
2219         if (tpcside == 1)
2220         {
2221           m_ntpc_clus1 += nclus;
2222         }
2223         break;
2224       case TrkrDefs::TrkrId::micromegasId:
2225         m_nmms_all += nclus;
2226         break;
2227       default:
2228         break;
2229       }
2230     }
2231   }
2232   if (m_doEventTree)
2233   {
2234     if (Verbosity() > 1)
2235     {
2236       std::cout << " m_event:" << m_event << std::endl;
2237       std::cout << " m_ntpc_clus0:" << m_ntpc_clus0 << std::endl;
2238       std::cout << " m_ntpc_clus1: " << m_ntpc_clus1 << std::endl;
2239       std::cout << " m_nmvtx_all:" << m_nmvtx_all << std::endl;
2240       std::cout << " m_nintt_all: " << m_nintt_all << std::endl;
2241       std::cout << " m_nmms_all: " << m_nmms_all << std::endl;
2242     }
2243     m_eventtree->Fill();
2244   }
2245 }
2246 
2247 void TrackResiduals::fillResidualTreeSeeds(PHCompositeNode* topNode)
2248 {
2249   auto *silseedmap = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
2250   auto *tpcseedmap = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
2251   auto *tpcGeom =
2252       findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
2253   auto *trackmap = findNode::getClass<SvtxTrackMap>(topNode, m_trackMapName);
2254   auto *clustermap = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
2255   auto *vertexmap = findNode::getClass<SvtxVertexMap>(topNode, "SvtxVertexMap");
2256   auto *alignmentmap = findNode::getClass<SvtxAlignmentStateMap>(topNode, m_alignmentMapName);
2257   auto *geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
2258   auto *iteration_map = findNode::getClass<TrkrClusterIterationMap>(topNode, "TrkrClusterIterationMap");
2259    
2260   std::set<unsigned int> tpc_seed_ids;
2261 
2262   for (const auto& [key, track] : *trackmap)
2263   {
2264     if (!track)
2265     {
2266       continue;
2267     }
2268     m_trackid = track->get_id();
2269    
2270     m_crossing = track->get_crossing();
2271     m_crossing_estimate = SHRT_MAX;
2272     m_px = track->get_px();
2273     m_py = track->get_py();
2274     m_pz = track->get_pz();
2275 
2276     m_pt = std::sqrt(square(m_px) + square(m_py));
2277     m_eta = std::atanh(m_pz / std::sqrt(square(m_pt) + square(m_pz)));
2278     m_phi = std::atan2(m_py, m_px);
2279     float CVxx = track->get_error(3, 3);
2280     float CVxy = track->get_error(3, 4);
2281     float CVyy = track->get_error(4, 4);
2282     m_deltapt = std::sqrt((CVxx * square(m_px) + 2 * CVxy * m_px * m_py + CVyy * square(m_py)) / (square(m_px) + square(m_py)));
2283 
2284     m_charge = track->get_charge();
2285     m_quality = track->get_quality();
2286     m_chisq = track->get_chisq();
2287     m_ndf = track->get_ndf();
2288 
2289     if (Verbosity() > 1)
2290     {
2291       std::cout << "fillResidualTreeSeeds:  track " << m_trackid << " m_crossing " << m_crossing << " m_crossing_estimate " << m_crossing_estimate << " m_pt " << m_pt << std::endl;
2292     }
2293 
2294     m_nmaps = 0;
2295     m_nintt = 0;
2296     m_ntpc = 0;
2297     m_nmms = 0;
2298     m_silid = std::numeric_limits<unsigned int>::quiet_NaN();
2299     m_tpcid = std::numeric_limits<unsigned int>::quiet_NaN();
2300     m_silseedx = std::numeric_limits<float>::quiet_NaN();
2301     m_silseedy = std::numeric_limits<float>::quiet_NaN();
2302     m_silseedz = std::numeric_limits<float>::quiet_NaN();
2303     m_silseedpx = std::numeric_limits<float>::quiet_NaN();
2304     m_silseedpy = std::numeric_limits<float>::quiet_NaN();
2305     m_silseedpz = std::numeric_limits<float>::quiet_NaN();
2306     m_silseedphi = std::numeric_limits<float>::quiet_NaN();
2307     m_silseedeta = std::numeric_limits<float>::quiet_NaN();
2308     m_silseedcharge = std::numeric_limits<int>::quiet_NaN();
2309     m_tpcseedx = std::numeric_limits<float>::quiet_NaN();
2310     m_tpcseedy = std::numeric_limits<float>::quiet_NaN();
2311     m_tpcseedz = std::numeric_limits<float>::quiet_NaN();
2312     m_tpcseedpx = std::numeric_limits<float>::quiet_NaN();
2313     m_tpcseedpy = std::numeric_limits<float>::quiet_NaN();
2314     m_tpcseedpz = std::numeric_limits<float>::quiet_NaN();
2315     m_tpcseedphi = std::numeric_limits<float>::quiet_NaN();
2316     m_tpcseedeta = std::numeric_limits<float>::quiet_NaN();
2317     m_tpcseedcharge = std::numeric_limits<int>::quiet_NaN();
2318 
2319     m_vertexid = track->get_vertex_id();
2320 
2321     m_pcax = track->get_x();
2322     m_pcay = track->get_y();
2323     m_pcaz = track->get_z();
2324     m_dcaxy = std::numeric_limits<float>::quiet_NaN();
2325     m_dcaz = std::numeric_limits<float>::quiet_NaN();
2326     if (vertexmap)
2327     {
2328       auto vertexit = vertexmap->find(m_vertexid);
2329       if (vertexit != vertexmap->end())
2330       {
2331         auto *vertex = vertexit->second;
2332         m_vx = vertex->get_x();
2333         m_vy = vertex->get_y();
2334         m_vz = vertex->get_z();
2335         Acts::Vector3 vert(m_vx, m_vy, m_vz);
2336         auto dcapair = TrackAnalysisUtils::get_dca(track, vert);
2337         m_dcaxy = dcapair.first.first;
2338         m_dcaz = dcapair.second.first;
2339       }
2340     }
2341 
2342     auto *tpcseed = track->get_tpc_seed();
2343     if (tpcseed)
2344     {
2345       m_tpcid = tpcseedmap->find(tpcseed);
2346       tpc_seed_ids.insert(tpcseedmap->find(tpcseed));
2347     }
2348     auto *silseed = track->get_silicon_seed();
2349     if (silseed)
2350     {
2351       m_silid = silseedmap->find(silseed);
2352       const auto si_pos = TrackSeedHelper::get_xyz(silseed);
2353       m_silseedx = si_pos.x();
2354       m_silseedy = si_pos.y();
2355       m_silseedz = si_pos.z();
2356       m_silseedpx = silseed->get_px();
2357       m_silseedpy = silseed->get_py();
2358       m_silseedpz = silseed->get_pz();
2359       m_silseedphi = silseed->get_phi();
2360       m_silseedeta = silseed->get_eta();
2361       m_silseedcharge = silseed->get_qOverR() > 0 ? 1 : -1;
2362       if (iteration_map)
2363       {
2364         m_silseedit = iteration_map->getIteration(*silseed->begin_cluster_keys());
2365    
2366       }
2367     }
2368     if (tpcseed)
2369     {
2370       const auto tpc_pos = TrackSeedHelper::get_xyz(tpcseed);
2371       m_tpcseedx = tpc_pos.x();
2372       m_tpcseedy = tpc_pos.y();
2373       m_tpcseedz = tpc_pos.z();
2374       m_tpcseedpx = tpcseed->get_px();
2375       m_tpcseedpy = tpcseed->get_py();
2376       m_tpcseedpz = tpcseed->get_pz();
2377       m_tpcseedphi = tpcseed->get_phi();
2378       m_tpcseedeta = tpcseed->get_eta();
2379       m_tpcseedcharge = tpcseed->get_qOverR() > 0 ? 1 : -1;
2380     }
2381     if (tpcseed)
2382     {
2383       float layerThicknesses[4] = {0.0, 0.0, 0.0, 0.0};
2384       // These are randomly chosen layer thicknesses for the TPC, to get the
2385       // correct region thicknesses in an easy to pass way to the helper fxn
2386       layerThicknesses[0] = tpcGeom->GetLayerCellGeom(7)->get_thickness();
2387       layerThicknesses[1] = tpcGeom->GetLayerCellGeom(8)->get_thickness();
2388       layerThicknesses[2] = tpcGeom->GetLayerCellGeom(27)->get_thickness();
2389       layerThicknesses[3] = tpcGeom->GetLayerCellGeom(50)->get_thickness();
2390 
2391       m_dedx = TrackAnalysisUtils::calc_dedx(tpcseed, clustermap, geometry, layerThicknesses);
2392     }
2393     if (m_zeroField)
2394     {
2395       float qor = std::numeric_limits<float>::quiet_NaN();
2396       float phi = std::numeric_limits<float>::quiet_NaN();
2397       float theta = std::numeric_limits<float>::quiet_NaN();
2398       float eta = std::numeric_limits<float>::quiet_NaN();
2399       if (tpcseed)
2400       {
2401         qor = tpcseed->get_qOverR();
2402         phi = tpcseed->get_phi();
2403         eta = tpcseed->get_eta();
2404         theta = tpcseed->get_theta();
2405       }
2406       else if (silseed)
2407       {
2408         qor = silseed->get_qOverR();
2409         phi = silseed->get_phi();
2410         eta = silseed->get_eta();
2411         theta = silseed->get_theta();
2412       }
2413       float pt = fabs(1. / qor) * (0.3 / 100) * 0.01;
2414       m_tpcseedpx = pt * std::cos(phi);
2415       m_tpcseedpy = pt * std::sin(phi);
2416       m_tpcseedpz = pt * std::cosh(eta) * std::cos(theta);
2417     }
2418     else
2419     {
2420       if (tpcseed)
2421       {
2422         m_tpcseedpx = tpcseed->get_px();
2423         m_tpcseedpy = tpcseed->get_py();
2424         m_tpcseedpz = tpcseed->get_pz();
2425       }
2426       else if (silseed)
2427       {
2428         m_silseedpx = silseed->get_px();
2429         m_silseedpy = silseed->get_py();
2430         m_silseedpz = silseed->get_pz();
2431       }
2432     }
2433     clearClusterStateVectors();
2434     if (Verbosity() > 1)
2435     {
2436       std::cout << "Track " << key << " has cluster/states"
2437                 << std::endl;
2438     }
2439 
2440     // get the fully corrected cluster global positions
2441     std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> global_raw;
2442     float minR = std::numeric_limits<float>::max();
2443     float maxR = 0;
2444     for (const auto& ckey : get_cluster_keys(track))
2445     {
2446       auto *cluster = clustermap->findCluster(ckey);
2447 
2448       // Fully correct the cluster positions for the crossing and all distortions
2449       Acts::Vector3 global = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(ckey, cluster, m_crossing);
2450 
2451       // add the global positions to a vector to give to the cluster mover
2452       global_raw.emplace_back(ckey, global);
2453       minR = std::min<double>(r(global.x(), global.y()), minR);
2454       maxR = std::max<double>(r(global.x(), global.y()), maxR);
2455     }
2456     m_tracklength = maxR - minR;
2457     // ---- we move the global positions back to the surface in fillClusterBranchesSeeds
2458 
2459     if (!m_doAlignment)
2460     {
2461       std::vector<TrkrDefs::cluskey> keys;
2462       for (const auto& ckey : get_cluster_keys(track))
2463       {
2464         keys.push_back(ckey);
2465       }
2466       if (m_zeroField)
2467       {
2468         lineFitClusters(keys, clustermap, m_crossing);
2469       }
2470       else
2471       {
2472         // this corrects the cluster positions and fits them, to fill the helical fit parameters
2473         //  that are used to calculate the "state" positions
2474         circleFitClusters(keys, clustermap, m_crossing);
2475       }
2476 
2477       for (const auto& ckey : get_cluster_keys(track))
2478       {
2479         fillClusterBranchesSeeds(ckey, global_raw, topNode);
2480       }
2481     }
2482 
2483     m_nhits = m_nmaps + m_nintt + m_ntpc + m_nmms;
2484 
2485     if (m_doAlignment)
2486     {
2487       /// repopulate with info that is going into alignment
2488       clearClusterStateVectors();
2489 
2490       if (alignmentmap && alignmentmap->find(key) != alignmentmap->end())
2491       {
2492         auto& statevec = alignmentmap->find(key)->second;
2493 
2494         for (auto& state : statevec)
2495         {
2496           auto ckey = state->get_cluster_key();
2497 
2498           fillClusterBranchesSeeds(ckey, global_raw, topNode);
2499 
2500           const auto& globderivs = state->get_global_derivative_matrix();
2501           const auto& locderivs = state->get_local_derivative_matrix();
2502 
2503           m_statelxglobderivdalpha.push_back(globderivs(0, 0));
2504           m_statelxglobderivdbeta.push_back(globderivs(0, 1));
2505           m_statelxglobderivdgamma.push_back(globderivs(0, 2));
2506           m_statelxglobderivdx.push_back(globderivs(0, 3));
2507           m_statelxglobderivdy.push_back(globderivs(0, 4));
2508           m_statelxglobderivdz.push_back(globderivs(0, 5));
2509 
2510           m_statelzglobderivdalpha.push_back(globderivs(1, 0));
2511           m_statelzglobderivdbeta.push_back(globderivs(1, 1));
2512           m_statelzglobderivdgamma.push_back(globderivs(1, 2));
2513           m_statelzglobderivdx.push_back(globderivs(1, 3));
2514           m_statelzglobderivdy.push_back(globderivs(1, 4));
2515           m_statelzglobderivdz.push_back(globderivs(1, 5));
2516 
2517           m_statelxlocderivd0.push_back(locderivs(0, 0));
2518           m_statelxlocderivz0.push_back(locderivs(0, 1));
2519           m_statelxlocderivphi.push_back(locderivs(0, 2));
2520           m_statelxlocderivtheta.push_back(locderivs(0, 3));
2521           m_statelxlocderivqop.push_back(locderivs(0, 4));
2522 
2523           m_statelzlocderivd0.push_back(locderivs(1, 0));
2524           m_statelzlocderivz0.push_back(locderivs(1, 1));
2525           m_statelzlocderivphi.push_back(locderivs(1, 2));
2526           m_statelzlocderivtheta.push_back(locderivs(1, 3));
2527           m_statelzlocderivqop.push_back(locderivs(1, 4));
2528         }
2529       }
2530     }
2531     if (!m_doMatchedOnly)
2532     {
2533       m_tree->Fill();
2534     }
2535     else
2536     {
2537       if (m_nmaps >= 3 && m_nintt >= 1 && m_ntpc > 32 && abs(m_crossing) < 5 && m_pt > 0.3)
2538       {
2539         m_tree->Fill();
2540       }
2541     }
2542   }
2543 }