Skip to content

Commit 9e9f5bf

Browse files
committed
Unbinned residuals with ITS refit and PV point added
With scdcalib.refitITS=true (default) the ITS track outer param will be refitted from scratch using stable Kalman filter staring from the inner param (and using it as as linearization point) and imposing PID of the global track (if any). Note that the reconstruction is done with extra syst.errors on the ITS clusters (20 microns): they can be added also for this refit with usual ITSCATrackerParam.sysErrY2... settings (though this is not necessary). The track residuals wrt the PV are added to the unbinned residuals with identified of padrow 190. Note that PV residuals interpretation differs from the rest: they are provided at the PCA of the track to PV, with PV rotated to the frame of the track. The X of the vertex in this frame is stored in the channel slot mapped from [-0.5:0.5] to short; the alpha of the track frame is stored as the angle in [-pi : pi] mapped to short: auto dy = yv - trkAtPCA.getY(), auto dz = zv - trkAtPCA.getZ(); short compXV = static_cast<short>(xv * 0x7fff / param::MaxVtxX); // MaxVtxX = 0.5 cm mClRes.emplace_back(dy, dz, trkAtPCA.getAlpha() / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
1 parent e82e459 commit 9e9f5bf

File tree

5 files changed

+111
-3
lines changed

5 files changed

+111
-3
lines changed

Detectors/TPC/calibration/SpacePoints/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# In applying this license CERN does not waive the privileges and immunities
99
# granted to it by virtue of its status as an Intergovernmental Organization
1010
# or submit itself to any jurisdiction.
11+
# add_compile_options(-O0 -g -fPIC)
1112

