Skip to content

Commit d82a9c3

Browse files
committed
Support per-layer ITS clusters in barrel-alignment-workflow
Cluster-overlap bookkeeping in AlignableDetectorITS moves to a per-layer ROF loop; this is the natural granularity anyway since row-side chip overlaps are always within a single layer. Note: this whole module will be superseded by the new MP-2 based package.
1 parent e50629e commit d82a9c3

5 files changed

Lines changed: 108 additions & 97 deletions

File tree

‎Detectors/Align/Workflow/include/AlignmentWorkflow/BarrelAlignmentSpec.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace align
2727

2828
/// create a processor spec
2929
framework::DataProcessorSpec getBarrelAlignmentSpec(o2::dataformats::GlobalTrackID::mask_t srcMP, o2::dataformats::GlobalTrackID::mask_t src,
30-
o2::detectors::DetID::mask_t dets, o2::detectors::DetID::mask_t skipDetClusters, bool enableCosmic, int postproc, bool useMC);
30+
o2::detectors::DetID::mask_t dets, o2::detectors::DetID::mask_t skipDetClusters, bool enableCosmic, int postproc, bool useMC, bool itsStag);
3131

3232
} // namespace align
3333
} // namespace o2

‎Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,11 @@ void BarrelAlignmentSpec::endOfStream(EndOfStreamContext& ec)
357357
mDBGOut.reset();
358358
}
359359

360-
DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_t src, DetID::mask_t dets, DetID::mask_t skipDetClusters, bool enableCosmic, int postprocess, bool useMC)
360+
DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_t src, DetID::mask_t dets, DetID::mask_t skipDetClusters, bool enableCosmic, int postprocess, bool useMC, bool itsStag)
361361
{
362362
std::vector<OutputSpec> outputs;
363363
auto dataRequest = std::make_shared<DataRequest>();
364+
dataRequest->setITSPerLayer(itsStag);
364365
bool loadTPCCalib = false;
365366
Options opts{
366367
ConfigParamSpec{"apply-xor", o2::framework::VariantType::Bool, false, {"flip the 8-th bit of slope and position (for processing TRD CTFs from 2021 pilot beam)"}},

‎Detectors/Align/Workflow/src/barrel-alignment-workflow.cxx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext)
9595
bool loadTPCTracks = configcontext.options().get<bool>("enable-tpc-tracks");
9696
bool enableCosmic = configcontext.options().get<bool>("enable-cosmic");
9797
bool useMC = configcontext.options().get<bool>("enable-mc");
98+
bool doStag = o2::itsmft::DPLAlpideParamInitializer::isITSStaggeringEnabled(configcontext);
9899

99100
DetID::mask_t dets = allowedDets & DetID::getMask(configcontext.options().get<std::string>("detectors"));
100101
DetID::mask_t skipDetClusters; // optionally skip automatically loaded clusters
@@ -154,7 +155,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext)
154155
specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpt));
155156
}
156157

