18#include "Math/Factory.h"
19#include "Math/UnaryOperators.h"
42 mMinimizer.reset(ROOT::Math::Factory::CreateMinimizer(
"Minuit2",
"Migrad"));
43 if (mMinimizer ==
nullptr) {
44 LOGP(fatal,
"Cannot create minimizer");
46 mMinimizer->SetMaxFunctionCalls(1'000'000'000);
47 mMinimizer->SetStrategy(0);
48 mMinimizer->SetPrintLevel(0);
51 LOGP(info,
"Using propagator to find intersection");
54 mMinimizer->SetFunction(mPropagator);
56 LOGP(info,
"Using local straight-line to find intersection");
57 mMinimizer->SetFunction(mLine);
63 LOGP(fatal,
"No parameter file specified");
71 ++mStats[Stats::kHitTotal];
74 ++mStats[Stats::kHitIsOB];
77 ++mStats[Stats::kHitIsIB];
81 mCurWorkingHits[WorkingHit::kEntering] = WorkingHit(iEvent, WorkingHit::kEntering, hit);
82 mCurWorkingHits[WorkingHit::kExiting] = WorkingHit(iEvent, WorkingHit::kExiting, hit);
85 if (!deformHit(WorkingHit::kEntering) || !deformHit(WorkingHit::kExiting)) {
86 ++mStats[Stats::kHitDead];
89 ++mStats[Stats::kHitAlive];
92 auto midPointOrig = mCurWorkingHits[WorkingHit::kEntering].mPoint + (mCurWorkingHits[WorkingHit::kExiting].mPoint - mCurWorkingHits[WorkingHit::kEntering].mPoint) * 0.5;
93 auto midPointDef = mCurWorkingHits[WorkingHit::kEntering].mPointDef + (mCurWorkingHits[WorkingHit::kExiting].mPointDef - mCurWorkingHits[WorkingHit::kEntering].mPointDef) * 0.5;
94 const short idDef = getDetID(midPointDef), idOrig = getDetID(midPointOrig);
99 if (idDef != idOrig) {
100 ++mStats[Stats::kHitMigrated];
102 ++mStats[Stats::kHitNotMigrated];
105 if constexpr (
false) {
108 bool crossesBoundary{
false};
109 TGeoNode *nEnt{
nullptr}, *nExt{
nullptr};
111 auto dirEnt = mCurWorkingHits[WorkingHit::kEntering].mPointDef - midPointDef;
112 auto stepEnt = std::min(
static_cast<double>(dirEnt.R()), std::abs(dirEnt.R() - 5.e-4));
113 auto dirEntU = dirEnt.Unit();
114 gGeoManager->SetCurrentPoint(midPointDef.X(), midPointDef.Y(), midPointDef.Z());
115 gGeoManager->SetCurrentDirection(dirEntU.X(), dirEntU.Y(), dirEntU.Z());
116 nEnt = gGeoManager->FindNextBoundaryAndStep(stepEnt,
false);
117 if (gGeoManager->IsOnBoundary()) {
118 ++mStats[Stats::kHitEntBoundary];
119 crossesBoundary =
true;
123 auto dirExt = midPointDef - mCurWorkingHits[WorkingHit::kEntering].mPointDef;
124 auto stepExt = std::min(
static_cast<double>(dirExt.R()), std::abs(dirExt.R() - 5.e-4));
125 auto dirExtU = dirExt.Unit();
126 gGeoManager->SetCurrentPoint(midPointDef.X(), midPointDef.Y(), midPointDef.Z());
127 gGeoManager->SetCurrentDirection(dirExtU.X(), dirExtU.Y(), dirExtU.Z());
128 nExt = gGeoManager->FindNextBoundaryAndStep(stepExt,
false);
129 if (gGeoManager->IsOnBoundary()) {
130 ++mStats[Stats::kHitExtBoundary];
131 crossesBoundary =
true;
135 if (crossesBoundary && nEnt !=
nullptr && nExt !=
nullptr) {
139 ++mStats[Stats::kHitSameBoundary];
142 ++mStats[Stats::kHitNoBoundary];
146 mCurHit.
SetPosStart(mCurWorkingHits[WorkingHit::kEntering].mPointDef);
147 mCurHit.
SetPos(mCurWorkingHits[WorkingHit::kExiting].mPointDef);
150 ++mStats[Stats::kHitSuccess];
154bool MisAlignmentHits::deformHit(WorkingHit::HitType t)
156 auto& wHit = mCurWorkingHits[t];
159 constexpr double minStep{1e-5};
160 constexpr double zMargin{4.0};
161 constexpr double phiMargin{0.4};
163 prepareLineMethod(t);
164 mMinimizer->SetVariable(0,
"t", 0.0, minStep);
166 if (!preparePropagatorMethod(t)) {
169 mMinimizer->SetVariable(0,
"r", mPropagator.mTrack.getX(), minStep);
171 mMinimizer->SetLimitedVariable(1,
"phiStar", wHit.mPhi, minStep,
172 std::max(
static_cast<double>(wHit.mPhiBorder1),
static_cast<double>(wHit.mPhi) - phiMargin),
173 std::min(
static_cast<double>(wHit.mPhiBorder2),
static_cast<double>(wHit.mPhi) + phiMargin));
174 mMinimizer->SetLimitedVariable(2,
"zStar", wHit.mPoint.Z(), minStep,
175 std::max(
static_cast<double>(-constants::segment::lengthSensitive / 2.f),
static_cast<double>(wHit.mPoint.Z()) - zMargin),
176 std::min(
static_cast<double>(constants::segment::lengthSensitive / 2.f),
static_cast<double>(wHit.mPoint.Z()) + zMargin));
178 mMinimizer->Minimize();
180 auto ss = mMinimizer->Status();
182 ++mStats[Stats::kMinimizerCovPos];
183 }
else if (ss == 2) {
184 ++mStats[Stats::kMinimizerHesse];
185 }
else if (ss == 3) {
186 ++mStats[Stats::kMinimizerEDM];
187 }
else if (ss == 4) {
188 ++mStats[Stats::kMinimizerLimit];
189 }
else if (ss == 5) {
190 ++mStats[Stats::kMinimizerOther];
192 ++mStats[Stats::kMinimizerConverged];
195 if (ss == 0 || ss == 1) {
196 ++mStats[Stats::kMinimizerStatusOk];
197 if (mMinimizer->MinValue() < 2e-4) {
198 ++mStats[Stats::kMinimizerValueOk];
200 ++mStats[Stats::kMinimizerValueBad];
204 ++mStats[Stats::kMinimizerStatusBad];
209 wHit.recalculateIdeal(
static_cast<float>(mMinimizer->X()[1]),
static_cast<float>(mMinimizer->X()[2]));
217 gGeoManager->PushPath();
218 auto id = getDetIDFromCords(point);
219 gGeoManager->PopPath();
226 const auto node = gGeoManager->FindNode(point.X(), point.Y(), point.Z());
227 if (node ==
nullptr) {
228 ++mStats[Stats::kFindNodeFailed];
231 ++mStats[Stats::kFindNodeSuccess];
234 const std::string
path = gGeoManager->GetPath();
236 ++mStats[Stats::kProjNonSensitive];
239 ++mStats[Stats::kProjSensitive];
241 return getDetIDFromPath(
path);
244short MisAlignmentHits::getDetIDFromPath(
const std::string&
path)
const
246 static const std::regex
pattern{R
"(/cave_1/barrel_1/ITSV_2/ITSUWrapVol0_1/ITS3Layer(\d+)_(\d+)/ITS3CarbonForm(\d+)_(\d+)/ITS3Chip(\d+)_(\d+)/ITS3Segment(\d+)_(\d+)/ITS3RSU(\d+)_(\d+)/ITS3Tile(\d+)_(\d+)/ITS3PixelArray(\d+)_(\d+))"};
247 if (std::smatch matches; std::regex_search(
path, matches,
pattern)) {
248 if (matches.size() == 15) {
249 int iLayer = std::stoi(matches[1]);
250 int iCarbonForm = std::stoi(matches[4]);
251 int iSegment = std::stoi(matches[8]);
252 int iRSU = std::stoi(matches[10]);
253 int iTile = std::stoi(matches[12]);
254 return mGeo->
getChipIndex(iLayer, iCarbonForm, 0, iSegment, iRSU, iTile);
256 LOGP(fatal,
"Path did not contain expected number of matches ({})!", matches.size());
259 LOGP(fatal,
"Path was not matched ({})!",
path);
261 __builtin_unreachable();
266 auto makeFraction = [&](Stats
n, Stats d) ->
float {
return static_cast<float>(mStats[
n]) /
static_cast<float>(mStats[d] + mStats[
n]); };
267 LOGP(info,
"Processed {} Hits (IB:{}; OB:{}) ({:.2f}%):", mStats[Stats::kHitTotal], mStats[Stats::kHitIsIB], mStats[Stats::kHitIsOB], makeFraction(Stats::kHitIsIB, Stats::kHitIsOB));
268 LOGP(info,
" - Minimizer Status: {} ok {} bad ({:.2f}%)", mStats[Stats::kMinimizerStatusOk], mStats[Stats::kMinimizerStatusBad], makeFraction(Stats::kMinimizerStatusOk, Stats::kMinimizerStatusBad));
269 LOGP(info,
" - Minimizer Value: {} ok {} bad ({:.2f}%)", mStats[Stats::kMinimizerValueOk], mStats[Stats::kMinimizerValueBad], makeFraction(Stats::kMinimizerValueOk, Stats::kMinimizerValueBad));
270 LOGP(info,
" - Minimizer Detailed: {} Converged {} pos. forced Hesse ({:.2f}%)", mStats[Stats::kMinimizerConverged], mStats[Stats::kMinimizerHesse], makeFraction(Stats::kMinimizerConverged, Stats::kMinimizerHesse));
271 LOGP(info,
" - Minimizer Detailed: {} EDM {} call limit {} other ({:.2f}%)", mStats[Stats::kMinimizerEDM], mStats[Stats::kMinimizerLimit], mStats[Stats::kMinimizerOther], makeFraction(Stats::kMinimizerEDM, Stats::kMinimizerLimit));
272 LOGP(info,
" - FindNode: {} ok {} failed", mStats[Stats::kFindNodeSuccess], mStats[Stats::kFindNodeFailed]);
273 LOGP(info,
" - IsSensitve: {} yes {} no ({:.2f}%)", mStats[Stats::kProjSensitive], mStats[Stats::kProjNonSensitive], makeFraction(Stats::kProjSensitive, Stats::kProjNonSensitive));
274 LOGP(info,
" - IsAlive: {} yes {} no ({:.2f}%)", mStats[Stats::kHitAlive], mStats[Stats::kHitDead], makeFraction(Stats::kHitAlive, Stats::kHitDead));
275 LOGP(info,
" - HasMigrated: {} yes {} no ({:.2f}%)", mStats[Stats::kHitMigrated], mStats[Stats::kHitNotMigrated], makeFraction(Stats::kHitMigrated, Stats::kHitNotMigrated));
278 LOGP(info,
" - Propagator: {} null track {} null pdg", mStats[Stats::kPropTrackNull], mStats[Stats::kPropPDGNull]);
280 LOGP(info,
" --> Good Hits {} ({:.2f}%)", mStats[Stats::kHitSuccess], makeFraction(Stats::kHitSuccess, Stats::kHitIsIB));
283void MisAlignmentHits::prepareLineMethod(WorkingHit::HitType from)
287 mLine.mStart = mCurWorkingHits[WorkingHit::kEntering].mPoint;
288 mLine.mRadius = mCurWorkingHits[from].mRadius;
289 mLine.mSensorID = mCurWorkingHits[from].mSensorID;
290 mLine.mPhiTot = mCurWorkingHits[from].mPhiBorder2 - mCurWorkingHits[from].mPhiBorder1;
291 mLine.mPhi1 = mCurWorkingHits[from].mPhiBorder1;
293 mLine.mD[0] = mCurWorkingHits[WorkingHit::kExiting].mPoint.X() - mCurWorkingHits[WorkingHit::kEntering].mPoint.X();
294 mLine.mD[1] = mCurWorkingHits[WorkingHit::kExiting].mPoint.Y() - mCurWorkingHits[WorkingHit::kEntering].mPoint.Y();
295 mLine.mD[2] = mCurWorkingHits[WorkingHit::kExiting].mPoint.Z() - mCurWorkingHits[WorkingHit::kEntering].mPoint.Z();
298double MisAlignmentHits::StraightLine::DoEval(
const double*
x)
const
300 const double t =
x[0];
301 const double phi =
x[1];
302 const double z =
x[2];
303 const double nphi = std::clamp((phi - mPhi1) * 2.0 / mPhiTot - 1.0, -1.0, 1.0);
304 const double nz = std::clamp((
z - (-constants::segment::lengthSensitive / 2.0)) * 2.0 / constants::segment::lengthSensitive - 1.0, -1.0, 1.0);
307 double xline = mStart.X() + t * mD[0],
308 yline = mStart.Y() + t * mD[1],
309 zline = mStart.Z() + t * mD[2];
312 double xideal = mRadius * std::cos(phi), yideal = mRadius * std::sin(phi),
314 const auto [dx, dy, dz] = mMis->getDeformation(mSensorID, nphi, nz);
315 double xdef = xideal + dx, ydef = yideal + dy, zdef = zideal + dz;
318 return std::hypot(xline - xdef, yline - ydef, zline - zdef);
321bool MisAlignmentHits::preparePropagatorMethod(WorkingHit::HitType from)
323 mPropagator.mRadius = mCurWorkingHits[from].mRadius;
324 mPropagator.mSensorID = mCurWorkingHits[from].mSensorID;
325 mPropagator.mPhiTot = mCurWorkingHits[from].mPhiBorder2 - mCurWorkingHits[from].mPhiBorder1;
326 mPropagator.mPhi1 = mCurWorkingHits[from].mPhiBorder1;
327 const auto mcTrack = mMCReader->getTrack(mCurWorkingHits[from].mEvent, mCurWorkingHits[from].mTrackID);
328 if (mcTrack ==
nullptr) {
329 ++mStats[Stats::kPropTrackNull];
332 const std::array<float, 3> xyz{(float)mcTrack->GetStartVertexCoordinatesX(), (float)mcTrack->GetStartVertexCoordinatesY(), (float)mcTrack->GetStartVertexCoordinatesZ()},
333 pxyz{(
float)mcTrack->GetStartVertexMomentumX(), (
float)mcTrack->GetStartVertexMomentumY(), (
float)mcTrack->GetStartVertexMomentumZ()};
334 const TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrack->GetPdgCode());
335 if (pPDG ==
nullptr) {
336 ++mStats[Stats::kPropPDGNull];
339 mPropagator.mTrack =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
false);
344double MisAlignmentHits::Propagator::DoEval(
const double*
x)
const
346 const double r =
x[0];
347 const double phi =
x[1];
348 const double z =
x[2];
349 const double nphi = (
phi - mPhi1) * 2.0 / mPhiTot - 1.0;
350 const double nz = (
z - (-constants::segment::lengthSensitive / 2.0)) * 2.0 / constants::segment::lengthSensitive - 1.0;
353 if (!trc.propagateTo(
r, mBz)) {
356 const auto glo = trc.getXYZGlo();
359 double xideal = mRadius * std::cos(phi), yideal = mRadius * std::sin(phi),
361 const auto [dx, dy, dz] = mMis->getDeformation(mSensorID, nphi, nz);
362 double xdef = xideal + dx, ydef = yideal + dy, zdef = zideal + dz;
365 return std::hypot(glo.X() - xdef, glo.Y() - ydef, glo.Z() - zdef);
void SetDetectorID(short detID)
short GetDetectorID() const
void SetPos(math_utils::Point3D< T > const &p)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const ITS3Params & Instance()
std::optional< o2::itsmft::Hit > processHit(int iEvent, const o2::itsmft::Hit &hit)
static const char * getITS3SensorPattern()
static GeometryTGeo * Instance()
int getChipIndex(int lay, int detInLay) const
void SetPosStart(const math_utils::Point3D< Float_t > &p)
GLsizei const GLchar *const * path
GLdouble GLdouble GLdouble z
std::string digitizationgeometry_prefix
std::array< uint16_t, 5 > pattern