Project
Loading...
Searching...
No Matches
AlignableDetectorITS.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
20#include "Align/Controller.h"
21#include "Align/AlignConfig.h"
27#include "ITStracking/IOUtils.h"
28#include <TMath.h>
29#include <cstdio>
30
31using namespace TMath;
32using namespace o2::align::utils;
33
34namespace o2
35{
36namespace align
37{
38
39//____________________________________________
46
47/*
48//____________________________________________
49void AlignableDetectorITS::initGeom()
50{
51 if (getInitGeomDone()) {
52 return;
53 }
54 defineVolumes();
55 AlignableDetector::initGeom();
56}
57*/
58//____________________________________________
60{
61 // define ITS volumes
62 //
64
65 AlignableVolume *volITS = nullptr, *volLr = nullptr, *volHB = nullptr, *volSt = nullptr, *volHSt = nullptr, *volMod = nullptr;
66 AlignableSensorITS* sens = nullptr;
67 //
68 std::unordered_map<std::string, AlignableVolume*> sym2vol;
69 addVolume(volITS = new AlignableVolume(geom->composeSymNameITS(), getDetLabel(), mController));
70 sym2vol[volITS->getSymName()] = volITS;
71 //
72 int nonSensCnt = 0;
73 for (int ilr = 0; ilr < geom->getNumberOfLayers(); ilr++) {
74 for (int ihb = 0; ihb < geom->getNumberOfHalfBarrels(); ihb++) {
75 addVolume(volLr = new AlignableVolume(geom->composeSymNameHalfBarrel(ilr, ihb), getNonSensLabel(nonSensCnt++), mController));
76 sym2vol[volLr->getSymName()] = volLr;
77 volLr->setParent(volITS);
78 int nstavesHB = geom->getNumberOfStaves(ilr) / 2;
79 for (int ist = 0; ist < nstavesHB; ist++) {
80 addVolume(volSt = new AlignableVolume(geom->composeSymNameStave(ilr, ihb, ist), getNonSensLabel(nonSensCnt++), mController));
81 sym2vol[volSt->getSymName()] = volSt;
82 volSt->setParent(volLr);
83 for (int ihst = 0; ihst < geom->getNumberOfHalfStaves(ilr); ihst++) {
84 addVolume(volHSt = new AlignableVolume(geom->composeSymNameHalfStave(ilr, ihb, ist, ihst), getNonSensLabel(nonSensCnt++), mController));
85 sym2vol[volHSt->getSymName()] = volHSt;
86 volHSt->setParent(volSt);
87 for (int imd = 0; imd < geom->getNumberOfModules(ilr); imd++) {
88 addVolume(volMod = new AlignableVolume(geom->composeSymNameModule(ilr, ihb, ist, ihst, imd), getNonSensLabel(nonSensCnt++), mController));
89 sym2vol[volMod->getSymName()] = volMod;
90 volMod->setParent(volHSt);
91 } // module
92 } //halfstave
93 } // stave
94 } // layer halfBarrel
95 } // layer
96
97 for (int ich = 0; ich < geom->getNumberOfChips(); ich++) {
99 if (ich != chID) {
100 throw std::runtime_error(fmt::format("mismatch between counter {} and composed {} chip IDs", ich, chID));
101 }
103 int lay = 0, hba, sta = 0, ssta = 0, modd = 0, chip = 0;
104 geom->getChipId(chID, lay, hba, sta, ssta, modd, chip);
105 AlignableVolume* parVol = sym2vol[modd < 0 ? geom->composeSymNameStave(lay, hba, sta) : geom->composeSymNameModule(lay, hba, sta, ssta, modd)];
106 if (!parVol) {
107 throw std::runtime_error(fmt::format("did not find parent for chip {}", chID));
108 }
109 sens->setParent(parVol);
110 }
111 //
112}
113
114//____________________________________________
115int AlignableDetectorITS::processPoints(GIndex gid, int npntCut, bool inv)
116{
117 // Extract the points corresponding to this detector, recalibrate/realign them to the
118 // level of the "starting point" for the alignment/calibration session.
119 // If inv==true, the track propagates in direction of decreasing tracking X
120 // (i.e. upper leg of cosmic track)
121 //
122 auto algTrack = mController->getAlgTrack();
123 auto recoData = mController->getRecoContainer();
124 const auto& algConf = AlignConfig::Instance();
125 int npoints = 0;
126 auto procClus = [this, inv, &npoints, &algTrack](const ClusterD& clus) {
127 auto* sensor = this->getSensor(clus.getSensorID());
128 auto& pnt = algTrack->addDetectorPoint();
129 const auto* sysE = sensor->getAddError(); // additional syst error
130 pnt.setYZErrTracking(clus.getSigmaY2() + sysE[0] * sysE[0], clus.getSigmaYZ(), clus.getSigmaZ2() + sysE[1] * sysE[1]);
131 if (this->getUseErrorParam()) { // errors will be calculated just before using the point in the fit, using track info
132 pnt.setNeedUpdateFromTrack();
133 }
134 pnt.setXYZTracking(clus.getX(), clus.getY(), clus.getZ());
135 pnt.setSensor(sensor);
136 pnt.setAlphaSens(sensor->getAlpTracking());
137 pnt.setXSens(sensor->getXTracking());
138 pnt.setDetID(this->mDetID);
139 pnt.setSID(sensor->getSID());
140 pnt.setContainsMeasurement();
141 pnt.setInvDir(inv);
142 pnt.init();
143 npoints++;
144 };
145 std::array<int, 7> clusIDs{};
146 int nOverlaps = 0;
147 if (gid.getSource() == GIndex::ITS) {
148 const auto tracks = recoData->getITSTracks();
149 if (tracks.empty()) {
150 return -1; // source not loaded?
151 }
152 const auto& track = tracks[gid.getIndex()];
153 if (track.getNClusters() < npntCut) {
154 return -1;
155 }
156 const auto& clusIdx = recoData->getITSTracksClusterRefs();
157 // do we want to apply some cuts?
158 int clEntry = track.getFirstClusterEntry();
159 int preevSensID = -1;
160 bool errReported = false;
161 for (int icl = track.getNumberOfClusters(); icl--;) { // clusters refs are stored from outer to inner layers, we loop in inner -> outer direction
162 const auto& clus = mITSClustersArray[(clusIDs[npoints] = clusIdx[clEntry + icl])];
163 if (clus.getSensorID() < preevSensID && !errReported) { // clusters are ordered from outer to inner layer, hence decreasing sensorID
164 std::string errstr{};
165 for (int ie = track.getNumberOfClusters(); ie--;) {
166 errstr += fmt::format(" {}", mITSClustersArray[clusIdx[clEntry + ie]].getSensorID());
167 }
168 LOGP(error, "wrong ITS clusters order? : chips {}", errstr);
169 errReported = true;
170 }
171 preevSensID = clus.getSensorID();
172 if (clus.getBits()) { // overlapping clusters will have bit set
173 if (clus.isBitSet(EdgeFlags::Biased)) {
174 continue;
175 }
176 if (clus.getCount()) {
177 nOverlaps++;
178 }
179 }
180 procClus(clus);
181 }
182 } else { // ITSAB
183 const auto& trkITSABref = recoData->getITSABRefs()[gid.getIndex()];
184 const auto& ABTrackClusIdx = recoData->getITSABClusterRefs();
185 int nCl = trkITSABref.getNClusters();
186 int clEntry = trkITSABref.getFirstEntry();
187 for (int icl = 0; icl < nCl; icl++) { // clusters are stored from inner to outer layers
188 const auto& clus = mITSClustersArray[(clusIDs[npoints] = ABTrackClusIdx[clEntry + icl])];
189 if (clus.getBits()) { // overlapping clusters will have bit set
190 if (clus.isBitSet(EdgeFlags::Biased)) {
191 continue;
192 }
193 if (clus.getCount()) {
194 nOverlaps++;
195 }
196 }
197 procClus(clus);
198 }
199 }
200 if (npoints < npntCut) { // reset points to original start
201 algTrack->suppressLastPoints(npoints);
202 npoints = 0;
203 return 0;
204 }
205
206 // do we need to process overlaps?
207 if (nOverlaps) {
209 trcProp.resetCovariance(10);
210 auto propagator = o2::base::Propagator::Instance();
211 for (int icl = 0; icl < npoints; icl++) {
212 const auto& clus = mITSClustersArray[clusIDs[icl]];
213 float alp = getSensor(clus.getSensorID())->getAlpTracking();
214 if (!trcProp.rotate(alp) ||
215 !propagator->propagateToX(trcProp, clus.getX(), propagator->getNominalBz(), algConf.maxSnp, algConf.maxStep, base::Propagator::MatCorrType(algConf.matCorType)) ||
216 !trcProp.update(clus)) {
217 break;
218 }
219
220 if (clus.getCount()) { // there is an overlap, find best matching cluster
221 nOverlaps--;
222 int bestClusID = -1, clusIDtoCheck = mOverlapClusRef[clusIDs[icl]];
223 float bestChi2 = algConf.ITSOverlapMaxChi2;
224 auto trPropOvl = trcProp;
225 for (int iov = 0; iov < clus.getCount(); iov++) {
226 int clusOvlID = mOverlapCandidateID[clusIDtoCheck];
227 const auto& clusOvl = mITSClustersArray[clusOvlID];
228 if (iov == 0) {
229 if (!trPropOvl.rotate(getSensor(clusOvl.getSensorID())->getAlpTracking()) ||
230 !propagator->propagateToX(trPropOvl, clusOvl.getX(), propagator->getNominalBz(), algConf.maxSnp, algConf.maxStep, base::Propagator::MatCorrType::USEMatCorrNONE)) {
231 break;
232 }
233 }
234 auto chi2 = trPropOvl.getPredictedChi2(clusOvl);
235 if (chi2 < bestChi2) {
236 bestChi2 = chi2;
237 bestClusID = clusOvlID;
238 }
239 }
240 if (bestClusID != -1) { // account overlapping cluster
241 procClus(mITSClustersArray[bestClusID]);
242 }
243 }
244 if (!nOverlaps) {
245 break;
246 }
247 }
248 }
249 mNPoints += npoints;
250 return npoints;
251}
252
253//____________________________________________
255{
256 // prepare TF data for processing: convert clusters
257 const auto& algConf = AlignConfig::Instance();
258 auto recoData = mController->getRecoContainer();
259 const auto clusITS = recoData->getITSClusters();
260 const auto clusITSROF = recoData->getITSClustersROFRecords();
261 const auto patterns = recoData->getITSClustersPatterns();
262 auto pattIt = patterns.begin();
263 mITSClustersArray.clear();
264 mITSClustersArray.reserve(clusITS.size());
265 if (algConf.ITSOverlapMargin > 0) {
266 mOverlapClusRef.clear();
267 mOverlapClusRef.resize(clusITS.size(), -1);
268
269 mOverlapCandidateID.clear();
270 mOverlapCandidateID.reserve(clusITS.size());
271 }
272 static std::vector<int> edgeClusters;
273 int ROFCount = 0;
274 int16_t curSensID = -1;
275 struct ROFChipEntry {
276 int16_t rofCount = -1;
277 int chipFirstEntry = -1;
278 };
279 std::array<ROFChipEntry, o2::itsmft::ChipMappingITS::getNChips()> chipROFStart{}; // fill only for clusters with overlaps
280
281 for (const auto& rof : clusITSROF) {
282 int maxic = rof.getFirstEntry() + rof.getNEntries();
283 edgeClusters.clear();
284 for (int ic = rof.getFirstEntry(); ic < maxic; ic++) {
285 const auto& c = clusITS[ic];
286 int16_t sensID = c.getSensorID();
287 auto* sensor = getSensor(sensID);
288 double sigmaY2, sigmaZ2, sigmaYZ = 0, locXYZC[3], traXYZ[3];
289 auto pattItCopy = pattIt;
290 auto locXYZ = o2::its::ioutils::extractClusterDataA(c, pattIt, mITSDict, sigmaY2, sigmaZ2); // local ideal coordinates
291 const auto& matAlg = sensor->getMatrixClAlg(); // local alignment matrix !!! RS FIXME
292 matAlg.LocalToMaster(locXYZ.data(), locXYZC); // aligned point in the local frame
293 const auto& mat = sensor->getMatrixT2L(); // RS FIXME check if correct
294 mat.MasterToLocal(locXYZC, traXYZ);
295 auto& cl3d = mITSClustersArray.emplace_back(sensID, traXYZ[0], traXYZ[1], traXYZ[2], sigmaY2, sigmaZ2, sigmaYZ); // local --> tracking
296
297 if (algConf.ITSOverlapMargin > 0) {
298 // fill chips overlaps info for clusters whose center is within of the algConf.ITSOverlapMargin distance from the chip min or max row edge
299 // but the pixel closest to this edge has distance of at least algConf.ITSOverlapEdgeRows from the edge
300 int row = 0, col = 0;
302 int drow = row < o2::itsmft::SegmentationAlpide::NRows / 2 ? row : o2::itsmft::SegmentationAlpide::NRows - row - 1; // distance to the edge
303 if (drow * o2::itsmft::SegmentationAlpide::PitchRow < algConf.ITSOverlapMargin) { // rough check is passed, check if the edge cluster is indeed good
304 cl3d.setBit(row < o2::itsmft::SegmentationAlpide::NRows / 2 ? EdgeFlags::LowRow : EdgeFlags::HighRow); // flag that this is an edge cluster and indicate the low/high row side
305 // check if it is not too close to the edge (to be biased)
306 if (algConf.ITSOverlapEdgeRows > 0) { // is there a restriction?
307 auto pattID = c.getPatternID();
308 drow = c.getRow();
310 if (!mITSDict->isGroup(pattID)) {
311 const auto& patt = mITSDict->getPattern(pattID); // reference pixel is min row/col corner
313 drow = o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() - 1);
314 }
315 } else { // group: reference pixel is the one containing the COG
316 o2::itsmft::ClusterPattern patt(pattItCopy);
317 drow = row < o2::itsmft::SegmentationAlpide::NRows / 2 ? drow - patt.getRowSpan() / 2 : o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() / 2 - 1);
318 }
319 } else {
320 o2::itsmft::ClusterPattern patt(pattItCopy); // reference pixel is min row/col corner
322 drow = o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() - 1);
323 }
324 }
325 if (drow < algConf.ITSOverlapEdgeRows) { // too close to the edge, flag this
326 cl3d.setBit(EdgeFlags::Biased);
327 }
328 }
329 if (!cl3d.isBitSet(EdgeFlags::Biased)) {
330 if (chipROFStart[sensID].rofCount != ROFCount) { // remember 1st entry
331 chipROFStart[sensID].rofCount = ROFCount;
332 chipROFStart[sensID].chipFirstEntry = edgeClusters.size(); // remember 1st entry of edge cluster for this chip
333 }
334 edgeClusters.push_back(ic);
335 }
336 }
337 }
338 } // clusters of ROF
339 // relate edge clusters of ROF to each other
340 int prevSensID = -1;
341 for (auto ic : edgeClusters) {
342 auto& cl = mITSClustersArray[ic];
343 int sensID = cl.getSensorID();
344 auto ovl = mOverlaps[sensID];
345 int ovlCount = 0;
346 for (int ir = 0; ir < OVL::NSides; ir++) {
347 if (ovl.rowSide[ir] == OVL::NONE) { // no overlap from this row side
348 continue;
349 }
350 int chipOvl = ovl.rowSide[ir]; // look for overlaps with this chip
351 // are there clusters with overlaps on chipOvl?
352 if (chipROFStart[chipOvl].rofCount == ROFCount) {
353 auto oClusID = edgeClusters[chipROFStart[chipOvl].chipFirstEntry];
354 while (oClusID < int(mITSClustersArray.size())) {
355 auto oClus = mITSClustersArray[oClusID];
356 if (oClus.getSensorID() != sensID) {
357 break; // no more clusters on the overlapping chip
358 }
359 if (oClus.isBitSet(ovl.rowSideOverlap[ir]) && // make sure that the edge cluster is on the right side of the row
360 !oClus.isBitSet(EdgeFlags::Biased) && // not too close to the edge
361 std::abs(oClus.getZ() - cl.getZ()) < algConf.ITSOverlapMaxDZ) { // apply fiducial cut on Z distance of 2 clusters
362 // register overlaping cluster
363 if (!ovlCount) { // 1st overlap
365 }
366 mOverlapCandidateID.push_back(oClusID);
367 ovlCount++;
368 }
369 oClusID++;
370 }
371 }
372 }
373 cl.setCount(std::min(127, ovlCount));
374 }
375
376 ROFCount++;
377 } // loop over ROFs
378 return true;
379}
380
381//____________________________________________
382void AlignableDetectorITS::Print(const Option_t* opt) const
383{
385}
386
387//____________________________________________
388void AlignableDetectorITS::SetAddErrorLr(int ilr, double sigY, double sigZ)
389{
390 // set syst. errors for specific layer
392 int chMin = geom->getFirstChipIndex(ilr), chMax = geom->getLastChipIndex(ilr);
393 for (int isn = chMin; isn <= chMax; isn++) {
394 getSensor(isn)->setAddError(sigY, sigZ);
395 }
396}
397
398//____________________________________________
400{
401 // exclude sensor of the layer from alignment
403 int chMin = geom->getFirstChipIndex(ilr), chMax = geom->getLastChipIndex(ilr);
404 for (int isn = chMin; isn <= chMax; isn++) {
405 getSensor(isn)->setSkip();
406 }
407}
408
409//_________________________________________________
411{
412 // set type of points error parameterization // RS DO WE NEED THIS?
414}
415
416//_________________________________________________
418{
419 // update point using specific error parameterization
420 // the track must be in the detector tracking frame
421 //TODO RS
422 /*
423 const AlignableSensor* sens = pnt->getSensor();
424 int vid = sens->getVolID();
425 double angPol = ATan(t.getTgl());
426 double angAz = ASin(t.getSnp());
427 double errY, errZ;
428 GetErrorParamAngle(lr, angPol, angAz, errY, errZ);
429 const double* sysE = sens->getAddError(); // additional syst error
430 //
431 pnt->setYZErrTracking(errY * errY + sysE[0] * sysE[0], 0, errZ * errZ + sysE[1] * sysE[1]);
432 pnt->init();
433 */
434 //
435}
436
437} // namespace align
438} // namespace o2
Configuration file for global alignment.
ITS detector wrapper.
Base class of alignable volume.
Steering class for the global alignment.
Wrapper container for different reconstructed object types.
Definition of the ClusterTopology class.
Definition of the GeometryTGeo class.
uint32_t col
Definition RawData.h:4
uint32_t c
Definition RawData.h:2
Definition of the ITS track.
Reference on ITS/MFT clusters set.
std::vector< ClusterD > mITSClustersArray
void updatePointByTrackInfo(AlignmentPoint *pnt, const trackParam_t *t) const override
int processPoints(GIndex gid, int npntCut, bool inv) final
std::vector< o2::itsmft::ChipMappingITS::Overlaps > mOverlaps
void Print(const Option_t *opt="") const override
void SetAddErrorLr(int ilr, double sigY, double sigZ)
const o2::itsmft::TopologyDictionary * mITSDict
AlignableSensor * getSensor(int id) const
virtual void addVolume(AlignableVolume *vol)
void Print(const Option_t *opt="") const override
void setAddError(double y, double z)
void setParent(AlignableVolume *par)
const char * getSymName() const
GTrackID getCurrentTrackID() const
const o2::globaltracking::RecoContainer * getRecoContainer() const
Definition Controller.h:200
AlignmentTrack * getAlgTrack() const
Definition Controller.h:198
Controller * mController
Definition DOFSet.h:73
static const char * getSymbolicName(o2::detectors::DetID detid, int sensid)
static int getSensID(o2::detectors::DetID detid, int sensid)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static GeometryTGeo * Instance()
static constexpr int getNChips()
number of chips per barrel
std::vector< Overlaps > getOverlapsInfo() const
int getRowSpan() const
Returns the number of rows.
static constexpr unsigned short InvalidPatternID
Definition CompCluster.h:46
static constexpr float PitchRow
static void localToDetectorUnchecked(float xRow, float zCol, int &iRow, int &iCol)
same but w/o check for row/column range
const ClusterPattern & getPattern(int n) const
Returns the pattern of the topology.
bool isGroup(int n) const
Returns true if the element corresponds to a group of rare topologies.
const GLdouble * v
Definition glcorearb.h:832
typename track::TrackParametrizationWithError< double > trackParam_t
Definition utils.h:29
std::array< T, 3 > extractClusterDataA(const itsmft::CompClusterExt &c, iterator &iter, const itsmft::TopologyDictionary *dict, T &sig2y, T &sig2z)
Definition IOUtils.h:102
void align(gsl::span< ElinkEncoder< BareFormat, CHARGESUM > > elinks)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
o2::InteractionRecord ir(0, 0)
std::vector< int > row