Skip to content

Commit 6cd6ed0

Browse files
shahor02claude
andcommitted
Support per-layer ITS clusters in its-standalone-postprocessing-workflow
All 7 study classes selectable from this single workflow. AnomalyStudy is ported in full (its nROF is a config parameter and all histograms are per layer, so per-layer ROF counters are the natural granularity). EfficiencyStudy and ITSBeamBackgroundStudy request the per-layer input but refuse to run on it (LOGP fatal): their algorithms rely on assumptions the staggered readout breaks (cluster-ROF index == track-ROF index; chaining consecutive ROFs across the 3 IB layers into one strobe series), and the replacement is an analysis choice for the study to make. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent cb8d8bd commit 6cd6ed0

15 files changed

Lines changed: 181 additions & 112 deletions

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/AnomalyStudy.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace study
2222

2323
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
2424

25-
o2::framework::DataProcessorSpec getAnomalyStudy(mask_t srcClustersMask, bool useMC);
25+
o2::framework::DataProcessorSpec getAnomalyStudy(mask_t srcClustersMask, bool useMC, bool itsStag);
2626
} // namespace study
2727
} // namespace o2::its
2828

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/AvgClusSize.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace study
2828

2929
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
3030

31-
o2::framework::DataProcessorSpec getAvgClusSizeStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader);
31+
o2::framework::DataProcessorSpec getAvgClusSizeStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag);
3232
} // namespace study
3333
} // namespace its
3434
} // namespace o2

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/Efficiency.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace its
2626
namespace study
2727
{
2828
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
29-
o2::framework::DataProcessorSpec getEfficiencyStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader);
29+
o2::framework::DataProcessorSpec getEfficiencyStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag);
3030

3131
float mEtaCuts[2] = {-1.0, 1.0};
3232
float mPtCuts[2] = {0, 10}; /// no cut for B=0

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/ITSBeamBackgroundStudy.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace o2::its::study
2020

2121
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
2222

23-
o2::framework::DataProcessorSpec getITSBeamBackgroundStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC);
23+
o2::framework::DataProcessorSpec getITSBeamBackgroundStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, bool itsStag);
2424

2525
} // namespace o2::its::study
2626
#endif

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/PIDStudy.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace study
2828

2929
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
3030

31-
o2::framework::DataProcessorSpec getPIDStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader);
31+
o2::framework::DataProcessorSpec getPIDStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag);
3232
} // namespace study
3333
} // namespace its
3434
} // namespace o2

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/TrackCheck.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace its
2626
namespace study
2727
{
2828
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
29-
o2::framework::DataProcessorSpec getTrackCheckStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader);
29+
o2::framework::DataProcessorSpec getTrackCheckStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag);
3030
} // namespace study
3131
} // namespace its
3232
} // namespace o2

‎Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/TrackExtension.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class MCKinematicsReader;
2424
namespace its::study
2525
{
2626
using mask_t = o2::dataformats::GlobalTrackID::mask_t;
27-
o2::framework::DataProcessorSpec getTrackExtensionStudy(mask_t srcTracksMask, mask_t srcClustersMask, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader);
27+
o2::framework::DataProcessorSpec getTrackExtensionStudy(mask_t srcTracksMask, mask_t srcClustersMask, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag);
2828
} // namespace its::study
2929

3030
} // namespace o2

