6 #include "GaudiKernel/ITHistSvc.h"
15 using namespace InDet;
20 void myFCN_LLsolver( Int_t &, Double_t *, Double_t &, Double_t *, Int_t);
23 double pdfxy(
double *
x,
double *
p);
34 return std::abs(
a - m_median) < std::abs(
b -m_median);
40 const std::string&
name,
43 m_x(4),m_cov(4,0),m_z(0.),m_zErr(0.),
45 m_zSolved(0.), m_zErrSolved(0.),
46 m_NPARS(10), m_pLL(m_NPARS,0),m_VLL(m_NPARS,0),
47 m_vertexCount(0),m_getLLres(false),
48 m_fitStatus(unsolved),m_minVtxProb{},m_nUsed(0)
51 declareInterface<IInDetBeamSpotTool>(
this);
52 declareProperty(
"UseLikelihood",m_useLL =
true);
55 declareProperty(
"InitParX", m_init_x =0.0);
56 declareProperty(
"InitParY", m_init_y =0.0);
57 declareProperty(
"InitParZ", m_init_z =0.0);
58 declareProperty(
"InitParAx", m_init_ax=0.0);
59 declareProperty(
"InitParAy", m_init_ay=0.0);
60 declareProperty(
"InitParSigmaX", m_init_sx=0.01);
61 declareProperty(
"InitParSigmaY", m_init_sy=0.01);
62 declareProperty(
"InitParSigmaZ", m_init_sz=56.0);
63 declareProperty(
"InitParK", m_init_k =1.0);
64 declareProperty(
"InitParRhoXY", m_init_rhoxy=0.0);
65 declareProperty(
"MinuitMaxIterations", m_minuit_maxIter=2000);
66 declareProperty(
"InitParMinX", m_init_min_x =0.0);
67 declareProperty(
"InitParMinY", m_init_min_y =0.0);
68 declareProperty(
"InitParMinZ", m_init_min_z =0.0);
69 declareProperty(
"InitParMinAx", m_init_min_ax=0.0);
70 declareProperty(
"InitParMinAy", m_init_min_ay=0.0);
71 declareProperty(
"InitParMinSigmaX", m_init_min_sx=0.0001);
72 declareProperty(
"InitParMinSigmaY", m_init_min_sy=0.0001);
74 declareProperty(
"InitParMinSigmaZ", m_init_min_sz=0.0);
75 declareProperty(
"InitParMinK", m_init_min_k =0);
76 declareProperty(
"InitParMinRhoXY", m_init_min_rhoxy=-1.0);
78 declareProperty(
"InitParMaxX", m_init_max_x =0.0);
79 declareProperty(
"InitParMaxY", m_init_max_y =0.0);
80 declareProperty(
"InitParMaxZ", m_init_max_z =0.0);
81 declareProperty(
"InitParMaxAx", m_init_max_ax=0.0);
82 declareProperty(
"InitParMaxAy", m_init_max_ay=0.0);
83 declareProperty(
"InitParMaxSigmaX", m_init_max_sx=2.0);
84 declareProperty(
"InitParMaxSigmaY", m_init_max_sy=2.0);
85 declareProperty(
"InitParMaxSigmaZ", m_init_max_sz=3000.);
86 declareProperty(
"InitParMaxK", m_init_max_k =10.);
87 declareProperty(
"InitParMaxRhoXY", m_init_max_rhoxy=1.0);
89 declareProperty(
"DefaultX0", m_def_x0=0.0);
90 declareProperty(
"DefaultY0", m_def_y0=0.0);
91 declareProperty(
"DefaultZ", m_def_z=0.0);
92 declareProperty(
"DefaultTiltX", m_def_ax=0.0);
93 declareProperty(
"DefaultTiltY", m_def_ay=0.0);
95 declareProperty(
"DefaultSigmaX", m_def_sx=0.0);
96 declareProperty(
"DefaultSigmaY", m_def_sy=0.0);
97 declareProperty(
"DefaultSigmaZ", m_def_sz=0.0);
101 declareProperty(
"MaxSigmaTr", m_sigTr=20.);
102 declareProperty(
"MaxVtxErrTr", m_maxVtxErTr=100.);
103 declareProperty(
"OutlierChi2Tr", m_outlierChi2Tr=20.);
104 declareProperty(
"MaxOutlierLoops",m_maxOutlierLoops = 30);
105 declareProperty(
"OutlierMaxRejection",m_singleIterationMax=30);
106 declareProperty(
"OutlierWidthFail", m_widthFail=5.1
e-3);
107 declareProperty(
"OutlierRhoFail", m_rhoFail=0.8);
109 declareProperty(
"OutlierKFailMin", m_kMinFail = 0);
110 declareProperty(
"OutlierKFailMax", m_kMaxFail = 9.9);
112 declareProperty(
"DoFitSanityCheck", m_doFitSanityCheck=
true);
113 declareProperty(
"DoChi2OnlyOutlierRemoval",m_doChi2OutlierRemoval=
false);
116 declareProperty(
"FixParK" , m_fixInputK =
false);
117 declareProperty(
"UseLLNorm" , m_useLLNorm =
false);
118 declareProperty(
"FixWidth", m_fixWidth =
false);
120 declareProperty(
"TruncatedRMS", m_truncatedRMS =
true);
121 declareProperty(
"RMSFraction", m_fractionRMS = 0.95);
122 declareProperty(
"SetInitialRMS", m_setInitialRMS =
false);
129 m_x(4),m_cov(4,0),m_z(0.),m_zErr(0.),
131 m_zSolved(0.), m_zErrSolved(0.),
132 m_NPARS(10), m_pLL(m_NPARS,0),m_VLL(m_NPARS,0),
133 m_vertexCount(0),m_getLLres(false),
134 m_fitStatus(unsolved),m_nUsed(0)
212 return StatusCode::SUCCESS;
219 return StatusCode::SUCCESS;
252 bool llResult =
false;
258 ATH_MSG_WARNING(
"Log-likelihood fit failed: Reverting to chi2 solution" );
266 bool printOut =
true;
269 ATH_MSG_WARNING(
"Log-likelihood fit failed: Reverting to chi2 solution" );
285 <<
" using Vertex " << (
m_getLLres ?
"Log-likelihood":
"Chi2") <<
" method" );
309 CLHEP::HepSymMatrix
c(4,0);
352 TMinuit * minuit =
new TMinuit(
m_NPARS);
358 minuit->SetPrintLevel(1);
361 minuit->SetPrintLevel(0);
363 minuit->SetPrintLevel(-1);
368 minuit->SetErrorDef(0.5);
374 minuit->mnexcm(
"SET STR",arglist,1,errFlag);
386 std::pair<int, std::string>
status;
388 bool goodFit =
false;
394 if (
status.first == 3 && (
status.second ==
"SUCCESSFUL" ||
395 status.second ==
"CONVERGED " ||
396 status.second ==
"CONVERGED") ){
420 minuit->GetParameter(
i,
m_pLL(
i+1) ,
t);
521 double meanx(0.),meany(0.), meanz(0.);
522 double meanxSqr(0.),meanySqr(0.), meanzSqr(0.);
523 double rmsX(0.),rmsY(0.), rmsZ(0.);
526 std::vector<double> vx,vy,vz;
532 if (!
it->valid)
continue;
536 meanxSqr += (
it->x)*(
it->x);
538 meanySqr += (
it->y)*(
it->y);
540 meanzSqr += (
it->z)*(
it->z);
551 std::sort(vx.begin(),vx.end());
552 std::sort(vy.begin(),vy.end());
553 std::sort(vz.begin(),vz.end());
556 double medianx = (vx.size() > 1 ? vx.at(vx.size()/2) : 0.);
557 double mediany = (vy.size() > 1 ? vy.at(vy.size()/2) : 0.);
558 double medianz = (vz.size() > 1 ? vz.at(vz.size()/2) : 0.);
562 <<
" z: " << medianz );
580 for (
unsigned int ivtx(0); ivtx < vx.size(); ++ivtx) {
581 double x = vx.at(ivtx);
582 double y = vy.at(ivtx);
583 double z = vz.at(ivtx);
599 rmsX = std::sqrt( std::abs(meanxSqr - meanx*meanx));
602 rmsY = std::sqrt( std::abs(meanySqr - meany*meany));
605 rmsZ = std::sqrt( std::abs(meanzSqr - meanz*meanz));
619 <<
" " <<
", y: " << meany <<
" " << rmsY <<
", z: " << meanz <<
" " << rmsZ );
623 CLHEP::HepVector chi2Pos(4);
624 CLHEP::HepSymMatrix chi2Cov(4);
625 double zpos(0), zerr(0);
634 if (!
it->valid)
continue;
639 if ( std::abs( medianz -
it->z ) > 10*rmsZ)
fail += 16;
642 if ( (medianx -
it->x)*(medianx-
it->x)/rmsX/rmsX + (mediany-
it->y)*(mediany-
it->y)/rmsY/rmsY >
m_sigTr*
m_sigTr) {
643 ATH_MSG_DEBUG(
"Vertex info: extended past radial extent: sig."
644 << sqrt((medianx -
it->x)*(medianx-
it->x)/rmsX/rmsX + (mediany-
it->y)*(mediany-
it->y)/rmsY/rmsY) <<
" > "
652 ATH_MSG_DEBUG(
"Vertex reject from simple mean; reason: " <<
fail <<
" : x,y,z: "
653 <<
it->x <<
" " <<
it->y <<
" " <<
it->z
654 <<
" , sigma(x,y,z): " << sqrt(
it->vxx) <<
" " << sqrt(
it->vyy)
655 <<
" " << sqrt(
it->vzz)
663 chi2Pos(1) +=
it->x *
it->vxx +
it->y*
it->vxy;
664 chi2Pos(2) +=
it->x*
it->vxx*
it->z +
it->y*
it->vxy*
it->z;
665 chi2Pos(3) +=
it->y*
it->vyy +
it->x*
it->vxy;
666 chi2Pos(4) +=
it->y*
it->vyy*
it->z +
it->x*
it->vxy*
it->z;
669 chi2Cov.fast(1,1) +=
it->vxx;
670 chi2Cov.fast(2,1) +=
it->vxx*
it->z;
671 chi2Cov.fast(2,2) +=
it->vxx*
it->z*
it->z;
672 chi2Cov.fast(3,1) +=
it->vxy;
673 chi2Cov.fast(3,2) +=
it->vxy*
it->z;
674 chi2Cov.fast(3,3) +=
it->vyy;
675 chi2Cov.fast(4,1) +=
it->vxy*
it->z;
676 chi2Cov.fast(4,2) +=
it->vxy*
it->z*
it->z;
677 chi2Cov.fast(4,3) +=
it->vyy*
it->z;
678 chi2Cov.fast(4,4) +=
it->vyy*
it->z*
it->z;
680 zpos +=
it->z/
it->vzz;
685 ATH_MSG_DEBUG(
"Removed: " << failCount <<
" vertices from simple mean,RMS." );
695 chi2Cov.invert(invFail);
696 chi2Pos = chi2Cov*chi2Pos;
698 zerr = 1./std::sqrt(zerr);
705 ATH_MSG_DEBUG(
"Mean position: x,y,z " << meanx <<
" " << meany <<
" " << meanz );
706 ATH_MSG_DEBUG(
" RMS: x,y,z " << rmsX <<
" " << rmsY <<
" " << rmsZ );
710 ATH_MSG_DEBUG(
"New chi2:" << chi2Pos <<
"\n" << chi2Cov <<
"\n" << zpos <<
" " << zerr );
735 ATH_MSG_INFO(
"Log-Likelihood fit converged in outlier removal. Exiting outlier removal." );
739 CLHEP::HepSymMatrix bsCov(2);
751 ATH_MSG_INFO(
": removeOutliers: LL fit not use/converged/trusted - " <<
752 "using chi2 for mean and simple RMS for width values " );
759 bsCov(1,1) = rmsX*rmsX;
760 bsCov(2,2) = rmsY*rmsY;
777 std::multimap<double, BeamSpot::VrtHolder*> chi2map;
782 if ( !
it->valid)
continue;
794 double increaseChi2(0);
796 increaseChi2 =
fail * 1e5;
801 CLHEP::HepSymMatrix
b(2);
804 b(1,1) =
it->vxx + bsCov(1,1);
805 b(2,2) =
it->vyy + bsCov(2,2);
806 b(2,1) =
it->vxy + bsCov(2,1);
810 if (failInv)
continue;
811 double ch = (
it->x - (xbar +
it->z*
ax)) *
b(1,1) * (
it->x - (xbar +
it->z*
ax))
812 + (
it->y - (ybar +
it->z*
ay)) *
b(2,2) * (
it->y - (ybar +
it->z*
ay))
813 + 2*(
it->x - (xbar +
it->z*
ax)) *
b(2,1) * (
it->y - (ybar +
it->z*
ay));
820 chi2map.insert(std::make_pair(
ch, &(*
it)));
826 for (std::multimap<double, BeamSpot::VrtHolder*>::reverse_iterator vit = chi2map.rbegin(); vit != chi2map.rend(); ++vit) {
827 if ( !vit->second)
continue;
828 if ( !vit->second->valid)
continue;
830 ATH_MSG_DEBUG(
" removeOutlier: Reached max number of vertex rejections for this iteration.\n"
831 <<
"\tNeed to recalculate mean positions." );
841 ATH_MSG_DEBUG(
" No more 'bad' vertices found in this iteration." );
843 ATH_MSG_DEBUG(
" No futher vertices removed - moving to final iteration" );
845 ATH_MSG_DEBUG(
" Moving to next iteration of outlier removal." );
853 vit->second->valid =
false;
855 ATH_MSG_DEBUG(
"Vertex rejected; chi2: " << vit->first <<
". pos(x,y,z): "
856 << vit->second->x <<
" " << vit->second->y <<
" " << vit->second->z
857 <<
" , sigma(x,y,z): " << sqrt(vit->second->vxx) <<
" " << sqrt(vit->second->vyy)
858 <<
" " << sqrt(vit->second->vzz)
865 ATH_MSG_WARNING(
"No vertices removed and fit still fails - most likely final result will fail" );
873 std::vector< BeamSpot::VrtHolder > vertexTemp(
m_vertexData);
875 std::random_device
rng;
876 std::mt19937 urng(
rng());
879 std::vector< BeamSpot::VrtHolder > vertex1,vertex2;
883 bool goodFit1(
false), goodFit2(
false);
889 ATH_MSG_WARNING(
"Fit using \"vertex1\" " << ( llSolve ?
"Successful":
"Failed") );
913 ATH_MSG_WARNING(
"Fit using \"vertex2\" " << ( llSolve ?
"Successful":
"Failed") );
933 ATH_MSG_WARNING(
"Fit was " << ( goodFit2 || goodFit1 ?
"Successful ":
"Unsuccessful ")
934 <<
" using a subset of the available vertices" );
935 if (( goodFit2 || goodFit1) )
941 }
else if (goodFit2) {
952 ATH_MSG_DEBUG(
" Recursive debug: Loop: " <<
m_rCount <<
". Number of failed vertices: " << fCount );
955 if ( fCount > 0 || ( fCount == 0 &&
m_rCount == 1 && !llSolve)) {
958 <<
". No more iterations performed." );
970 std::pair<int, std::string> &
status) {
971 if (!minuit)
return false;
973 std::string sRes = minuit->fCstatu.Data();
975 Double_t fmin, fedm, errdef;
976 Int_t npari,nparx,istat;
977 minuit->mnstat(fmin, fedm, errdef,npari,nparx,istat);
979 ATH_MSG_DEBUG(
"Fit reports status: " << istat <<
" and " << sRes );
984 bool sanityPassed(
true);
987 minuit->GetParameter(6,
x,ex);
989 sanityPassed =
false;
992 minuit->GetParameter(4,
x,ex);
994 sanityPassed =
false;
997 minuit->GetParameter(5,
x,ex);
999 sanityPassed =
false;
1003 minuit->GetParameter(7,
x,ex);
1005 sanityPassed =
false;
1013 if (!sanityPassed) {
1015 status.second =
"FAILED BEAMSPOT SANITY CHECK";
1017 ATH_MSG_DEBUG(
"Fit " << ( sanityPassed ?
"Passed":
"Failed") <<
" sanity check: " );
1019 if ( istat != 3)
return false;
1027 constexpr
double Pi =
M_PI;
1034 using Vertices = std::vector<BeamSpot::VrtHolder>;
1035 Vertices::const_iterator vit = BeamSpot::vertexData->begin();
1040 double covXX,covYY,covXY;
1044 for ( ; vit != vertexData->end(); ++vit) {
1045 if (!vit->valid)
continue;
1061 det = covXX * covYY - covXY*covXY;
1062 double recDet = 1./
det;
1065 temp = 2*TMath::Log(2*Pi);
1068 covXY = -covXY * recDet;
1069 double t = covXX *recDet;
1070 covXX = covYY *recDet;
1106 minuit->FixParameter(6);
1107 minuit->FixParameter(7);
1110 minuit->FixParameter(0);
1111 minuit->FixParameter(1);
1112 minuit->FixParameter(2);
1113 minuit->FixParameter(3);
1116 minuit->FixParameter(4);
1117 minuit->FixParameter(5);
1138 if(printOut) minuit->SetPrintLevel(0);
1150 std::map<std::string,double> covMap;
1151 std::vector<double> covVector;
1152 covVector.resize(55);
1157 int map[] = {1,2,9,3,4,5,6,10,7,8};
1159 int map2[] = {1,2,8,3,4,5,6,9,7,10};
1160 for(
int i=0;
i < 10; ++
i){
1164 int map2[] = {1,2,6,3,4,8,9,7,10,5};
1165 for(
int i=0;
i < 10; ++
i){
1171 for (
int i=0;
i<10;++
i) {
1172 for (
int j=
i;j<10;++j) {
1174 covVector[
temp++] = 0;
1175 }
else if (
m_fixWidth && (
i == 5 ||
i == 6 ||
i == 8 || j == 5 || j == 6 || j == 8 ) ){
1176 covVector[
temp++] = 0;
1185 const std::string keyArr[] = {
"posXErr",
"covXY",
"covXZ",
"covXTiltX",
"covXTiltY",
"covXSx",
"covXSy",
"covXSz",
"covXRhoXY",
"covXk",
1186 "posYErr",
"covYZ",
"covYTiltX",
"covYTiltY",
"covYSx",
"covYSy",
"covYSz",
"covYRhoXY",
"covYk",
1187 "posZErr",
"covZTiltX",
"covZTiltY",
"covZSx",
"covZSy",
"covZSz",
"covZRhoXY",
"covZk",
1188 "tiltXErr",
"covTiltXTiltY",
"covTiltXSx",
"covTiltXSy",
"covTiltXSz",
"covTiltXRhoXY",
"covTiltXk",
1189 "tiltYErr",
"covTiltYSx",
"covTiltYSy",
"covTiltYSz",
"covTiltYRhoXY",
"covTiltYk",
1190 "sigmaXErr",
"covSxSy",
"covSxSz",
"covSxRhoXY",
"covSxk",
1191 "sigmaYErr",
"covSySz",
"covSyRhoXY",
"covSyk",
1192 "sigmaZErr",
"covSzRhoXY",
"covSzk",
1193 "rhoXYErr",
"covRhoXYk",
1200 for(
int i = 0;
i < 55;
i++){
1201 covMap[keyArr[
i]] = covVector[
i];
1206 covMap[ keyArr[0] ] = sqrt(covVector[0]);
1207 covMap[ keyArr[10] ] = sqrt(covVector[10]);
1208 covMap[ keyArr[19] ] = sqrt(covVector[19]);
1209 covMap[ keyArr[27] ] = sqrt(covVector[27]);
1210 covMap[ keyArr[34] ] = sqrt(covVector[34]);
1211 covMap[ keyArr[40] ] = sqrt(covVector[40]);
1212 covMap[ keyArr[45] ] = sqrt(covVector[45]);
1213 covMap[ keyArr[49] ] = sqrt(covVector[49]);
1214 covMap[ keyArr[52] ] = sqrt(covVector[52]);
1215 covMap[ keyArr[54] ] = sqrt(covVector[54]);
1222 CLHEP::HepSymMatrix covc =
getCov(
z);
1224 covMap[
"posXErr"] = sqrt( covc(1,1) );
1225 covMap[
"posYErr"] = sqrt( covc(2,2) );
1226 covMap[
"tiltXErr"] = sqrt( covc(3,3) );
1227 covMap[
"tiltYErr"] = sqrt( covc(4,4) );
1238 std::map<std::string,double> paramMap;