13 #include "StEmcUtil/geometry/StEmcGeom.h"
14 #include "StEvent/StCtbTriggerDetector.h"
15 #include "StEvent/StDcaGeometry.h"
16 #include "StEvent/StEmcCollection.h"
17 #include "StEvent/StEmcDetector.h"
18 #include "StEvent/StEmcModule.h"
19 #include "StEvent/StEmcRawHit.h"
20 #include "StEvent/StEvent.h"
21 #include "StEvent/StGlobalTrack.h"
22 #include "StEvent/StTrackDetectorInfo.h"
23 #include "StEvent/StTrackNode.h"
24 #include "StEvent/StTriggerDetectorCollection.h"
25 #include "StGenericVertexMaker/Minuit/StMinuitVertexFinder.h"
26 #include "StGenericVertexMaker/Minuit/St_VertexCutsC.h"
27 #include "StGenericVertexMaker/StCtbMatcher.h"
28 #include "St_base/StMessMgr.h"
31 std::vector<StPhysicalHelixD> StMinuitVertexFinder::mHelices;
32 std::vector<UShort_t> StMinuitVertexFinder::mHelixFlags;
33 std::vector<Double_t > StMinuitVertexFinder::mZImpact;
34 Bool_t StMinuitVertexFinder::requireCTB;
35 Int_t StMinuitVertexFinder::nCTBHits;
38 void StMinuitVertexFinder::Clear(){
39 StGenericVertexFinder::Clear();
47 mExternalSeedPresent = kTRUE;
52 StMinuitVertexFinder::StMinuitVertexFinder(VertexFit_t fitMode) :
55 mExternalSeedPresent = kFALSE;
60 mUseOldBEMCRank = kFALSE;
61 mLowerSplitVtxRank = kFALSE;
68 StMinuitVertexFinder::~StMinuitVertexFinder()
70 LOG_WARN <<
"Skipping delete Minuit in StMinuitVertexFinder::~StMinuitVertexFinder()" << endm;
76 void StMinuitVertexFinder::InitRun(
int run_number,
const St_db_Maker* db_maker)
78 StGenericVertexFinder::InitRun(run_number, db_maker);
81 mMinNumberOfFitPointsOnTrack = cuts->MinNumberOfFitPointsOnTrack();
82 mDcaZMax = cuts->DcaZMax();
83 mMinTrack = (mMinTrack<0 ? cuts->MinTrack() : mMinTrack);
84 mRImpactMax = cuts->RImpactMax();
92 LOG_INFO <<
"Set cuts: MinNumberOfFitPointsOnTrack = " << mMinNumberOfFitPointsOnTrack
93 <<
" DcaZMax = " << mDcaZMax
94 <<
" MinTrack = " << mMinTrack
95 <<
" RImpactMax = " << mRImpactMax
96 <<
" ZMin = " << mZMin
97 <<
" ZMax = " << mZMax
104 StMinuitVertexFinder::setFlagBase(){
112 Int_t StMinuitVertexFinder::findSeeds() {
115 int zIdxMax = (int) (mZMax - mZMin);
116 Int_t zImpactArr[zIdxMax];
117 for (Int_t i=0; i < zIdxMax; i++)
120 Int_t nTrk = mZImpact.size();
121 for (Int_t iTrk=0; iTrk < nTrk; iTrk++) {
122 if ((mZImpact[iTrk] > mZMin) &&
123 (mZImpact[iTrk] < mZMax))
124 zImpactArr[int(mZImpact[iTrk]-mZMin)]++;
131 for (Int_t iBin=0; iBin < zIdxMax - nBinZ; iBin++) {
133 for (Int_t iBin2=0; iBin2 < nBinZ; iBin2++) {
134 nTrkBin += zImpactArr[iBin + iBin2];
136 if (nTrkBin > nOldBin)
138 else if (nTrkBin < nOldBin) {
140 if (mNSeed < maxSeed) {
141 Float_t seed_z = mZMin + iBin + (Float_t)nBinZ / 2 - 1;
144 for (Int_t iTrk = 0; iTrk < nTrk; iTrk ++ ) {
145 if ( fabs(mZImpact[iTrk] - seed_z ) < mDcaZMax ) {
146 meanZ += mZImpact[iTrk];
150 if (nTrkZ >= mMinTrack) {
152 LOG_INFO <<
"Seed " << mNSeed <<
", z " << seed_z <<
" nTrk " << nTrkZ <<
" meanZ/nTrkZ " << meanZ/nTrkZ << endm;
154 seed_z = meanZ/nTrkZ;
155 mSeedZ[mNSeed] = seed_z;
160 LOG_WARN <<
"Too many vertex seeds, limit=" << maxSeed << endm;
165 if (mDebugLevel > 1) {
166 LOG_INFO <<
"iBin " << iBin <<
" nTrkBin " << nTrkBin <<
" nOldBin " << nOldBin <<
", slope " << slope <<
" mNSeed " << mNSeed << endm;
171 LOG_INFO <<
"Found " << mNSeed <<
" seeds" << endm;
175 void StMinuitVertexFinder::fillBemcHits(
StEvent *event){
176 static Int_t nMod = 120;
177 static Int_t nEta = 20;
178 static Int_t nSub = 2;
179 static Float_t mEmcThres = 0.15;
180 for (Int_t m=0; m < nMod; m++)
181 for (Int_t e=0; e < nEta; e++)
182 for (Int_t s=0; s < nSub; s++)
186 if (event->emcCollection() &&
event->emcCollection()->detector(kBarrelEmcTowerId)) {
187 StEmcDetector* bemcDet =
event->emcCollection()->detector(kBarrelEmcTowerId);
188 for (Int_t iMod=0; iMod < nMod; iMod++) {
189 if (!bemcDet->module(iMod))
192 StSPtrVecEmcRawHit& hits = mod->hits();
193 for (StEmcRawHitIterator hitIter = hits.begin(); hitIter != hits.end(); hitIter++) {
195 if (hit->energy() > mEmcThres) {
196 mBemcHit[hit->module()-1][hit->eta()-1][hit->sub()-1]=1;
203 LOG_INFO <<
"Found " << n_emc_hit <<
" emc hits" << endm;
208 StMinuitVertexFinder::matchTrack2BEMC(
const StTrack *
track){
209 static const Double_t rBemc = 242;
210 static StEmcGeom *bemcGeom = StEmcGeom::getEmcGeom(
"bemc");
214 if (track->outerGeometry()==0) {
216 LOG_INFO <<
"No outer track geom" << endm;
223 if (!helix.
valid()) {
225 LOG_INFO <<
"Invalid helix" << endm;
232 if (d2.first > 99999999 && d2.second > 99999999)
234 Double_t path=d2.second;
235 if (d2.first >= 0 && d2.first < d2.second)
237 else if(d2.first>=0 || d2.second<=0) {
238 LOG_WARN <<
"Unexpected solution for track crossing Cyl:"
240 << track->geometry()->momentum().mag()
241 <<
", d2.first=" << d2.first
242 <<
", second=" << d2.second <<
", trying first" << endm;
247 Float_t phi=posCyl.phi();
248 Float_t eta=posCyl.pseudoRapidity();
251 Int_t mod, ieta, sub;
252 if (bemcGeom->
getBin(phi, eta, mod, ieta, sub) == 0) {
255 if (sub > 0 && mBemcHit[mod-1][ieta-1][sub-1]) {
263 Int_t StMinuitVertexFinder::checkCrossMembrane(
const StTrack *track) {
264 Int_t n_pnt_neg=0, n_pnt_pos=0;
266 StPtrVecHit hits = track->detectorInfo()->hits(kTpcId);
267 for (StHitIterator hitIter = hits.begin(); hitIter != hits.end(); hitIter++) {
268 if ((*hitIter)->position().z() < 0)
270 if ((*hitIter)->position().z() > 0)
273 return (n_pnt_pos > 5 && n_pnt_neg > 5);
276 void StMinuitVertexFinder::calculateRanks() {
298 Int_t nBemcMatchTot = 0;
299 Int_t nVtxTrackTot = 0;
300 for (Int_t iVertex=0; iVertex < size(); iVertex++) {
302 nVtxTrackTot += primV->numTracksUsedInFinder();
303 nBemcMatchTot += primV->numMatchesWithBEMC();
308 for (Int_t iVertex=0; iVertex < size(); iVertex++) {
311 Float_t avg_dip_expected = -0.0033*primV->position().z();
312 Float_t n_bemc_expected = 0;
315 n_bemc_expected = (1-0.25*(1-(float)primV->numTracksUsedInFinder()/nVtxTrackTot))*nBemcMatchTot;
317 n_bemc_expected = (float)primV->numTracksUsedInFinder()/nVtxTrackTot*nBemcMatchTot;
320 Float_t n_cross_expected = fabs(primV->position().z())*0.0020*primV->numTracksUsedInFinder();
323 LOG_INFO <<
"vertex z " << primV->position().z() <<
" dip expected " << avg_dip_expected <<
" bemc " << n_bemc_expected <<
" cross " << n_cross_expected << endm;
326 Float_t rank_avg_dip = 1 - fabs(primV->meanDip() - avg_dip_expected)*sqrt((
float)primV->numTracksUsedInFinder())/0.67;
328 Float_t rank_bemc = 0;
329 if (n_bemc_expected >= 1) {
331 Float_t sigma = 0.5*sqrt(n_bemc_expected);
334 sigma = ( sigma < 0.75 ? 0.75 : sigma);
336 rank_bemc = (primV->numMatchesWithBEMC() - n_bemc_expected)/sigma;
341 Float_t rank_cross = 0;
342 if ( n_cross_expected >= 1 ) {
343 Float_t sigma=1.1*sqrt(n_cross_expected);
344 rank_cross = (primV->numTracksCrossingCentralMembrane() - n_cross_expected)/sigma;
348 rank_avg_dip = ( rank_avg_dip < -5 ? -5 : rank_avg_dip );
349 rank_bemc = ( rank_bemc < -5 ? -5 : (rank_bemc > 1 ? 1 : rank_bemc) );
350 rank_cross = ( rank_cross < -5 ? -5 : (rank_cross > 1 ? 1 : rank_cross) );
353 LOG_INFO <<
"rankings: " << rank_avg_dip <<
" " << rank_bemc <<
" " << rank_cross << endm;
357 if (mLowerSplitVtxRank && mCTBSum > 6000.0*primV->numTracksUsedInFinder()/80. + 2000)
358 primV->setRanking(rank_cross+rank_bemc+rank_avg_dip-3);
360 primV->setRanking(rank_cross+rank_bemc+rank_avg_dip);
362 if (primV->ranking() > mBestRank) {
363 mBestRank = primV->ranking();
370 int StMinuitVertexFinder::fit(
StEvent* event)
376 std::vector<ctbHit> ctbHits;
381 ctbDet = &(trigCol->ctb());
383 for (UInt_t slat = 0; slat < ctbDet->numberOfSlats(); slat++) {
384 for (UInt_t tray = 0; tray < ctbDet->numberOfTrays(); tray++) {
386 curHit.adc = ctbDet->mips(tray,slat,0);
388 mCTBSum += curHit.adc;
389 ctb_get_slat_from_data(slat, tray, curHit.phi, curHit.eta);
390 ctbHits.push_back(curHit);
407 Int_t n_ctb_match_tot = 0;
408 Int_t n_bemc_match_tot = 0;
409 Int_t n_cross_tot = 0;
416 double RImpactMax2 = mRImpactMax*mRImpactMax;
418 for (
const StTrackNode* stTrack : event->trackNodes())
421 if (!accept(g))
continue;
423 if (! gDCA)
continue;
426 double RImpact2 = DCAPosition.perp2();
427 if (RImpact2 > RImpactMax2)
continue;
428 mDCAs.push_back(gDCA);
431 mHelices.push_back(g->geometry()->helix());
432 mHelixFlags.push_back(1);
433 Double_t z_lin = DCAPosition.z();
434 mZImpact.push_back(z_lin);
436 Bool_t shouldHitCTB = kFALSE;
437 Double_t etaInCTBFrame = -999;
438 bool ctb_match = EtaAndPhiToOrriginAtCTB(g,&ctbHits,shouldHitCTB,etaInCTBFrame);
440 mHelixFlags[mHelixFlags.size()-1] |= kFlagCTBMatch;
444 if (matchTrack2BEMC(g)) {
445 mHelixFlags[mHelixFlags.size()-1] |= kFlagBEMCMatch;
449 if (checkCrossMembrane(g)) {
450 mHelixFlags[mHelixFlags.size()-1] |= kFlagCrossMembrane;
456 LOG_INFO <<
"Found " << n_ctb_match_tot <<
" ctb matches, " << n_bemc_match_tot <<
" bemc matches, " << n_cross_tot <<
" tracks crossing central membrane" << endm;
460 if (mHelices.empty()) {
461 LOG_WARN <<
"StMinuitVertexFinder::fit: no tracks to fit." << endm;
466 LOG_INFO <<
"StMinuitVertexFinder::fit size of helix vector: " << mHelices.size() << endm;
469 if (mRequireCTB) requireCTB = kTRUE;
472 mMinuit->mnexcm(
"CLEar", 0, 0, mStatusMin);
484 static Double_t step[3] = {0.03, 0.03, 0.03};
488 if (!mExternalSeedPresent) {
495 Float_t old_vtx_z = -999;
496 Double_t seed_z = -999;
497 Double_t chisquare = 0;
499 for (Int_t iSeed = 0; iSeed < mNSeed; iSeed++) {
502 mMinuit->mnexcm(
"CLEar", 0, 0, mStatusMin);
504 seed_z= mSeedZ[iSeed];
506 if (mExternalSeedPresent)
507 seed_z = mExternalSeed.z();
509 LOG_INFO <<
"Vertex seed = " << seed_z << endm;
513 mMinuit->mnparm(0,
"z", seed_z, step[2], 0, 0, mStatusMin);
516 mMinuit->mnparm(0,
"x", 0, step[0], 0, 0, mStatusMin);
517 mMinuit->mnparm(1,
"y", 0, step[1], 0, 0, mStatusMin);
518 mMinuit->mnparm(2,
"z", seed_z, step[2], 0, 0, mStatusMin);
525 Int_t n_helix = mHelices.size();
529 for (Int_t i=0; i < n_helix; i++) {
530 if (fabs(mZImpact[i]-seed_z) < mDcaZMax) {
531 mHelixFlags[i] |= kFlagDcaz;
535 mHelixFlags[i] &= ~kFlagDcaz;
539 LOG_INFO << n_trk_vtx <<
" tracks within dcaZ cut (iter " << iter <<
" )" << endm;
541 if (n_trk_vtx < mMinTrack) {
543 LOG_INFO <<
"Less than mMinTrack (=" << mMinTrack <<
") tracks, skipping vtx" << endm;
547 mMinuit->mnexcm(
"MINImize", 0, 0, mStatusMin);
552 LOG_WARN <<
"StMinuitVertexFinder::fit: error in Minuit::mnexcm(), check status flag. ( iter=" << iter <<
")" << endm;
556 Double_t fedm, errdef;
559 mMinuit->mnstat(chisquare, fedm, errdef, npari, nparx, mStatusMin);
561 if (mStatusMin != 3) {
562 LOG_INFO <<
"Warning: Minuit Status: " << mStatusMin <<
", func val " << chisquare<< endm;
567 Double_t new_z, zerr;
569 mMinuit->GetParameter(0, new_z, zerr);
572 mMinuit->GetParameter(2, new_z, zerr);
575 if (fabs(new_z - seed_z) > 1)
579 for (Int_t i=0; i < n_helix; i++) {
580 if ( fabs(mZImpact[i] - new_z) < mDcaZMax ) {
584 if ( 10 * abs(n_trk - n_trk_vtx) >= n_trk_vtx )
589 }
while (!done && iter < 5 && n_trk_vtx >= mMinTrack);
591 if (n_trk_vtx < mMinTrack)
595 LOG_WARN <<
"Vertex unstable: no convergence after " << iter <<
" iterations. Skipping vertex " << endm;
599 if (!mExternalSeedPresent && fabs(seed_z-mSeedZ[iSeed]) > mDcaZMax) {
600 LOG_WARN <<
"Vertex walks during fits: seed was " << mSeedZ[iSeed] <<
", vertex at " << seed_z << endm;
603 if (fabs(seed_z - old_vtx_z) < mDcaZMax) {
605 LOG_INFO <<
"Vertices too close (<mDcaZMax). Skipping" << endm;
613 memset(cov,0,
sizeof(cov));
617 mMinuit->GetParameter(0, val, verr);
618 XVertex.setZ(val); cov[5]=verr*verr;
622 XVertex.setX(
beamX(val)); cov[0]=0.1;
623 XVertex.setY(
beamY(val)); cov[2]=0.1;
626 XVertex =
StThreeVectorD(mMinuit->fU[0],mMinuit->fU[1],mMinuit->fU[2]);
631 mMinuit->mnemat(emat,3);
640 primV.setPosition(XVertex);
641 primV.setChiSquared(chisquare);
642 primV.setCovariantMatrix(cov);
643 primV.setVertexFinderId(minuitVertexFinder);
645 primV.setRanking(333);
646 primV.setNumTracksUsedInFinder(n_trk_vtx);
648 Int_t n_ctb_match = 0;
649 Int_t n_bemc_match = 0;
653 Double_t mean_dip = 0;
655 for (UInt_t i=0; i < mHelixFlags.size(); i++) {
656 if (!(mHelixFlags[i] & kFlagDcaz))
659 if (mHelixFlags[i] & kFlagCTBMatch)
661 if (mHelixFlags[i] & kFlagBEMCMatch)
663 if (mHelixFlags[i] & kFlagCrossMembrane)
665 mean_dip += mHelices[i].dipAngle();
666 sum_pt += mHelices[i].momentum(0).perp();
669 mean_dip /= n_trk_vtx;
672 LOG_INFO <<
"check n_trk_vtx " << n_trk_vtx <<
", found "
673 << n_ctb_match <<
" ctb matches, "
674 << n_bemc_match <<
" bemc matches, "
675 << n_cross <<
" tracks crossing central membrane\n"
676 <<
"mean dip " << mean_dip << endm;
678 primV.setNumMatchesWithCTB(n_ctb_match);
679 primV.setNumMatchesWithBEMC(n_bemc_match);
680 primV.setNumTracksCrossingCentralMembrane(n_cross);
681 primV.setMeanDip(mean_dip);
682 primV.setSumOfTrackPt(sum_pt);
687 old_vtx_z = XVertex.z();
694 mExternalSeedPresent = kFALSE;
703 double StMinuitVertexFinder::CalcChi2DCAs(
const StThreeVectorD &vtx) {
707 if (fabs(vtx.x())> 10)
return 1e6;
708 if (fabs(vtx.y())> 10)
return 1e6;
709 if (fabs(vtx.z())>300)
return 1e6;
710 for (UInt_t i=0; i<
mDCAs.size(); i++) {
712 if ( !(mHelixFlags[i] & kFlagDcaz) || (requireCTB && !(mHelixFlags[i] & kFlagCTBMatch)) )
716 if (! gDCA)
continue;
722 Double_t chi2 = gDCA->thelix().
Dca(&(vtx.x()),&err2);
725 static double scale = 100;
726 f += scale*(1. - TMath::Exp(-chi2/scale));
728 if((mHelixFlags[i] & kFlagCTBMatch) && e<3.0) nCTBHits++;
737 bool StMinuitVertexFinder::accept(
StTrack* track)
const
740 track->flag() >= 0 &&
741 track->fitTraits().numberOfFitPoints() >= mMinNumberOfFitPointsOnTrack &&
742 !track->topologyMap().trackFtpc() &&
743 finite(track->length()) &&
744 track->geometry()->helix().
valid());
751 mMinuit->SetPrintLevel(level);
755 void StMinuitVertexFinder::printInfo(ostream& os)
const
757 os <<
"StMinuitVertexFinder - Statistics:" << endl;
758 os <<
"Number of vertices found ......." << size() << endl;
759 os <<
"Rank of best vertex ............" << mBestRank << endl;
761 os <<
"Properties of best vertex:" << endl;
762 os <<
"position ..................... " << mBestVtx->position() << endl;
763 os <<
"position errors .............. " << mBestVtx->positionError()<< endl;
764 os <<
"# of used tracks ............. " << mBestVtx->numTracksUsedInFinder() << endl;
765 os <<
"Chisquare .................... " << mBestVtx->chiSquared() << endl;
767 os <<
"min # of fit points for tracks . " << mMinNumberOfFitPointsOnTrack << endl;
771 Int_t StMinuitVertexFinder::NCtbMatches() {
bool valid(double world=1.e+5) const
checks for valid parametrization
double beamX(double z) const
double beamY(double z) const
double distance(const StThreeVector< double > &p, bool scanPeriods=true) const
minimal distance between point and helix
pair< double, double > pathLength(double r) const
path length at given r (cylindrical r)
void setPrintLevel(Int_t=0)
Use mMinuit print level.
VertexFit_t mVertexFitMode
The type of vertex fit to use in derived concrete implementation.
static StGenericVertexFinder * sSelf
By default point to invalid object.
Int_t getBin(const Float_t phi, const Float_t eta, Int_t &m, Int_t &e, Int_t &s) const
double Dca(const double point[3], double *dcaErr=0) const
DCA to given space point (with error matrix)