22 #include <phfield/PHFieldConfig_v3.h>
23 #include <phfield/PHFieldUtility.h>
24 #include <phgeom/PHGeomUtility.h>
38 static bool inited =
false;
41 static double FMAGSTR;
42 static double KMAGSTR;
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;
122 evalFileName =
"vertex_eval.root";
130 if(evalFile !=
nullptr)
150 int ret = MakeNodes(topNode);
153 ret = GetNodes(topNode);
156 ret = InitField(topNode);
159 ret = InitGeom(topNode);
166 cout <<
"PHField check: " <<
"-------" << endl;
167 std::ofstream field_scan(
"field_scan.csv");
174 _extrapolator.
init(field, _t_geo_manager);
192 LogInfo(
"Vertexing Returned: " << ret);
195 LogInfo(
"VertexFitting failed");
211 _recEvent = findNode::getClass<SRecEvent>(topNode,
"SRecEvent");
223 if (
verbosity > 1) cout <<
"VertexFit::InitField" << endl;
227 cout <<
"VertexFit::InitField - use filed from NodeTree." << endl;
230 if (
verbosity > 1) cout <<
"VertexFit::InitField - create magnetic field setup" << endl;
231 unique_ptr<PHFieldConfig> default_field_cfg(
nullptr);
243 if (
verbosity > 1) cout <<
"VertexFit::InitGeom" << endl;
248 cout <<
"VertexFit::InitGeom - use geom from NodeTree." << endl;
250 assert(_t_geo_manager);
260 nPos = idx_pos.size();
261 nNeg = idx_neg.size();
265 if(evalTree !=
nullptr)
273 for(
int i = 0; i < nPos; ++i)
280 int j = sign1 + sign2 == 0 ? 0 : i + 1;
284 if(idx_pos[i] == idx_neg[j])
continue;
290 if(!track_neg.
isValid())
continue;
324 dimuon.
vtx.SetXYZ(_vtxpar_curr.
_r[0][0], _vtxpar_curr.
_r[1][0], _vtxpar_curr.
_r[2][0]);
339 double z_curr = 9999.;
340 while(fabs(z_curr - z_vertex_opt) > 0.5 && nTry < 100)
342 z_curr = z_vertex_opt;
350 z_vertex_opt = -305.465 + 104.731*m - 24.3589*m*m + 2.5564*m*m*m - 0.0978876*m*m*m*m;
408 TVector3 pos1[NSTEPS_FMAG + NSTEPS_TARGET + 1];
409 TVector3 pos2[NSTEPS_FMAG + NSTEPS_TARGET + 1];
410 TVector3 mom1[NSTEPS_FMAG + NSTEPS_TARGET + 1];
411 TVector3 mom2[NSTEPS_FMAG + NSTEPS_TARGET + 1];
416 double dist_min = 1E6;
419 for(
int iStep = 0; iStep < NSTEPS_FMAG + NSTEPS_TARGET + 1; ++iStep)
421 double dist = (pos1[iStep] - pos2[iStep]).Perp();
422 if(dist < dist_min && FMAGSTR*charge1*mom1[iStep].Px() > 0 && FMAGSTR*charge2*mom2[iStep].Px() > 0)
429 if(iStep_min == -1)
return Z_DUMP;
430 return pos1[iStep_min].Z();
435 _trkpar_curr.clear();
453 _vtxpar_curr.
_r[0][0] = X_BEAM;
454 _vtxpar_curr.
_r[1][0] = Y_BEAM;
455 _vtxpar_curr.
_r[2][0] = z_start;
457 _vtxpar_curr.
_cov.Zero();
458 _vtxpar_curr.
_cov[0][0] = SIGX_BEAM*SIGX_BEAM;
459 _vtxpar_curr.
_cov[1][1] = SIGY_BEAM*SIGY_BEAM;
460 _vtxpar_curr.
_cov[2][2] = sigz_start*sigz_start;
468 double chisq_min = 1E6;
471 nStart = z_start.size();
472 for(
int i = 0; i < nStart; ++i)
475 LogInfo(
"Testing starting point: " << z_start[i]);
481 chisq_km.push_back(_chisq_kalman);
482 chisq_vx.push_back(_chisq_vertex);
483 z_vertex.push_back(_vtxpar_curr.
_r[2][0]);
484 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]));
486 if(_chisq_kalman < chisq_min)
489 chisq_min = _chisq_kalman;
493 if(index_min < 0)
return 0;
495 _chisq_kalman = chisq_km[index_min];
496 _chisq_vertex = chisq_vx[index_min];
497 _vtxpar_curr.
_r[2][0] = z_vertex[index_min];
498 if(z_vertex[index_min] > 1E4)
500 index_min = z_start.size();
501 _vtxpar_curr.
_r[2][0] = z_start.back();
511 _trkpar_curr.push_back(_track.
getNodeList().front().getSmoothed());
513 else if(_track.
getNodeList().front().isFilterDone())
515 _trkpar_curr.push_back(_track.
getNodeList().front().getFiltered());
519 _trkpar_curr.push_back(_track.
getNodeList().front().getPredicted());
528 _trkpar.
_z = _track.
getZ(0);
530 _trkpar_curr.push_back(_trkpar);
535 _trkpar_curr.push_back(_trkpar);
541 double _chisq_kalman_prev = 1E6;
542 for(; nIter < _max_iteration; ++nIter)
545 LogInfo(
"Iteration: " << nIter);
550 for(
unsigned int j = 0; j < _trkpar_curr.size(); j++)
555 _node_vertex.
setZ(_vtxpar_curr.
_r[2][0]);
561 LogInfo(
"Vertex fit for this track failed!");
568 _chisq_kalman += _node_vertex.
getChisq();
576 LogInfo(
"At this iteration: ");
577 LogInfo(_vtxpar_curr.
_r[2][0] <<
" === " << _node_vertex.
getZ() <<
" : " << _chisq_kalman <<
" === " << _chisq_vertex <<
" : " << _vtxpar_curr.
_r[0][0] <<
" === " << _vtxpar_curr.
_r[1][0]);
579 if(_vtxpar_curr.
_r[2][0] < Z_UPSTREAM || _vtxpar_curr.
_r[2][0] > Z_DOWNSTREAM)
586 if(nIter > 0 && (fabs(_vtxpar_curr.
_r[2][0] - _node_vertex.
getZ()) < _tolerance || _chisq_kalman > _chisq_kalman_prev))
break;
587 _chisq_kalman_prev = _chisq_kalman;
598 double pz = sqrt(p*p - px*px - py*py);
609 TMatrixD vertex_dummy(3, 1);
611 vertex_dummy[2][0] = _vtxpar_curr.
_r[2][0];
617 TMatrixD zeta = mxy - H*(_vtxpar_curr.
_r - vertex_dummy);
618 TMatrixD _r_filtered = _vtxpar_curr.
_r + K*zeta;
619 TMatrixD _cov_filtered = _vtxpar_curr.
_cov - K*H*(_vtxpar_curr.
_cov);
623 _vtxpar_curr.
_r = _r_filtered;
624 _vtxpar_curr.
_cov = _cov_filtered;
632 _trkpar_start.
_z = _track.
getZ(0);
661 return z_vertex_single;
666 evalFile =
new TFile(evalFileName.c_str(),
"recreate");
667 evalTree =
new TTree(
"T",
"VertexFit eval");
669 evalTree->Branch(
"runID", &runID,
"runID/I");
670 evalTree->Branch(
"eventID", &eventID,
"eventID/I");
671 evalTree->Branch(
"targetPos", &targetPos,
"targetPos/I");
672 evalTree->Branch(
"choice_eval", &choice_eval,
"choice_eval/I");
673 evalTree->Branch(
"choice_by_kf_eval", &choice_by_kf_eval,
"choice_by_kf_eval/I");
674 evalTree->Branch(
"choice_by_vx_eval", &choice_by_vx_eval,
"choice_by_vx_eval/I");
676 evalTree->Branch(
"nStart", &nStart,
"nStart/I");
677 evalTree->Branch(
"nIter_eval", nIter_eval,
"nIter_eval[nStart]/I");
678 evalTree->Branch(
"chisq_kf_eval", chisq_kf_eval,
"chisq_kf_eval[nStart]/D");
679 evalTree->Branch(
"chisq_vx_eval", chisq_vx_eval,
"chisq_vx_eval[nStart]/D");
680 evalTree->Branch(
"z_vertex_eval", z_vertex_eval,
"z_vertex_eval[nStart]/D");
681 evalTree->Branch(
"r_vertex_eval", r_vertex_eval,
"r_vertex_eval[nStart]/D");
682 evalTree->Branch(
"z_start_eval", z_start_eval,
"z_start_eval[nStart]/D");
684 evalTree->Branch(
"m_chisq_kf_eval", &m_chisq_kf_eval,
"m_chisq_kf_eval/D");
685 evalTree->Branch(
"m_z_vertex_eval", &m_z_vertex_eval,
"m_z_vertex_eval/D");
686 evalTree->Branch(
"s_chisq_kf_eval", &s_chisq_kf_eval,
"s_chisq_kf_eval/D");
687 evalTree->Branch(
"s_z_vertex_eval", &s_z_vertex_eval,
"s_z_vertex_eval/D");
692 if(evalTree ==
nullptr)
return;
694 choice_by_kf_eval = -1;
695 choice_by_vx_eval = -1;
696 double chisq_kf_min = 1E6;
697 double chisq_vx_min = 1E6;
699 m_chisq_kf_eval = 0.;
700 m_z_vertex_eval = 0.;
701 for(
int i = 0; i < nStart; ++i)
703 chisq_kf_eval[i] = chisq_km[i];
704 chisq_vx_eval[i] = chisq_vx[i];
705 z_vertex_eval[i] = z_vertex[i];
706 r_vertex_eval[i] = r_vertex[i];
707 z_start_eval[i] = z_start[i];
709 m_chisq_kf_eval += chisq_kf_eval[i];
710 m_z_vertex_eval += z_vertex_eval[i];
712 if(chisq_kf_min > chisq_km[i])
714 choice_by_kf_eval = i;
715 chisq_kf_min = chisq_km[i];
718 if(chisq_vx_min > chisq_vx[i])
720 choice_by_vx_eval = i;
721 chisq_vx_min = chisq_vx[i];
724 m_chisq_kf_eval /= nStart;
725 m_z_vertex_eval /= nStart;
727 s_chisq_kf_eval = 0.;
728 s_z_vertex_eval = 0.;
735 for(
int i = 0; i < nStart; ++i)
737 s_chisq_kf_eval += ((m_chisq_kf_eval - chisq_kf_eval[i])*(m_chisq_kf_eval - chisq_kf_eval[i]));
738 s_z_vertex_eval += ((m_z_vertex_eval - z_vertex_eval[i])*(m_z_vertex_eval - z_vertex_eval[i]));
740 s_chisq_kf_eval = sqrt(s_chisq_kf_eval/(nStart-1));
741 s_z_vertex_eval = sqrt(s_z_vertex_eval/(nStart-1));
750 for(
unsigned int i = 0; i < z_start.size(); i++)
752 cout <<
"============= Hypothesis " << i <<
" ============" << endl;
753 cout <<
"z_start = " << z_start[i] <<
", sigz_start = " << sig_z_start[i] << endl;
754 cout <<
"Found z_vertex = " << z_vertex[i] << endl;
755 cout <<
"With chisq_km = " << chisq_km[i] <<
" and chisq_vx = " << chisq_vx[i] << endl;
#define VFEXIT_FAIL_ITERATION
Int_t getNDimuons()
Get dimuons.
int verbosity
The verbosity level. 0 means not verbose at all.
TrkPar & getPredicted()
Gets.
VertexFit(const std::string &name="VertexFit")
int setRecEvent(SRecEvent *recEvent, int sign1=1, int sign2=-1)
Set the SRecEvent, main external call the use vertex fit.
void addTrack(int index, SRecTrack &_track)
Add one track parameter set into the fit.
Double_t getChisqVertex()
void setRecStatus(int status)
void setStartingVertex(double z_start, double sigz_start)
void addHypothesis(double z, double sigz=50.)
virtual double get_DoubleFlag(const std::string &name) const
TMatrixD & getMeasurement()
int processOnePair()
After setting both tracks and hypothesis, start the iteration.
Double_t getChisqTarget()
PHFieldConfig_v3 implements field configuration information for input a field map file...
static TMatrixD getAtBC(const TMatrixD &A, const TMatrixD &B, const TMatrixD &C)
void setZVertex(Double_t z, bool update=true)
transient DST object for field storage and access
int isValid() const
isValid returns non zero if object contains vailid data
static recoConsts * instance()
double findDimuonVertexFast(SRecTrack &track1, SRecTrack &track2)
static TMatrixD invertMatrix(const TMatrixD &m)
void insertDimuon(SRecDimuon dimuon)
Insert dimuon.
TMatrixD & getProjector()
void setCurrTrkpar(Node &_node)
set the current track parameter using the current node
double getVertexZ0()
Gets.
std::vector< Int_t > getChargedTrackIDs(Int_t charge)
Get track IDs.
double findSingleMuonVertex(SRecTrack &_track)
void init()
Initialize and reset.
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.
bool fit_node(Node &_node)
Fit one node.
#define VFEXIT_FAIL_DIMUONPAIR
int findVertex()
Find the primary vertex.
TMatrixD & getMeasurementCov()
virtual int Verbosity() const
Gets the verbosity of this module.
TLorentzVector getMomentumVertex()
Get the vertex info.
Output a lot of messages.
std::list< Node > & getNodeList()
int End(PHCompositeNode *topNode)
Called at the end of all processing.
static KalmanFilter * instance()
singlton instance
TLorentzVector p_neg_single
TMatrixD _state_kf
State vectors and its covariance.
static TMatrixD getABCt(const TMatrixD &A, const TMatrixD &B, const TMatrixD &C)
SRecTrack & getTrack(Int_t i)
Double_t getChisqUpstream()
static TGeoManager * GetTGeoManager(PHCompositeNode *topNode)
Main user interface: DST node -> TGeoManager for downstream use.
int InitRun(PHCompositeNode *topNode)
TMatrixD getCovariance(Int_t i)
void bookEvaluation(std::string evalFileName="vtx_eval.root")
Evaluation.
int process_event(PHCompositeNode *topNode)
void identify(std::ostream &os=std::cout) const
PHObject virtual overloads.
int Init(PHCompositeNode *topNode)
void enableDumpCorrection()
Enable the dump mode: stop calc prop matrix, start calc travel length.
TMatrixD getStateVector(Int_t i)
void print()
Debugging output.
void updateVertex()
Core function, update the vertex prediction according to the track info.
Int_t getCharge() const
Gets.
TLorentzVector p_pos_single
static TMatrixD getABtC(const TMatrixD &A, const TMatrixD &B, const TMatrixD &C)
virtual int get_IntFlag(const std::string &name) const
void swimToVertex(TVector3 *pos=nullptr, TVector3 *mom=nullptr, bool hyptest=true)
Simple swim to vertex.
virtual void identify(std::ostream &os=std::cout) const