1213
o2_add_library(SpacePoints
1314
SOURCES src/SpacePointsCalibParam.cxx

Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct SpacePointsCalibConfParam : public o2::conf::ConfigurableParamHelper<Spac
4141
int minTOFTRDPVContributors = 2; ///< min contributors from TRD or TOF (fast detectors) to consider tracks of this PV
4242
bool ignoreNonPVContrib = true; ///< flag if tracks which did not contribute to the PV should be ignored or not
4343
bool enableTrackDownsampling = false; ///< flag if track sampling shall be enabled or not
44+
bool refitITS = true; ///< refit ITS tracks with PID attached to the seed
4445
float tsalisThreshold = 1.f; ///< in case the sampling functions returns a value smaller than this the track is discarded (1. means no downsampling)
4546

4647
// other settings for track interpolation

Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibParam.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ static constexpr float MaxY = 50.f; ///< max value for y position (sector c
5858
static constexpr float MaxZ = 300.f; ///< max value for z position
5959
static constexpr float MaxTgSlp = 1.f; ///< max value for phi (from snp, converted to tangens)
6060
static constexpr float MaxTRDSlope = 5.; ///< max value for the TRD tracklet getDy
61+
static constexpr float MaxVtxX = 0.5; ///< max X value of the PV rotated to the frame of track at its DCA to PV
6162
// miscellaneous
6263
static constexpr float sEps = 1e-6f; ///< small number for float comparisons
6364

Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ class TrackInterpolation
239239
/// Reset cache and output vectors
240240
void reset();
241241

242+
// refit ITS track taking PID (unless already refitted) from the seed and reassign to the seed
243+
bool refITSTrack(o2::dataformats::GlobalTrackID, int iSeed);
242244
// -------------------------------------- outlier rejection --------------------------------------------------
243245

244246
/// Validates the given input track and its residuals
@@ -328,6 +330,7 @@ class TrackInterpolation
328330
std::vector<o2::dataformats::GlobalTrackID> mGIDs{}; ///< GIDs of input tracks
329331
std::vector<o2::globaltracking::RecoContainer::GlobalIDSet> mGIDtables{}; ///< GIDs of contributors from single detectors for each seed
330332
std::vector<float> mTrackTimes{}; ///< time estimates for all input tracks in micro seconds
333+
std::vector<int> mTrackPVID{}; ///< track vertex index (if any)
331334
std::vector<o2::track::TrackParCov> mSeeds{}; ///< seeding track parameters (ITS tracks)
332335
std::vector<int> mParentID{}; ///< entry of more global parent track for skimmed seeds (-1: no parent)
333336
std::map<int, int> mTrackTypes; ///< mapping of track source to array index in mTrackIndices
@@ -337,6 +340,7 @@ class TrackInterpolation
337340
// ITS specific input only needed for debugging
338341
gsl::span<const int> mITSTrackClusIdx; ///< input ITS track cluster indices span
339342
std::vector<o2::BaseCluster<float>> mITSClustersArray; ///< ITS clusters created in run() method from compact clusters
343+
std::vector<int> mITSRefitSeedID; ///< seed ID first using refitted ITS track
340344
const o2::itsmft::TopologyDictionary* mITSDict = nullptr; ///< cluster patterns dictionary
341345

342346
// output

Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ void TrackInterpolation::prepareInputTrackSample(const o2::globaltracking::RecoC
221221
int nv = vtxRefs.size() - 1;
222222
GTrackID::mask_t allowedSources = GTrackID::getSourcesMask("ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF") & mSourcesConfigured;
223223
constexpr std::array<int, 3> SrcFast = {int(GTrackID::ITSTPCTRD), int(GTrackID::ITSTPCTOF), int(GTrackID::ITSTPCTRDTOF)};
224+
if (mParams->refitITS) {
225+
mITSRefitSeedID.resize(mRecoCont->getITSTracks().size(), -1);
226+
}
224227

225228
for (int iv = 0; iv < nv; iv++) {
226229
LOGP(debug, "processing PV {} of {}", iv, nv);
@@ -281,6 +284,7 @@ void TrackInterpolation::prepareInputTrackSample(const o2::globaltracking::RecoC
281284
mGIDtables.push_back(gidTable);
282285
mTrackTimes.push_back(pv.getTimeStamp().getTimeStamp());
283286
mTrackIndices[mTrackTypes[vid.getSource()]].push_back(nTrackSeeds++);
287+
mTrackPVID.push_back(iv);
284288
}
285289
}
286290
}
@@ -360,13 +364,13 @@ void TrackInterpolation::process()
360364
if (mParams->enableTrackDownsampling && !isTrackSelected(mSeeds[seedIndex])) {
361365
continue;
362366
}
363-
364367
auto addPart = [this, seedIndex](GTrackID::Source src) {
365368
this->mGIDs.push_back(this->mGIDtables[seedIndex][src]);
366369
this->mGIDtables.push_back(this->mRecoCont->getSingleDetectorRefs(this->mGIDs.back()));
367370
this->mTrackTimes.push_back(this->mTrackTimes[seedIndex]);
368371
this->mSeeds.push_back(this->mSeeds[seedIndex]);
369372
this->mParentID.push_back(seedIndex); // store parent seed id
373+
this->mTrackPVID.push_back(this->mTrackPVID[seedIndex]);
370374
};
371375

372376
GTrackID::mask_t partsAdded;
@@ -450,9 +454,12 @@ void TrackInterpolation::interpolateTrack(int iSeed)
450454
(*trackDataExtended).clsITS.push_back(clsITS);
451455
}
452456
}
457+
if (mParams->refitITS && !refITSTrack(gidTable[GTrackID::ITS], iSeed)) {
458+
return;
459+
}
453460
trackData.gid = mGIDs[iSeed];
454461
trackData.par = mSeeds[iSeed];
455-
auto& trkWork = mSeeds[iSeed];
462+
auto trkWork = mSeeds[iSeed];
456463
o2::track::TrackPar trkInner{trkWork};
457464
// reset the cache array (sufficient to set cluster available to zero)
458465
for (auto& elem : mCache) {
@@ -734,6 +741,27 @@ void TrackInterpolation::interpolateTrack(int iSeed)
734741
trackData.nExtDetResid++;
735742
}
736743
}
744+
if (!stopPropagation) { // add residual to PV
745+
const auto& pv = mRecoCont->getPrimaryVertices()[mTrackPVID[iSeed]];
746+
o2::math_utils::Point3D<float> vtx{pv.getX(), pv.getY(), pv.getZ()};
747+
if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->maxStep, mMatCorr)) {
748+
LOGP(debug, "Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
749+
stopPropagation = true;
750+
break;
751+
}
752+
// rotate PV to the track frame
753+
float sn, cs, alpha = trkWorkITS.getAlpha();
754+
math_utils::detail::bringToPMPi(alpha);
755+
math_utils::detail::sincos<float>(alpha, sn, cs);
756+
float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
757+
auto dy = yv - trkWorkITS.getY();
758+
auto dz = zv - trkWorkITS.getZ();
759+
if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWorkITS.getY()) < param::MaxY) && (std::abs(trkWorkITS.getZ()) < param::MaxZ) && abs(xv) < param::MaxVtxX) {
760+
short compXV = static_cast<short>(xv * 0x7fff / param::MaxVtxX);
761+
mClRes.emplace_back(dy, dz, alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
762+
trackData.nExtDetResid++;
763+
}
764+
}
737765
break;
738766
}
739767
}
@@ -826,6 +854,9 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
826854
(*trackDataExtended).clsITS.push_back(clsITS);
827855
}
828856
}
857+
if (mParams->refitITS && !refITSTrack(gidTable[GTrackID::ITS], iSeed)) {
858+
return;
859+
}
829860
trackData.gid = mGIDs[iSeed];
830861
trackData.par = mSeeds[iSeed];
831862