‎Detectors/ITSMFT/ITS/postprocessing/studies/src/AnomalyStudy.cxx‎

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -197,41 +197,47 @@ void AnomalyStudy::process(o2::globaltracking::RecoContainer& recoData)
197197
auto nROF = o2::its::study::AnomalyStudyParamConfig::Instance().nRofTimeFrames;
198198
auto nLayProc = o2::its::study::AnomalyStudyParamConfig::Instance().nLayersToProcess;
199199
auto doROFAnalysis = o2::its::study::AnomalyStudyParamConfig::Instance().doROFAnalysis;
200-
int rofCount = 0;
201-
auto clusRofRecords = recoData.getITSClustersROFRecords();
202-
auto compClus = recoData.getITSClusters();
203-
auto clusPatt = recoData.getITSClustersPatterns();
204-
205-
getClusterPatterns(compClus, clusPatt, *mDict);
206-
207-
auto pattIt = clusPatt.begin();
208-
std::vector<ITSCluster> globalClusters;
209-
o2::its::ioutils::convertCompactClusters(compClus, pattIt, globalClusters, mDict);
210-
211200
int lay, sta, ssta, mod, chipInMod;
212-
for (auto& rofRecord : clusRofRecords) {
213-
auto clustersInRof = rofRecord.getROFData(compClus);
214-
auto patternsInRof = rofRecord.getROFData(mPatterns);
215-
auto locClustersInRof = rofRecord.getROFData(globalClusters);
216-
for (unsigned int clusInd{0}; clusInd < clustersInRof.size(); clusInd++) {
217-
const auto& compClus = clustersInRof[clusInd];
218-
auto& locClus = locClustersInRof[clusInd];
219-
auto& clusPattern = patternsInRof[clusInd];
220-
auto gloC = locClus.getXYZGlo(*mGeom);
221-
mChipMapping.expandChipInfoHW(compClus.getChipID(), lay, sta, ssta, mod, chipInMod);
222-
if (lay >= nLayProc) {
223-
continue;
224-
}
225-
float phi = TMath::ATan2(gloC.Y(), gloC.X());
226-
mTFvsPhiHist[lay]->Fill(phi, mTFCount);
227-
mTFvsPhiClusSizeHist[lay]->Fill(phi, mTFCount, clusPattern.getNPixels());
228-
if (doROFAnalysis) {
229-
mROFvsPhiHist[lay]->Fill(phi, (mTFCount - 1) * nROF + rofCount);
230-
mROFvsPhiClusSizeHist[lay]->Fill(phi, (mTFCount - 1) * nROF + rofCount, clusPattern.getNPixels());
201+
// in the staggered readout the clusters and their ROFs are provided per layer, every layer having its
202+
// own ROF length and numbering; all the filled histograms are per layer, hence each layer slot is
203+
// processed with its own ROF counter
204+
int nLr = recoData.getITSPerLayer() ? o2::globaltracking::MaxITSLayers : 1;
205+
for (int lr = 0; lr < nLr; lr++) { // with a single (monolithic) input all clusters are in the layer slot 0
206+
int rofCount = 0;
207+
auto clusRofRecords = recoData.getITSClustersROFRecords(lr);
208+
auto compClus = recoData.getITSClusters(lr);
209+
auto clusPatt = recoData.getITSClustersPatterns(lr);
210+
211+
getClusterPatterns(compClus, clusPatt, *mDict);
212+
213+
auto pattIt = clusPatt.begin();
214+
std::vector<ITSCluster> globalClusters;
215+
o2::its::ioutils::convertCompactClusters(compClus, pattIt, globalClusters, mDict);
216+
217+
for (auto& rofRecord : clusRofRecords) {
218+
auto clustersInRof = rofRecord.getROFData(compClus);
219+
auto patternsInRof = rofRecord.getROFData(mPatterns);
220+
auto locClustersInRof = rofRecord.getROFData(globalClusters);
221+
for (unsigned int clusInd{0}; clusInd < clustersInRof.size(); clusInd++) {
222+
const auto& compClus = clustersInRof[clusInd];
223+
auto& locClus = locClustersInRof[clusInd];
224+
auto& clusPattern = patternsInRof[clusInd];
225+
auto gloC = locClus.getXYZGlo(*mGeom);
226+
mChipMapping.expandChipInfoHW(compClus.getChipID(), lay, sta, ssta, mod, chipInMod);
227+
if (lay >= nLayProc) {
228+
continue;
229+
}
230+
float phi = TMath::ATan2(gloC.Y(), gloC.X());
231+
mTFvsPhiHist[lay]->Fill(phi, mTFCount);
232+
mTFvsPhiClusSizeHist[lay]->Fill(phi, mTFCount, clusPattern.getNPixels());
233+
if (doROFAnalysis) {
234+
mROFvsPhiHist[lay]->Fill(phi, (mTFCount - 1) * nROF + rofCount);
235+
mROFvsPhiClusSizeHist[lay]->Fill(phi, (mTFCount - 1) * nROF + rofCount, clusPattern.getNPixels());
236+
}
231237
}
238+
++rofCount;
232239
}
233-
++rofCount;
234-
}
240+
} // loop over the layer slots
235241
mStopwatch.Stop();
236242
LOGP(info, "Processed TF: {} in {} s", mTFCount, mStopwatch.RealTime());
237243
}
@@ -263,10 +269,11 @@ void AnomalyStudy::getClusterPatterns(gsl::span<const o2::itsmft::CompClusterExt
263269
}
264270

265271
// getter
266-
DataProcessorSpec getAnomalyStudy(mask_t srcClustersMask, bool useMC)
272+
DataProcessorSpec getAnomalyStudy(mask_t srcClustersMask, bool useMC, bool itsStag)
267273
{
268274
std::vector<OutputSpec> outputs;
269275
auto dataRequest = std::make_shared<DataRequest>();
276+
dataRequest->setITSPerLayer(itsStag);
270277
dataRequest->requestClusters(srcClustersMask, useMC);
271278
dataRequest->requestTracks(GTrackID::getSourcesMask(""), useMC);
272279

‎Detectors/ITSMFT/ITS/postprocessing/studies/src/AvgClusSize.cxx‎

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "DataFormatsParameters/GRPObject.h"
2626
#include "DataFormatsITS/TrackITS.h"
2727
#include "DataFormatsGlobalTracking/RecoContainer.h"
28+
#include "DataFormatsITSMFT/ClustersPerLayer.h"
2829
#include "ReconstructionDataFormats/GlobalTrackID.h"
2930
#include "ReconstructionDataFormats/PrimaryVertex.h"
3031
#include "ReconstructionDataFormats/PID.h"
@@ -90,7 +91,7 @@ class AvgClusSizeStudy final : public Task
9091
float getAverageClusterSize(o2::its::TrackITS*);
9192
float calcV0HypoMass(const V0&, PID, PID);
9293
void calcAPVars(const V0&, float*, float*);
93-
void getClusterSizes(std::vector<int>&, const gsl::span<const o2::itsmft::CompClusterExt>, gsl::span<const unsigned char>::iterator&, const o2::itsmft::TopologyDictionary*);
94+
void getClusterSizes(std::vector<int>&, int offs, const gsl::span<const o2::itsmft::CompClusterExt>, gsl::span<const unsigned char>::iterator&, const o2::itsmft::TopologyDictionary*);
9495
void saveHistograms();
9596
void plotHistograms();
9697
void fillEtaBin(float eta, float clusSize, int i);
@@ -101,7 +102,7 @@ class AvgClusSizeStudy final : public Task
101102
// Data
102103
std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
103104
std::shared_ptr<DataRequest> mDataRequest;
104-
std::vector<int> mClusterSizes;
105+
o2::itsmft::ClustersPerLayer<int> mClusterSizes; // addressed by the composed (layer,index) ID
105106
gsl::span<const int> mInputITSidxs;
106107
std::vector<o2::MCTrack> mMCTracks;
107108
const o2::itsmft::TopologyDictionary* mDict = nullptr;
@@ -294,7 +295,7 @@ void AvgClusSizeStudy::run(ProcessingContext& pc)
294295
process(recoData);
295296
}
296297

297-
void AvgClusSizeStudy::getClusterSizes(std::vector<int>& clusSizeVec, const gsl::span<const o2::itsmft::CompClusterExt> ITSclus, gsl::span<const unsigned char>::iterator& pattIt, const o2::itsmft::TopologyDictionary* mdict)
298+
void AvgClusSizeStudy::getClusterSizes(std::vector<int>& clusSizeVec, int offs, const gsl::span<const o2::itsmft::CompClusterExt> ITSclus, gsl::span<const unsigned char>::iterator& pattIt, const o2::itsmft::TopologyDictionary* mdict)
298299
{
299300
for (unsigned int iClus{0}; iClus < ITSclus.size(); ++iClus) {
300301
auto& clus = ITSclus[iClus];
@@ -309,18 +310,26 @@ void AvgClusSizeStudy::getClusterSizes(std::vector<int>& clusSizeVec, const gsl:
309310
npix = mdict->getNpixels(pattID);
310311
patt = mdict->getPattern(pattID);
311312
}
312-
clusSizeVec[iClus] = npix;
313+
clusSizeVec[offs + iClus] = npix;
313314
}
314315
}
315316

316317
void AvgClusSizeStudy::loadData(o2::globaltracking::RecoContainer& recoData)
317318
{
318319
mInputITSidxs = recoData.getITSTracksClusterRefs();
319-
auto compClus = recoData.getITSClusters();
320-
auto clusPatt = recoData.getITSClustersPatterns();
321-
mClusterSizes.resize(compClus.size());
322-
auto pattIt = clusPatt.begin();
323-
getClusterSizes(mClusterSizes, compClus, pattIt, mDict);
320+
int nLr = recoData.getITSPerLayer() ? o2::globaltracking::MaxITSLayers : 1;
321+
mClusterSizes.init(nLr);
322+
for (int lr = 0; lr < nLr; lr++) { // with a single (monolithic) input all clusters are in the layer slot 0
323+
mClusterSizes.beginLayer(lr);
324+
auto compClus = recoData.getITSClusters(lr);
325+
auto clusPatt = recoData.getITSClustersPatterns(lr);
326+
auto pattIt = clusPatt.begin();
327+
auto& sizes = mClusterSizes.getClusters();
328+
int offs = (int)sizes.size();
329+
sizes.resize(offs + compClus.size());
330+
getClusterSizes(sizes, offs, compClus, pattIt, mDict);
331+
}
332+
mClusterSizes.finalize();
324333
}
325334

326335
void AvgClusSizeStudy::process(o2::globaltracking::RecoContainer& recoData)
@@ -646,10 +655,11 @@ void AvgClusSizeStudy::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
646655
}
647656
}
648657