157-
specs.emplace_back(o2::align::getBarrelAlignmentSpec(srcMP, src, dets, skipDetClusters, enableCosmic, postprocess, useMC));
158+
specs.emplace_back(o2::align::getBarrelAlignmentSpec(srcMP, src, dets, skipDetClusters, enableCosmic, postprocess, useMC, doStag));
158159
// RS FIXME: check which clusters are really needed
159160
if (!postprocess) {
160161
GID::mask_t dummy;

‎Detectors/Align/include/Align/AlignableDetectorITS.h‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "ReconstructionDataFormats/TrackParametrizationWithError.h"
2323
#include "ReconstructionDataFormats/BaseCluster.h"
2424
#include "ITSMFTReconstruction/ChipMappingITS.h"
25+
#include "DataFormatsITSMFT/ClustersPerLayer.h"
2526

2627
namespace o2
2728
{
@@ -76,9 +77,9 @@ class AlignableDetectorITS : public AlignableDetector
7677
//
7778
protected:
7879
//
79-
std::vector<ClusterD> mITSClustersArray;
80-
std::vector<int> mOverlapCandidateID; // pool of indices for potentially overlapping clusters
81-
std::vector<int> mOverlapClusRef; // 1st entry in mOverlapCandidateID for the overlapping cluster indices of each cluster
80+
o2::itsmft::ClustersPerLayer<ClusterD> mITSClustersArray;
81+
std::vector<int> mOverlapCandidateID; // pool of composed IDs of the potentially overlapping clusters
82+
std::vector<int> mOverlapClusRef; // 1st entry in mOverlapCandidateID for the overlapping clusters of each cluster, indexed by the flat cluster index
8283
std::vector<o2::itsmft::ChipMappingITS::Overlaps> mOverlaps;
8384
const o2::itsmft::TopologyDictionary* mITSDict{nullptr}; // cluster patterns dictionary
8485
//

‎Detectors/Align/src/AlignableDetectorITS.cxx‎

Lines changed: 99 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ int AlignableDetectorITS::processPoints(GIndex gid, int npntCut, bool inv)
219219

220220
if (clus.getCount()) { // there is an overlap, find best matching cluster
221221
nOverlaps--;
222-
int bestClusID = -1, clusIDtoCheck = mOverlapClusRef[clusIDs[icl]];
222+
int bestClusID = -1, clusIDtoCheck = mOverlapClusRef[mITSClustersArray.flatIndex(clusIDs[icl])];
223223
float bestChi2 = algConf.ITSOverlapMaxChi2;
224224
auto trPropOvl = trcProp;
225225
for (int iov = 0; iov < clus.getCount(); iov++) {
@@ -256,18 +256,11 @@ bool AlignableDetectorITS::prepareDetectorData()
256256
// prepare TF data for processing: convert clusters
257257
const auto& algConf = AlignConfig::Instance();
258258
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());
259+
int nLr = recoData->getITSPerLayer() ? o2::globaltracking::MaxITSLayers : 1;
260+
mITSClustersArray.init(nLr);
265261
if (algConf.ITSOverlapMargin > 0) {
266262
mOverlapClusRef.clear();
267-
mOverlapClusRef.resize(clusITS.size(), -1);
268-
269263
mOverlapCandidateID.clear();
270-
mOverlapCandidateID.reserve(clusITS.size());
271264
}
272265
static std::vector<int> edgeClusters;
273266
int ROFCount = 0;
@@ -278,103 +271,118 @@ bool AlignableDetectorITS::prepareDetectorData()
278271
};
279272
std::array<ROFChipEntry, o2::itsmft::ChipMappingITS::getNChips()> chipROFStart{}; // fill only for clusters with overlaps
280273

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
274+
for (int lr = 0; lr < nLr; lr++) { // with a single (monolithic) input all clusters are in the layer slot 0
275+
mITSClustersArray.beginLayer(lr);
276+
const auto clusITS = recoData->getITSClusters(lr);
277+
const auto clusITSROF = recoData->getITSClustersROFRecords(lr);
278+
const auto patterns = recoData->getITSClustersPatterns(lr);
279+
auto pattIt = patterns.begin();
280+
const int clOffs = mITSClustersArray.getFirstIndex(lr); // flat index of the 1st cluster of this layer slot
281+
mITSClustersArray.getClusters().reserve(clOffs + clusITS.size());
282+
if (algConf.ITSOverlapMargin > 0) {
283+
mOverlapClusRef.resize(clOffs + clusITS.size(), -1);
284+
mOverlapCandidateID.reserve(clOffs + clusITS.size());
285+
}
286+
287+
for (const auto& rof : clusITSROF) {
288+
int maxic = rof.getFirstEntry() + rof.getNEntries();
289+
edgeClusters.clear();
290+
for (int ic = rof.getFirstEntry(); ic < maxic; ic++) {
291+
const auto& c = clusITS[ic];
292+
int16_t sensID = c.getSensorID();
293+
auto* sensor = getSensor(sensID);
294+
double sigmaY2, sigmaZ2, sigmaYZ = 0, locXYZC[3], traXYZ[3];
295+
auto pattItCopy = pattIt;
296+
auto locXYZ = o2::its::ioutils::extractClusterDataA(c, pattIt, mITSDict, sigmaY2, sigmaZ2); // local ideal coordinates
297+
const auto& matAlg = sensor->getMatrixClAlg(); // local alignment matrix !!! RS FIXME
298+
matAlg.LocalToMaster(locXYZ.data(), locXYZC); // aligned point in the local frame
299+
const auto& mat = sensor->getMatrixT2L(); // RS FIXME check if correct
300+
mat.MasterToLocal(locXYZC, traXYZ);
301+
auto& cl3d = mITSClustersArray.getClusters().emplace_back(sensID, traXYZ[0], traXYZ[1], traXYZ[2], sigmaY2, sigmaZ2, sigmaYZ); // local --> tracking
296302

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;
301-
o2::itsmft::SegmentationAlpide::localToDetectorUnchecked(locXYZ[0], locXYZ[2], row, col);
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();
309-
if (pattID != itsmft::CompCluster::InvalidPatternID) {
310-
if (!mITSDict->isGroup(pattID)) {
311-
const auto& patt = mITSDict->getPattern(pattID); // reference pixel is min row/col corner
303+
if (algConf.ITSOverlapMargin > 0) {
304+
// fill chips overlaps info for clusters whose center is within of the algConf.ITSOverlapMargin distance from the chip min or max row edge
305+
// but the pixel closest to this edge has distance of at least algConf.ITSOverlapEdgeRows from the edge
306+
int row = 0, col = 0;
307+
o2::itsmft::SegmentationAlpide::localToDetectorUnchecked(locXYZ[0], locXYZ[2], row, col);
308+
int drow = row < o2::itsmft::SegmentationAlpide::NRows / 2 ? row : o2::itsmft::SegmentationAlpide::NRows - row - 1; // distance to the edge
309+
if (drow * o2::itsmft::SegmentationAlpide::PitchRow < algConf.ITSOverlapMargin) { // rough check is passed, check if the edge cluster is indeed good
310+
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
311+
// check if it is not too close to the edge (to be biased)
312+
if (algConf.ITSOverlapEdgeRows > 0) { // is there a restriction?
313+
auto pattID = c.getPatternID();
314+
drow = c.getRow();
315+
if (pattID != itsmft::CompCluster::InvalidPatternID) {
316+
if (!mITSDict->isGroup(pattID)) {
317+
const auto& patt = mITSDict->getPattern(pattID); // reference pixel is min row/col corner
318+
if (row > o2::itsmft::SegmentationAlpide::NRows / 2) {
319+
drow = o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() - 1);
320+
}
321+
} else { // group: reference pixel is the one containing the COG
322+
o2::itsmft::ClusterPattern patt(pattItCopy);
323+
drow = row < o2::itsmft::SegmentationAlpide::NRows / 2 ? drow - patt.getRowSpan() / 2 : o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() / 2 - 1);
324+
}
325+
} else {
326+
o2::itsmft::ClusterPattern patt(pattItCopy); // reference pixel is min row/col corner
312327
if (row > o2::itsmft::SegmentationAlpide::NRows / 2) {
313328
drow = o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() - 1);
314329
}
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);
318330
}
319-
} else {
320-
o2::itsmft::ClusterPattern patt(pattItCopy); // reference pixel is min row/col corner
321-
if (row > o2::itsmft::SegmentationAlpide::NRows / 2) {
322-
drow = o2::itsmft::SegmentationAlpide::NRows - 1 - (drow + patt.getRowSpan() - 1);
331+
if (drow < algConf.ITSOverlapEdgeRows) { // too close to the edge, flag this
332+
cl3d.setBit(EdgeFlags::Biased);
323333
}
324334
}
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
335+
if (!cl3d.isBitSet(EdgeFlags::Biased)) {
336+
if (chipROFStart[sensID].rofCount != ROFCount) { // remember 1st entry
337+
chipROFStart[sensID].rofCount = ROFCount;
338+
chipROFStart[sensID].chipFirstEntry = edgeClusters.size(); // remember 1st entry of edge cluster for this chip
339+
}
340+
edgeClusters.push_back(clOffs + ic);
333341
}
334-
edgeClusters.push_back(ic);
335342
}
336343
}
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
364-
mOverlapClusRef[ic] = mOverlapCandidateID.size();
344+
} // clusters of ROF
345+
// relate edge clusters of ROF to each other
346+
int prevSensID = -1;
347+
for (auto ic : edgeClusters) { // ic is the flat cluster index here
348+
auto& cl = mITSClustersArray.getClusters()[ic];
349+
int sensID = cl.getSensorID();
350+
auto ovl = mOverlaps[sensID];
351+
int ovlCount = 0;
352+
for (int ir = 0; ir < OVL::NSides; ir++) {
353+
if (ovl.rowSide[ir] == OVL::NONE) { // no overlap from this row side
354+
continue;
355+
}
356+
int chipOvl = ovl.rowSide[ir]; // look for overlaps with this chip
357+
// are there clusters with overlaps on chipOvl?
358+
if (chipROFStart[chipOvl].rofCount == ROFCount) {
359+
auto oClusID = edgeClusters[chipROFStart[chipOvl].chipFirstEntry];
360+
while (oClusID < int(mITSClustersArray.size())) {
361+
auto oClus = mITSClustersArray.getClusters()[oClusID];
362+
if (oClus.getSensorID() != sensID) {
363+
break; // no more clusters on the overlapping chip
365364
}
366-
mOverlapCandidateID.push_back(oClusID);
367-
ovlCount++;
365+
if (oClus.isBitSet(ovl.rowSideOverlap[ir]) && // make sure that the edge cluster is on the right side of the row
366+
!oClus.isBitSet(EdgeFlags::Biased) && // not too close to the edge
367+
std::abs(oClus.getZ() - cl.getZ()) < algConf.ITSOverlapMaxDZ) { // apply fiducial cut on Z distance of 2 clusters
368+
// register overlaping cluster
369+
if (!ovlCount) { // 1st overlap
370+
mOverlapClusRef[ic] = mOverlapCandidateID.size();
371+
}
372+
mOverlapCandidateID.push_back(o2::itsmft::composeClusID(lr, oClusID - clOffs)); // store the composed ID
373+
ovlCount++;
374+
}
375+
oClusID++;
368376
}
369-
oClusID++;
370377
}
371378
}
379+
cl.setCount(std::min(127, ovlCount));
372380
}
373-
cl.setCount(std::min(127, ovlCount));
374-
}
375381

376-
ROFCount++;
377-
} // loop over ROFs
382+
ROFCount++;
383+
} // loop over ROFs
384+
} // loop over the layer slots
385+
mITSClustersArray.finalize();
378386
return true;
379387
}
380388

0 commit comments

Comments
 (0)