@@ -987,7 +1018,7 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
9871018
int chip = cls.getSensorID();
9881019
float chipX, chipAlpha;
9891020
geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
990-
if (!trkWorkITS.rotate(chipAlpha) || !propagator->PropagateToXBxByBz(trkWorkITS, chipX, mParams->maxSnp, mParams->maxStep, mMatCorr)) {
1021+
if (!trkWorkITS.rotate(chipAlpha) || !propagator->propagateToX(trkWorkITS, chipX, mBz, mParams->maxSnp, mParams->maxStep, mMatCorr)) {
9911022
LOGP(debug, "Failed final propagation to ITS X={} alpha={}", chipX, chipAlpha);
9921023
stopPropagation = true;
9931024
break;
@@ -1000,6 +1031,27 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
10001031
trackData.nExtDetResid++;
10011032
}
10021033
}
1034+
if (!stopPropagation) { // add residual to PV
1035+
const auto& pv = mRecoCont->getPrimaryVertices()[mTrackPVID[iSeed]];
1036+
o2::math_utils::Point3D<float> vtx{pv.getX(), pv.getY(), pv.getZ()};
1037+
if (!propagator->propagateToDCA(vtx, trkWorkITS, mBz, mParams->maxStep, mMatCorr)) {
1038+
LOGP(debug, "Failed propagation to DCA to PV ({} {} {}), {}", pv.getX(), pv.getY(), pv.getZ(), trkWorkITS.asString());
1039+
stopPropagation = true;
1040+
break;
1041+
}
1042+
// rotate PV to the track frame
1043+
float sn, cs, alpha = trkWorkITS.getAlpha();
1044+
math_utils::detail::bringToPMPi(alpha);
1045+
math_utils::detail::sincos<float>(alpha, sn, cs);
1046+
float xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
1047+
auto dy = yv - trkWorkITS.getY();
1048+
auto dz = zv - trkWorkITS.getZ();
1049+
if ((std::abs(dy) < param::MaxResid) && (std::abs(dz) < param::MaxResid) && (std::abs(trkWorkITS.getY()) < param::MaxY) && (std::abs(trkWorkITS.getZ()) < param::MaxZ) && abs(xv) < param::MaxVtxX) {
1050+
short compXV = static_cast<short>(xv * 0x7fff / param::MaxVtxX);
1051+
mClRes.emplace_back(dy, dz, alpha / TMath::Pi(), trkWorkITS.getY(), trkWorkITS.getZ(), 190, -1, compXV);
1052+
trackData.nExtDetResid++;
1053+
}
1054+
}
10031055
break;
10041056
}
10051057
}
@@ -1403,6 +1455,8 @@ void TrackInterpolation::reset()
14031455
mGIDtables.clear();
14041456
mTrackTimes.clear();
14051457
mSeeds.clear();
1458+
mITSRefitSeedID.clear();
1459+
mTrackPVID.clear();
14061460
}
14071461

