19#include "Math/Factory.h"
20#include "Math/UnaryOperators.h"
43 mMinimizer.reset(ROOT::Math::Factory::CreateMinimizer(
"Minuit2",
"Migrad"));
44 if (mMinimizer ==
nullptr) {
45 LOGP(fatal,
"Cannot create minimizer");
47 mMinimizer->SetMaxFunctionCalls(1'000'000'000);
48 mMinimizer->SetStrategy(0);
49 mMinimizer->SetPrintLevel(0);
52 LOGP(info,
"Using propagator to find intersection");
55 mMinimizer->SetFunction(mPropagator);
57 LOGP(info,
"Using local straight-line to find intersection");
58 mMinimizer->SetFunction(mLine);
64 LOGP(fatal,
"No parameter file specified");
72 ++mStats[Stats::kHitTotal];
75 ++mStats[Stats::kHitIsOB];
78 ++mStats[Stats::kHitIsIB];
82 mCurWorkingHits[WorkingHit::kEntering] = WorkingHit(iEvent, WorkingHit::kEntering, hit);
83 mCurWorkingHits[WorkingHit::kExiting] = WorkingHit(iEvent, WorkingHit::kExiting, hit);
86 if (!deformHit(WorkingHit::kEntering) || !deformHit(WorkingHit::kExiting)) {
87 ++mStats[Stats::kHitDead];
90 ++mStats[Stats::kHitAlive];
93 auto midPointOrig = mCurWorkingHits[WorkingHit::kEntering].mPoint + (mCurWorkingHits[WorkingHit::kExiting].mPoint - mCurWorkingHits[WorkingHit::kEntering].mPoint) * 0.5;
94 auto midPointDef = mCurWorkingHits[WorkingHit::kEntering].mPointDef + (mCurWorkingHits[WorkingHit::kExiting].mPointDef - mCurWorkingHits[WorkingHit::kEntering].mPointDef) * 0.5;
95 const short idDef = getDetID(midPointDef), idOrig = getDetID(midPointOrig);
100 if (idDef != idOrig) {
101 ++mStats[Stats::kHitMigrated];
103 ++mStats[Stats::kHitNotMigrated];
106 if constexpr (
false) {
109 bool crossesBoundary{
false};
110 TGeoNode *nEnt{
nullptr}, *nExt{
nullptr};
112 auto dirEnt = mCurWorkingHits[WorkingHit::kEntering].mPointDef - midPointDef;
113 auto stepEnt = std::min(
static_cast<double>(dirEnt.R()), std::abs(dirEnt.R() - 5.e-4));
114 auto dirEntU = dirEnt.Unit();
115 gGeoManager->SetCurrentPoint(midPointDef.X(), midPointDef.Y(), midPointDef.Z());
116 gGeoManager->SetCurrentDirection(dirEntU.X(), dirEntU.Y(), dirEntU.Z());
117 nEnt = gGeoManager->FindNextBoundaryAndStep(stepEnt,
false);
118 if (gGeoManager->IsOnBoundary()) {
119 ++mStats[Stats::kHitEntBoundary];
120 crossesBoundary =
true;
124 auto dirExt = midPointDef - mCurWorkingHits[WorkingHit::kEntering].mPointDef;
125 auto stepExt = std::min(
static_cast<double>(dirExt.R()), std::abs(dirExt.R() - 5.e-4));
126 auto dirExtU = dirExt.Unit();
127 gGeoManager->SetCurrentPoint(midPointDef.X(), midPointDef.Y(), midPointDef.Z());
128 gGeoManager->SetCurrentDirection(dirExtU.X(), dirExtU.Y(), dirExtU.Z());
129 nExt = gGeoManager->FindNextBoundaryAndStep(stepExt,
false);
130 if (gGeoManager->IsOnBoundary()) {
131 ++mStats[Stats::kHitExtBoundary];
132 crossesBoundary =
true;
136 if (crossesBoundary && nEnt !=
nullptr && nExt !=
nullptr) {
140 ++mStats[Stats::kHitSameBoundary];
143 ++mStats[Stats::kHitNoBoundary];
147 mCurHit.
SetPosStart(mCurWorkingHits[WorkingHit::kEntering].mPointDef);
148 mCurHit.
SetPos(mCurWorkingHits[WorkingHit::kExiting].mPointDef);
151 ++mStats[Stats::kHitSuccess];
155bool MisAlignmentHits::deformHit(WorkingHit::HitType t)
157 auto& wHit = mCurWorkingHits[t];
160 constexpr double minStep{1e-5};
161 constexpr double zMargin{4.0};
162 constexpr double phiMargin{0.4};
164 prepareLineMethod(t);
165 mMinimizer->SetVariable(0,
"t", 0.0, minStep);
167 if (!preparePropagatorMethod(t)) {
170 mMinimizer->SetVariable(0,
"r", mPropagator.mTrack.getX(), minStep);
172 mMinimizer->SetLimitedVariable(1,
"phiStar", wHit.mPhi, minStep,
173 std::max(
static_cast<double>(wHit.mPhiBorder1),
static_cast<double>(wHit.mPhi) - phiMargin),
174 std::min(
static_cast<double>(wHit.mPhiBorder2),
static_cast<double>(wHit.mPhi) + phiMargin));
175 mMinimizer->SetLimitedVariable(2,
"zStar", wHit.mPoint.Z(), minStep,
176 std::max(
static_cast<double>(-constants::segment::lengthSensitive / 2.f),
static_cast<double>(wHit.mPoint.Z()) - zMargin),
177 std::min(
static_cast<double>(constants::segment::lengthSensitive / 2.f),
static_cast<double>(wHit.mPoint.Z()) + zMargin));
179 mMinimizer->Minimize();
181 auto ss = mMinimizer->Status();
183 ++mStats[Stats::kMinimizerCovPos];
184 }
else if (ss == 2) {
185 ++mStats[Stats::kMinimizerHesse];
186 }
else if (ss == 3) {
187 ++mStats[Stats::kMinimizerEDM];
188 }
else if (ss == 4) {
189 ++mStats[Stats::kMinimizerLimit];
190 }
else if (ss == 5) {
191 ++mStats[Stats::kMinimizerOther];
193 ++mStats[Stats::kMinimizerConverged];
196 if (ss == 0 || ss == 1) {
197 ++mStats[Stats::kMinimizerStatusOk];
198 if (mMinimizer->MinValue() < 2e-4) {
199 ++mStats[Stats::kMinimizerValueOk];
201 ++mStats[Stats::kMinimizerValueBad];
205 ++mStats[Stats::kMinimizerStatusBad];
210 wHit.recalculateIdeal(
static_cast<float>(mMinimizer->X()[1]),
static_cast<float>(mMinimizer->X()[2]));
218 gGeoManager->PushPath();
219 auto id = getDetIDFromCords(point);
220 gGeoManager->PopPath();
227 const auto node = gGeoManager->FindNode(point.X(), point.Y(), point.Z());
228 if (node ==
nullptr) {
229 ++mStats[Stats::kFindNodeFailed];
232 ++mStats[Stats::kFindNodeSuccess];
235 const std::string
path = gGeoManager->GetPath();
237 ++mStats[Stats::kProjNonSensitive];
240 ++mStats[Stats::kProjSensitive];
242 return getDetIDFromPath(
path);
245short MisAlignmentHits::getDetIDFromPath(
const std::string&
path)
const
247 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+))"};
248 if (std::smatch matches; std::regex_search(
path, matches,
pattern)) {
249 if (matches.size() == 15) {
250 int iLayer = std::stoi(matches[1]);
251 int iCarbonForm = std::stoi(matches[4]);
252 int iSegment = std::stoi(matches[8]);
253 int iRSU = std::stoi(matches[10]);
254 int iTile = std::stoi(matches[12]);
255 return mGeo->
getChipIndex(iLayer, iCarbonForm, 0, iSegment, iRSU, iTile);
257 LOGP(fatal,
"Path did not contain expected number of matches ({})!", matches.size());
260 LOGP(fatal,
"Path was not matched ({})!",
path);
262 __builtin_unreachable();
267 auto makeFraction = [&](Stats
n, Stats d) ->
float {
return static_cast<float>(mStats[
n]) /
static_cast<float>(mStats[d] + mStats[
n]); };
268 LOGP(info,
"Processed {} Hits (IB:{}; OB:{}) ({:.2f}%):", mStats[Stats::kHitTotal], mStats[Stats::kHitIsIB], mStats[Stats::kHitIsOB], makeFraction(Stats::kHitIsIB, Stats::kHitIsOB));
269 LOGP(info,
" - Minimizer Status: {} ok {} bad ({:.2f}%)", mStats[Stats::kMinimizerStatusOk], mStats[Stats::kMinimizerStatusBad], makeFraction(Stats::kMinimizerStatusOk, Stats::kMinimizerStatusBad));
270 LOGP(info,
" - Minimizer Value: {} ok {} bad ({:.2f}%)", mStats[Stats::kMinimizerValueOk], mStats[Stats::kMinimizerValueBad], makeFraction(Stats::kMinimizerValueOk, Stats::kMinimizerValueBad));
271 LOGP(info,
" - Minimizer Detailed: {} Converged {} pos. forced Hesse ({:.2f}%)", mStats[Stats::kMinimizerConverged], mStats[Stats::kMinimizerHesse], makeFraction(Stats::kMinimizerConverged, Stats::kMinimizerHesse));
272 LOGP(info,
" - Minimizer Detailed: {} EDM {} call limit {} other ({:.2f}%)", mStats[Stats::kMinimizerEDM], mStats[Stats::kMinimizerLimit], mStats[Stats::kMinimizerOther], makeFraction(Stats::kMinimizerEDM, Stats::kMinimizerLimit));
273 LOGP(info,
" - FindNode: {} ok {} failed", mStats[Stats::kFindNodeSuccess], mStats[Stats::kFindNodeFailed]);
274 LOGP(info,
" - IsSensitve: {} yes {} no ({:.2f}%)", mStats[Stats::kProjSensitive], mStats[Stats::kProjNonSensitive], makeFraction(Stats::kProjSensitive, Stats::kProjNonSensitive));
275 LOGP(info,
" - IsAlive: {} yes {} no ({:.2f}%)", mStats[Stats::kHitAlive], mStats[Stats::kHitDead], makeFraction(Stats::kHitAlive, Stats::kHitDead));
276 LOGP(info,
" - HasMigrated: {} yes {} no ({:.2f}%)", mStats[Stats::kHitMigrated], mStats[Stats::kHitNotMigrated], makeFraction(Stats::kHitMigrated, Stats::kHitNotMigrated));
279 LOGP(info,
" - Propagator: {} null track {} null pdg", mStats[Stats::kPropTrackNull], mStats[Stats::kPropPDGNull]);
281 LOGP(info,
" --> Good Hits {} ({:.2f}%)", mStats[Stats::kHitSuccess], makeFraction(Stats::kHitSuccess, Stats::kHitIsIB));
284void MisAlignmentHits::prepareLineMethod(WorkingHit::HitType from)
288 mLine.mStart = mCurWorkingHits[WorkingHit::kEntering].mPoint;
289 mLine.mRadius = mCurWorkingHits[from].mRadius;
290 mLine.mSensorID = mCurWorkingHits[from].mSensorID;
291 mLine.mPhiTot = mCurWorkingHits[from].mPhiBorder2 - mCurWorkingHits[from].mPhiBorder1;
292 mLine.mPhi1 = mCurWorkingHits[from].mPhiBorder1;
294 mLine.mD[0] = mCurWorkingHits[WorkingHit::kExiting].mPoint.X() - mCurWorkingHits[WorkingHit::kEntering].mPoint.X();
295 mLine.mD[1] = mCurWorkingHits[WorkingHit::kExiting].mPoint.Y() - mCurWorkingHits[WorkingHit::kEntering].mPoint.Y();
296 mLine.mD[2] = mCurWorkingHits[WorkingHit::kExiting].mPoint.Z() - mCurWorkingHits[WorkingHit::kEntering].mPoint.Z();
299double MisAlignmentHits::StraightLine::DoEval(
const double*
x)
const
301 const double t =
x[0];
302 const double phi =
x[1];
303 const double z =
x[2];
304 const double nphi = std::clamp((phi - mPhi1) * 2.0 / mPhiTot - 1.0, -1.0, 1.0);
305 const double nz = std::clamp((
z - (-constants::segment::lengthSensitive / 2.0)) * 2.0 / constants::segment::lengthSensitive - 1.0, -1.0, 1.0);
308 double xline = mStart.X() + t * mD[0],
309 yline = mStart.Y() + t * mD[1],
310 zline = mStart.Z() + t * mD[2];
313 double xideal = mRadius * std::cos(phi), yideal = mRadius * std::sin(phi),
315 const auto [dx, dy, dz] = mMis->getDeformation(mSensorID, nphi, nz);
316 double xdef = xideal + dx, ydef = yideal + dy, zdef = zideal + dz;
319 return std::hypot(xline - xdef, yline - ydef, zline - zdef);
322bool MisAlignmentHits::preparePropagatorMethod(WorkingHit::HitType from)
324 mPropagator.mRadius = mCurWorkingHits[from].mRadius;
325 mPropagator.mSensorID = mCurWorkingHits[from].mSensorID;
326 mPropagator.mPhiTot = mCurWorkingHits[from].mPhiBorder2 - mCurWorkingHits[from].mPhiBorder1;
327 mPropagator.mPhi1 = mCurWorkingHits[from].mPhiBorder1;
328 const auto mcTrack = mMCReader->getTrack(mCurWorkingHits[from].mEvent, mCurWorkingHits[from].mTrackID);
329 if (mcTrack ==
nullptr) {
330 ++mStats[Stats::kPropTrackNull];
333 const std::array<float, 3> xyz{(float)mcTrack->GetStartVertexCoordinatesX(), (float)mcTrack->GetStartVertexCoordinatesY(), (float)mcTrack->GetStartVertexCoordinatesZ()},
334 pxyz{(
float)mcTrack->GetStartVertexMomentumX(), (
float)mcTrack->GetStartVertexMomentumY(), (
float)mcTrack->GetStartVertexMomentumZ()};
335 const TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrack->GetPdgCode());
336 if (pPDG ==
nullptr) {
337 ++mStats[Stats::kPropPDGNull];
340 mPropagator.mTrack =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
false);
345double MisAlignmentHits::Propagator::DoEval(
const double*
x)
const
347 const double r =
x[0];
348 const double phi =
x[1];
349 const double z =
x[2];
350 const double nphi = (
phi - mPhi1) * 2.0 / mPhiTot - 1.0;
351 const double nz = (
z - (-constants::segment::lengthSensitive / 2.0)) * 2.0 / constants::segment::lengthSensitive - 1.0;
354 if (!trc.propagateTo(
r, mBz)) {
357 const auto glo = trc.getXYZGlo();
360 double xideal = mRadius * std::cos(phi), yideal = mRadius * std::sin(phi),
362 const auto [dx, dy, dz] = mMis->getDeformation(mSensorID, nphi, nz);
363 double xdef = xideal + dx, ydef = yideal + dy, zdef = zideal + dz;
366 return std::hypot(glo.X() - xdef, glo.Y() - ydef, glo.Z() - zdef);
Definition of the SegmentationSuperAlpide class.
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