22 #include <phfield/PHFieldConfig_v3.h>
23 #include <phfield/PHFieldUtility.h>
24 #include <phgeom/PHGeomUtility.h>
38 static bool inited =
false;
47 static double SIGX_BEAM;
48 static double SIGY_BEAM;
51 static int NSTEPS_TARGET;
52 static int NSTEPS_SHIELDING;
53 static int NSTEPS_FMAG;
56 static double Z_TARGET;
58 static double Z_UPSTREAM;
59 static double Z_DOWNSTREAM;
62 void initGlobalVariables()
78 NSTEPS_SHIELDING = rc->
get_IntFlag(
"NSTEPS_SHIELDING");
92 initGlobalVariables();
95 TMatrixD m(2, 1), cov(2, 2), proj(2, 5);
100 cov[0][0] = SIGX_BEAM*SIGX_BEAM;
101 cov[1][1] = SIGY_BEAM*SIGY_BEAM;
115 _max_iteration = 200;
121 fit_target_center =
false;
124 evalFileName =
"vertex_eval.root";
132 if(evalFile !=
nullptr)
152 int ret = MakeNodes(topNode);
155 ret = GetNodes(topNode);
158 ret = InitField(topNode);
161 ret = InitGeom(topNode);
168 cout <<
"PHField check: " <<
"-------" << endl;
169 std::ofstream field_scan(
"field_scan.csv");
176 _extrapolator.
init(field, _t_geo_manager);
196 LogInfo(
"Vertexing Returned: " << ret);
199 LogInfo(
"VertexFitting failed");
215 _recEvent = findNode::getClass<SRecEvent>(topNode,
"SRecEvent");
227 if (
verbosity > 1) cout <<
"VertexFit::InitField" << endl;
231 cout <<
"VertexFit::InitField - use filed from NodeTree." << endl;
234 if (
verbosity > 1) cout <<
"VertexFit::InitField - create magnetic field setup" << endl;
235 unique_ptr<PHFieldConfig> default_field_cfg(
nullptr);
247 if (
verbosity > 1) cout <<
"VertexFit::InitGeom" << endl;
252 cout <<
"VertexFit::InitGeom - use geom from NodeTree." << endl;
254 assert(_t_geo_manager);
264 nPos = idx_pos.size();
265 nNeg = idx_neg.size();
269 if(evalTree !=
nullptr)
277 for(
int i = 0; i < nPos; ++i)
284 int j = sign1 + sign2 == 0 ? 0 : i + 1;
288 if(idx_pos[i] == idx_neg[j])
continue;
294 if(!track_neg.
isValid())
continue;
328 dimuon.
vtx.SetXYZ(_vtxpar_curr.
_r[0][0], _vtxpar_curr.
_r[1][0], _vtxpar_curr.
_r[2][0]);
343 double z_curr = 9999.;
344 while(fabs(z_curr - z_vertex_opt) > 0.5 && nTry < 100)
346 z_curr = z_vertex_opt;
356 z_vertex_opt = -310.0540 + 4.3539*m - 0.9518*m*m + 0.0803*m*m*m ;
363 if(fit_target_center) z_vertex_opt = Z_TARGET;
416 TVector3 pos1[NSTEPS_FMAG + NSTEPS_TARGET + 1];
417 TVector3 pos2[NSTEPS_FMAG + NSTEPS_TARGET + 1];
418 TVector3 mom1[NSTEPS_FMAG + NSTEPS_TARGET + 1];
419 TVector3 mom2[NSTEPS_FMAG + NSTEPS_TARGET + 1];
424 double dist_min = 1E6;
427 for(
int iStep = 0; iStep < NSTEPS_FMAG + NSTEPS_TARGET + 1; ++iStep)
429 double dist = (pos1[iStep] - pos2[iStep]).Perp();
430 if(dist < dist_min &&
FMAGSTR*charge1*mom1[iStep].Px() > 0 &&
FMAGSTR*charge2*mom2[iStep].Px() > 0)
437 if(iStep_min == -1)
return Z_DUMP;
438 return pos1[iStep_min].Z();
443 _trkpar_curr.clear();
461 _vtxpar_curr.
_r[0][0] = X_BEAM;
462 _vtxpar_curr.
_r[1][0] = Y_BEAM;
463 _vtxpar_curr.
_r[2][0] = z_start;
465 _vtxpar_curr.
_cov.Zero();
466 _vtxpar_curr.
_cov[0][0] = SIGX_BEAM*SIGX_BEAM;
467 _vtxpar_curr.
_cov[1][1] = SIGY_BEAM*SIGY_BEAM;
468 _vtxpar_curr.
_cov[2][2] = sigz_start*sigz_start;
476 double chisq_min = 1E6;
479 nStart = z_start.size();
480 for(
int i = 0; i < nStart; ++i)
483 LogInfo(
"Testing starting point: " << z_start[i]);
489 chisq_km.push_back(_chisq_kalman);
490 chisq_vx.push_back(_chisq_vertex);
491 z_vertex.push_back(_vtxpar_curr.
_r[2][0]);
492 r_vertex.push_back(sqrt(_vtxpar_curr.
_r[0][0]*_vtxpar_curr.
_r[0][0] + _vtxpar_curr.
_r[1][0]*_vtxpar_curr.
_r[1][0]));
494 if(_chisq_kalman < chisq_min)
497 chisq_min = _chisq_kalman;
501 if(index_min < 0)
return 0;
503 _chisq_kalman = chisq_km[index_min];
504 _chisq_vertex = chisq_vx[index_min];
505 _vtxpar_curr.
_r[2][0] = z_vertex[index_min];
506 if(z_vertex[index_min] > 1E4)
508 index_min = z_start.size();
509 _vtxpar_curr.
_r[2][0] = z_start.back();
519 _trkpar_curr.push_back(_track.
getNodeList().front().getSmoothed());
521 else if(_track.
getNodeList().front().isFilterDone())
523 _trkpar_curr.push_back(_track.
getNodeList().front().getFiltered());
527 _trkpar_curr.push_back(_track.
getNodeList().front().getPredicted());
536 _trkpar.
_z = _track.
getZ(0);
538 _trkpar_curr.push_back(_trkpar);
543 _trkpar_curr.push_back(_trkpar);
549 double _chisq_kalman_prev = 1E6;
550 for(; nIter < _max_iteration; ++nIter)
553 LogInfo(
"Iteration: " << nIter);
558 for(
unsigned int j = 0; j < _trkpar_curr.size(); j++)
563 _node_vertex.
setZ(_vtxpar_curr.
_r[2][0]);
569 LogInfo(
"Vertex fit for this track failed!");
576 _chisq_kalman += _node_vertex.
getChisq();
584 LogInfo(
"At this iteration: ");
585 LogInfo(_vtxpar_curr.
_r[2][0] <<
" === " << _node_vertex.
getZ() <<
" : " << _chisq_kalman <<
" === " << _chisq_vertex <<
" : " << _vtxpar_curr.
_r[0][0] <<
" === " << _vtxpar_curr.
_r[1][0]);
587 if(_vtxpar_curr.
_r[2][0] < Z_UPSTREAM || _vtxpar_curr.
_r[2][0] > Z_DOWNSTREAM)
594 if(nIter > 0 && (fabs(_vtxpar_curr.
_r[2][0] - _node_vertex.
getZ()) < _tolerance || _chisq_kalman > _chisq_kalman_prev))
break;
595 _chisq_kalman_prev = _chisq_kalman;
606 double pz = sqrt(p*p - px*px - py*py);
617 TMatrixD vertex_dummy(3, 1);
619 vertex_dummy[2][0] = _vtxpar_curr.
_r[2][0];
625 TMatrixD zeta = mxy - H*(_vtxpar_curr.
_r - vertex_dummy);
626 TMatrixD _r_filtered = _vtxpar_curr.
_r + K*zeta;
627 TMatrixD _cov_filtered = _vtxpar_curr.
_cov - K*H*(_vtxpar_curr.
_cov);
631 _vtxpar_curr.
_r = _r_filtered;
632 _vtxpar_curr.
_cov = _cov_filtered;
640 _trkpar_start.
_z = _track.
getZ(0);
669 return z_vertex_single;
674 evalFile =
new TFile(evalFileName.c_str(),
"recreate");
675 evalTree =
new TTree(
"T",
"VertexFit eval");
677 evalTree->Branch(
"runID", &runID,
"runID/I");
678 evalTree->Branch(
"eventID", &eventID,
"eventID/I");
679 evalTree->Branch(
"targetPos", &targetPos,
"targetPos/I");
680 evalTree->Branch(
"choice_eval", &choice_eval,
"choice_eval/I");
681 evalTree->Branch(
"choice_by_kf_eval", &choice_by_kf_eval,
"choice_by_kf_eval/I");
682 evalTree->Branch(
"choice_by_vx_eval", &choice_by_vx_eval,
"choice_by_vx_eval/I");
684 evalTree->Branch(
"nStart", &nStart,
"nStart/I");
685 evalTree->Branch(
"nIter_eval", nIter_eval,
"nIter_eval[nStart]/I");
686 evalTree->Branch(
"chisq_kf_eval", chisq_kf_eval,
"chisq_kf_eval[nStart]/D");
687 evalTree->Branch(
"chisq_vx_eval", chisq_vx_eval,
"chisq_vx_eval[nStart]/D");
688 evalTree->Branch(
"z_vertex_eval", z_vertex_eval,
"z_vertex_eval[nStart]/D");
689 evalTree->Branch(
"r_vertex_eval", r_vertex_eval,
"r_vertex_eval[nStart]/D");
690 evalTree->Branch(
"z_start_eval", z_start_eval,
"z_start_eval[nStart]/D");
692 evalTree->Branch(
"m_chisq_kf_eval", &m_chisq_kf_eval,
"m_chisq_kf_eval/D");
693 evalTree->Branch(
"m_z_vertex_eval", &m_z_vertex_eval,
"m_z_vertex_eval/D");
694 evalTree->Branch(
"s_chisq_kf_eval", &s_chisq_kf_eval,
"s_chisq_kf_eval/D");
695 evalTree->Branch(
"s_z_vertex_eval", &s_z_vertex_eval,
"s_z_vertex_eval/D");
700 if(evalTree ==
nullptr)
return;
702 choice_by_kf_eval = -1;
703 choice_by_vx_eval = -1;
704 double chisq_kf_min = 1E6;
705 double chisq_vx_min = 1E6;
707 m_chisq_kf_eval = 0.;
708 m_z_vertex_eval = 0.;
709 for(
int i = 0; i < nStart; ++i)
711 chisq_kf_eval[i] = chisq_km[i];
712 chisq_vx_eval[i] = chisq_vx[i];
713 z_vertex_eval[i] = z_vertex[i];
714 r_vertex_eval[i] = r_vertex[i];
715 z_start_eval[i] = z_start[i];
717 m_chisq_kf_eval += chisq_kf_eval[i];
718 m_z_vertex_eval += z_vertex_eval[i];
720 if(chisq_kf_min > chisq_km[i])
722 choice_by_kf_eval = i;
723 chisq_kf_min = chisq_km[i];
726 if(chisq_vx_min > chisq_vx[i])
728 choice_by_vx_eval = i;
729 chisq_vx_min = chisq_vx[i];
732 m_chisq_kf_eval /= nStart;
733 m_z_vertex_eval /= nStart;
735 s_chisq_kf_eval = 0.;
736 s_z_vertex_eval = 0.;
743 for(
int i = 0; i < nStart; ++i)
745 s_chisq_kf_eval += ((m_chisq_kf_eval - chisq_kf_eval[i])*(m_chisq_kf_eval - chisq_kf_eval[i]));
746 s_z_vertex_eval += ((m_z_vertex_eval - z_vertex_eval[i])*(m_z_vertex_eval - z_vertex_eval[i]));
748 s_chisq_kf_eval = sqrt(s_chisq_kf_eval/(nStart-1));
749 s_z_vertex_eval = sqrt(s_z_vertex_eval/(nStart-1));
758 for(
unsigned int i = 0; i < z_start.size(); i++)
760 cout <<
"============= Hypothesis " << i <<
" ============" << endl;
761 cout <<
"z_start = " << z_start[i] <<
", sigz_start = " << sig_z_start[i] << endl;
762 cout <<
"Found z_vertex = " << z_vertex[i] << endl;
763 cout <<
"With chisq_km = " << chisq_km[i] <<
" and chisq_vx = " << chisq_vx[i] << endl;
#define VFEXIT_FAIL_DIMUONPAIR
#define VFEXIT_FAIL_ITERATION
int verbosity
The verbosity level. 0 means not verbose at all.
@ VERBOSITY_A_LOT
Output a lot of messages.
virtual int Verbosity() const
Gets the verbosity of this module.
static KalmanFilter * instance()
singlton instance
void setCurrTrkpar(Node &_node)
set the current track parameter using the current node
bool fit_node(Node &_node)
Fit one node.
void enableDumpCorrection()
Enable the dump mode: stop calc prop matrix, start calc travel length.
std::list< Node > & getNodeList()
TrkPar & getPredicted()
Gets.
TMatrixD & getMeasurement()
TMatrixD & getProjector()
TMatrixD & getMeasurementCov()
PHFieldConfig_v3 implements field configuration information for input a field map file.
static PHField * GetFieldMapNode(const PHFieldConfig *default_config=nullptr, PHCompositeNode *topNode=nullptr, const int verbosity=0)
Get transient PHField from DST nodes. If not found, make a new one based on default_config.
transient DST object for field storage and access
virtual void identify(std::ostream &os=std::cout) const
virtual double get_DoubleFlag(const std::string &name) const
virtual int get_IntFlag(const std::string &name) const
static TGeoManager * GetTGeoManager(PHCompositeNode *topNode)
Main user interface: DST node -> TGeoManager for downstream use.
static TMatrixD getABtC(const TMatrixD &A, const TMatrixD &B, const TMatrixD &C)
static TMatrixD getABCt(const TMatrixD &A, const TMatrixD &B, const TMatrixD &C)
static TMatrixD getAtBC(const TMatrixD &A, const TMatrixD &B, const TMatrixD &C)
static TMatrixD invertMatrix(const TMatrixD &m)
TVector3 vtx
3-vector vertex position
void calcVariables(int choice=0)
Calculate the kinematic vairables, 0 = vertex, 1 = target, 2 = dump.
Int_t trackID_pos
Index of muon track used in host SRecEvent.
Double_t chisq_target
Chisq of three test position.
TLorentzVector p_neg_single
TLorentzVector p_pos_single
4-momentum of the muon tracks before vertex fit
Double_t chisq_kf
Vertex fit chisqs.
TLorentzVector p_pos
4-momentum of the muon tracks after vertex fit
TVector3 proj_target_pos
Track projections at different location.
void setRecStatus(int status)
std::vector< Int_t > getChargedTrackIDs(Int_t charge)
Get track IDs.
void identify(std::ostream &os=std::cout) const
PHObject virtual overloads.
void insertDimuon(SRecDimuon dimuon)
Insert dimuon.
void clearDimuons()
Clear the dimuon list.
SRecTrack & getTrack(Int_t i)
Int_t getNDimuons()
Get dimuons.
TMatrixD getCovariance(Int_t i)
Int_t getCharge() const
Gets.
Double_t getChisqTarget()
TLorentzVector getMomentumVertex()
Get the vertex info.
void setZVertex(Double_t z, bool update=true)
TMatrixD getStateVector(Int_t i)
Double_t getChisqUpstream()
int isValid() const
isValid returns non zero if object contains vailid data
void swimToVertex(TVector3 *pos=nullptr, TVector3 *mom=nullptr, bool hyptest=true)
Simple swim to vertex.
TVector3 getDumpPos()
Get mom/pos at a given location.
Double_t getChisqVertex()
TMatrixD _state_kf
State vectors and its covariance.
int process_event(PHCompositeNode *topNode)
int setRecEvent(SRecEvent *recEvent, int sign1=1, int sign2=-1)
Set the SRecEvent, main external call the use vertex fit.
void addHypothesis(double z, double sigz=50.)
double findDimuonVertexFast(SRecTrack &track1, SRecTrack &track2)
double findSingleMuonVertex(SRecTrack &_track)
int findVertex()
Find the primary vertex.
void print()
Debugging output.
void bookEvaluation(std::string evalFileName="vtx_eval.root")
Evaluation.
void addTrack(int index, SRecTrack &_track)
Add one track parameter set into the fit.
void updateVertex()
Core function, update the vertex prediction according to the track info.
void init()
Initialize and reset.
int Init(PHCompositeNode *topNode)
int InitRun(PHCompositeNode *topNode)
int End(PHCompositeNode *topNode)
Called at the end of all processing.
void setStartingVertex(double z_start, double sigz_start)
VertexFit(const std::string &name="VertexFit")
double getVertexZ0()
Gets.
int processOnePair()
After setting both tracks and hypothesis, start the iteration.
static recoConsts * instance()