14081462
//______________________________________________
@@ -1416,3 +1470,50 @@ void TrackInterpolation::setTPCVDrift(const o2::tpc::VDriftCorrFact& v)
14161470
o2::tpc::TPCFastTransformHelperO2::instance()->updateCalibration(*mFastTransform, 0, 1.0, mTPCVDriftRef, mTPCDriftTimeOffsetRef);
14171471
}
14181472
}
1473+
1474+
//______________________________________________
1475+
bool TrackInterpolation::refITSTrack(o2::dataformats::GlobalTrackID gid, int seedID)
1476+
{
1477+
// refit ITS track outwards taking PID (unless already refitted) from the seed and reassign to the seed
1478+
auto& seed = mSeeds[seedID];
1479+
int refitID = mITSRefitSeedID[gid.getIndex()];
1480+
if (refitID >= 0) { // track was already refitted
1481+
if (mSeeds[refitID].getPID() == seed.getPID()) {
1482+
seed = mSeeds[refitID];
1483+
}
1484+
return true;
1485+
}
1486+
const auto& trkITS = mRecoCont->getITSTrack(gid);
1487+
// fetch clusters
1488+
auto nCl = trkITS.getNumberOfClusters();
1489+
auto clEntry = trkITS.getFirstClusterEntry();
1490+
o2::track::TrackParCov track(trkITS); // start from the inner param
1491+
track.setPID(seed.getPID());
1492+
o2::track::TrackPar refLin(track); // and use it also as linearization reference
1493+
auto geom = o2::its::GeometryTGeo::Instance();
1494+
auto prop = o2::base::Propagator::Instance();
1495+
for (int iCl = nCl - 1; iCl >= 0; iCl--) { // clusters are stored from outer to inner layers
1496+
const auto& cls = mITSClustersArray[mITSTrackClusIdx[clEntry + iCl]];
1497+
int chip = cls.getSensorID();
1498+
float chipX, chipAlpha;
1499+
geom->getSensorXAlphaRefPlane(cls.getSensorID(), chipX, chipAlpha);
1500+
if (!track.rotate(chipAlpha, refLin, mBz)) {
1501+
LOGP(debug, "failed to rotate ITS tracks to alpha={} for the refit: {}", chipAlpha, track.asString());
1502+
return false;
1503+
}
1504+
if (!prop->propagateToX(track, refLin, cls.getX(), mBz, o2::base::PropagatorImpl<float>::MAX_SIN_PHI, o2::base::PropagatorImpl<float>::MAX_STEP, o2::base::PropagatorF::MatCorrType::USEMatCorrLUT)) {
1505+
LOGP(debug, "failed to propagate ITS tracks to X={}: {}", cls.getX(), track.asString());
1506+
return false;
1507+
}
1508+
std::array<float, 2> posTF{cls.getY(), cls.getZ()};
1509+
std::array<float, 3> covTF{cls.getSigmaY2(), cls.getSigmaYZ(), cls.getSigmaZ2()};
1510+
if (!track.update(posTF, covTF)) {
1511+
LOGP(debug, "failed to update ITS tracks by cluster ({},{})/({},{},{})", track.asString(), cls.getY(), cls.getZ(), cls.getSigmaY2(), cls.getSigmaYZ(), cls.getSigmaZ2());
1512+
return false;
1513+
}
1514+
}
1515+
seed = track;
1516+
// memorize that this ITS track was already refitted
1517+
mITSRefitSeedID[gid.getIndex()] = seedID;
1518+
return true;
1519+
}

0 commit comments

Comments
 (0)