649-
DataProcessorSpec getAvgClusSizeStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader)
658+
DataProcessorSpec getAvgClusSizeStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag)
650659
{
651660
std::vector<OutputSpec> outputs;
652661
auto dataRequest = std::make_shared<DataRequest>();
662+
dataRequest->setITSPerLayer(itsStag);
653663
dataRequest->requestTracks(srcTracksMask, useMC);
654664
dataRequest->requestClusters(srcClustersMask, useMC);
655665
dataRequest->requestSecondaryVertices(useMC);

‎Detectors/ITSMFT/ITS/postprocessing/studies/src/Efficiency.cxx‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,14 @@ void EfficiencyStudy::run(ProcessingContext& pc)
558558
void EfficiencyStudy::initialiseRun(o2::globaltracking::RecoContainer& recoData)
559559
{
560560
LOGP(info, "--------------- initialiseRun");
561+
if (recoData.getITSPerLayer()) {
562+
// The duplicated-cluster search scans the cluster ROF whose index equals that of the track ROF and
563+
// relies on the two ROF series being the same. With the staggered readout every layer has its own
564+
// ROF length and numbering, while the track ROFs follow the clock layer only, so the ROF of the
565+
// layer to scan has to be found from the track time instead. This requires deciding whether a
566+
// duplicate is searched in a single ROF or in all the ROFs compatible with the track time bracket.
567+
LOGP(fatal, "EfficiencyStudy does not support the per-layer (staggered) ITS clusters input yet");
568+
}
561569
if (mUseMC) {
562570
mTracksMCLabels = recoData.getITSTracksMCLabels();
563571
mClustersMCLCont = recoData.getITSClustersMCLabels();
@@ -2837,10 +2845,11 @@ void EfficiencyStudy::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
28372845
}
28382846
}
28392847

2840-
DataProcessorSpec getEfficiencyStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader)
2848+
DataProcessorSpec getEfficiencyStudy(mask_t srcTracksMask, mask_t srcClustersMask, bool useMC, std::shared_ptr<o2::steer::MCKinematicsReader> kineReader, bool itsStag)
28412849
{
28422850
std::vector<OutputSpec> outputs;
28432851
auto dataRequest = std::make_shared<DataRequest>();
2852+
dataRequest->setITSPerLayer(itsStag);
28442853
dataRequest->requestTracks(srcTracksMask, useMC);
28452854
dataRequest->requestClusters(srcClustersMask, useMC);
28462855

0 commit comments

Comments
 (0)