Skip to content

Commit edba59a

Browse files
David Dobrigkeit Chinellatoromainschotter
authored andcommitted
Run 3 centrality in place
1 parent a8cf091 commit edba59a

File tree

2 files changed

+259
-9
lines changed

2 files changed

+259
-9
lines changed

Common/TableProducer/multCentTable.cxx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ struct MultCentTable {
144144
products.tableExtraMult2MCExtras(collision.mcCollisionId());
145145
}
146146
}
147-
void processCentrality(aod::Collisions const& collisions)
147+
void processCentrality(aod::Collisions const& collisions, soa::Join<aod::BCs, aod::Timestamps> const&)
148148
{
149149
// it is important that this function is at the end of the other process functions.
150150
// it requires `mults` to be properly set, which will only happen after the other process
@@ -157,10 +157,11 @@ struct MultCentTable {
157157
if(collisions.size() != mults.size()) {
158158
LOGF(fatal, "Size of collisions doesn't match size of multiplicity buffer!");
159159
}
160-
161-
// module.generateCentralities();
160+
auto const& collision = collisions.begin();
161+
const auto& bc = collision.bc_as<soa::Join<aod::BCs, aod::Timestamps>>();
162+
module.generateCentralities(ccdb, metadataInfo, bc, mults, products);
162163
}
163-
164+
164165
PROCESS_SWITCH(MultCentTable, processRun2, "Process Run 2", false);
165166
PROCESS_SWITCH(MultCentTable, processRun3, "Process Run 3", true);
166167
PROCESS_SWITCH(MultCentTable, processRun3WithGlobalCounters, "Process Run 3 + global tracking counters", false);

Common/Tools/MultModule.h

Lines changed: 254 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "Common/DataModel/Multiplicity.h"
3030
#include "Common/DataModel/Centrality.h"
3131
#include "PWGMM/Mult/DataModel/bestCollisionTable.h"
32+
#include "TFormula.h"
3233

3334
//__________________________________________
3435
// MultModule
@@ -245,9 +246,13 @@ struct standardConfigurables : o2::framework::ConfigurableGroup {
245246
o2::framework::Configurable<int> minNclsITSibGlobalTrack{"minNclsITSibGlobalTrack", 1, "min. number of ITSib clusters for global tracks"};
246247

247248
// ccdb information
248-
o2::framework::Configurable<std::string> ccdbPathVtxZ{"ccdbPathVtxZ", "Centrality/Calibration", "The CCDB path for centrality/multiplicity information"};
249+
o2::framework::Configurable<std::string> ccdbPathVtxZ{"ccdbPathVtxZ", "Centrality/Calibration", "The CCDB path for vertex-Z calibration"};
250+
o2::framework::Configurable<std::string> ccdbPathCentrality{"ccdbPathCentrality", "Centrality/Estimators", "The CCDB path for centrality information"};
249251
o2::framework::Configurable<std::string> reconstructionPass{"reconstructionPass", "", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}};
250252

253+
// centrality operation
254+
o2::framework::Configurable<std::string> generatorName{"generatorName", "", {"Specify if and only if this is MC. Typical: PYTHIA"}};
255+
o2::framework::Configurable<bool> embedINELgtZEROselection{"embedINELgtZEROselection", false, {"Option to do percentile 100.5 if not INELgtZERO"}};
251256
};
252257

253258
class MultModule
@@ -257,6 +262,7 @@ class MultModule
257262
{
258263
// constructor
259264
mRunNumber = 0;
265+
mRunNumberCentrality = 0;
260266
lCalibLoaded = false;
261267
lCalibObjects = nullptr;
262268
hVtxZFV0A = nullptr;
@@ -269,6 +275,7 @@ class MultModule
269275

270276
// internal: calib related, vtx-z profiles
271277
int mRunNumber;
278+
int mRunNumberCentrality;
272279
bool lCalibLoaded;
273280
TList* lCalibObjects;
274281
TProfile* hVtxZFV0A;
@@ -282,14 +289,90 @@ class MultModule
282289
// (N.B.: will be invisible to the outside, create your own copies)
283290
o2::common::multiplicity::standardConfigurables internalOpts;
284291

292+
//_________________________________________________
293+
// centrality-related objects
294+
struct TagRun2V0MCalibration {
295+
bool mCalibrationStored = false;
296+
TFormula* mMCScale = nullptr;
297+
float mMCScalePars[6] = {0.0};
298+
TH1* mhVtxAmpCorrV0A = nullptr;
299+
TH1* mhVtxAmpCorrV0C = nullptr;
300+
TH1* mhMultSelCalib = nullptr;
301+
} Run2V0MInfo;
302+
struct TagRun2V0ACalibration {
303+
bool mCalibrationStored = false;
304+
TH1* mhVtxAmpCorrV0A = nullptr;
305+
TH1* mhMultSelCalib = nullptr;
306+
} Run2V0AInfo;
307+
struct TagRun2SPDTrackletsCalibration {
308+
bool mCalibrationStored = false;
309+
TH1* mhVtxAmpCorr = nullptr;
310+
TH1* mhMultSelCalib = nullptr;
311+
} Run2SPDTksInfo;
312+
struct TagRun2SPDClustersCalibration {
313+
bool mCalibrationStored = false;
314+
TH1* mhVtxAmpCorrCL0 = nullptr;
315+
TH1* mhVtxAmpCorrCL1 = nullptr;
316+
TH1* mhMultSelCalib = nullptr;
317+
} Run2SPDClsInfo;
318+
struct TagRun2CL0Calibration {
319+
bool mCalibrationStored = false;
320+
TH1* mhVtxAmpCorr = nullptr;
321+
TH1* mhMultSelCalib = nullptr;
322+
} Run2CL0Info;
323+
struct TagRun2CL1Calibration {
324+
bool mCalibrationStored = false;
325+
TH1* mhVtxAmpCorr = nullptr;
326+
TH1* mhMultSelCalib = nullptr;
327+
} Run2CL1Info;
328+
struct CalibrationInfo {
329+
std::string name = "";
330+
bool mCalibrationStored = false;
331+
TH1* mhMultSelCalib = nullptr;
332+
float mMCScalePars[6] = {0.0};
333+
TFormula* mMCScale = nullptr;
334+
explicit CalibrationInfo(std::string name)
335+
: name(name),
336+
mCalibrationStored(false),
337+
mhMultSelCalib(nullptr),
338+
mMCScalePars{0.0},
339+
mMCScale(nullptr)
340+
{
341+
}
342+
bool isSane(bool fatalize = false)
343+
{
344+
if (!mhMultSelCalib) {
345+
return true;
346+
}
347+
for (int i = 1; i < mhMultSelCalib->GetNbinsX() + 1; i++) {
348+
if (mhMultSelCalib->GetXaxis()->GetBinLowEdge(i) > mhMultSelCalib->GetXaxis()->GetBinUpEdge(i)) {
349+
if (fatalize) {
350+
LOG(fatal) << "Centrality calibration table " << name << " has bins with low edge > up edge";
351+
}
352+
LOG(warning) << "Centrality calibration table " << name << " has bins with low edge > up edge";
353+
return false;
354+
}
355+
}
356+
return true;
357+
}
358+
};
359+
360+
CalibrationInfo fv0aInfo = CalibrationInfo("FV0");
361+
CalibrationInfo ft0mInfo = CalibrationInfo("FT0");
362+
CalibrationInfo ft0aInfo = CalibrationInfo("FT0A");
363+
CalibrationInfo ft0cInfo = CalibrationInfo("FT0C");
364+
CalibrationInfo ft0cVariant1Info = CalibrationInfo("FT0Cvar1");
365+
CalibrationInfo fddmInfo = CalibrationInfo("FDD");
366+
CalibrationInfo ntpvInfo = CalibrationInfo("NTracksPV");
367+
CalibrationInfo nGlobalInfo = CalibrationInfo("NGlobal");
368+
CalibrationInfo mftInfo = CalibrationInfo("MFT");
369+
370+
285371
template <typename TConfigurables, typename TInitContext>
286372
void init(TConfigurables const& opts, TInitContext& context)
287373
{
288374
// read in configurations from the task where it's used
289375
internalOpts = opts;
290-
291-
mRunNumber = 0;
292-
293376
internalOpts.mEnabledTables.resize(nTablesConst, 0);
294377

295378
LOGF(info, "Configuring tables to generate");
@@ -333,6 +416,7 @@ class MultModule
333416
}
334417

335418
mRunNumber = 0;
419+
mRunNumberCentrality = 0;
336420
lCalibLoaded = false;
337421
hVtxZFV0A = nullptr;
338422
hVtxZFT0A = nullptr;
@@ -344,10 +428,12 @@ class MultModule
344428

345429
//__________________________________________________
346430
template <typename TCollision, typename TTracks, typename TBCs, typename TZdc, typename TFV0A, typename TFV0C, typename TFT0>
347-
void collisionProcessRun2(TCollision const& collision, TTracks const& tracks, TBCs const& bcs, TZdc const& zdc, TFV0A const& fv0a, TFV0C const& fv0c, TFT0 const& ft0 )
431+
o2::common::multiplicity::multEntry collisionProcessRun2(TCollision const& collision, TTracks const& tracks, TBCs const& bcs, TZdc const& zdc, TFV0A const& fv0a, TFV0C const& fv0c, TFT0 const& ft0 )
348432
{
349433
// initialize properties
350434
o2::common::multiplicity::multEntry mults;
435+
436+
return mults;
351437
}
352438

353439
//__________________________________________________
@@ -665,6 +751,169 @@ class MultModule
665751
mults[collision.globalIndex()].multMFTAllTracks = nAllTracks;
666752
mults[collision.globalIndex()].multMFTTracks = nTracks;
667753
}
754+
755+
//__________________________________________________
756+
template <typename TCCDB, typename TMetadata, typename TBC>
757+
void ConfigureCentralityRun3(TCCDB& ccdb, TMetadata const& metadataInfo, TBC const& bc){
758+
if (bc.runNumber() != mRunNumberCentrality) {
759+
mRunNumberCentrality = bc.runNumber(); // mark that this run has been attempted already regardless of outcome
760+
LOGF(info, "centrality loading procedure for timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber());
761+
TList* callst = nullptr;
762+
// Check if the ccdb path is a root file
763+
if (internalOpts.ccdbPathCentrality.value.find(".root") != std::string::npos) {
764+
TFile f(internalOpts.ccdbPathCentrality.value.c_str(), "READ");
765+
f.GetObject(internalOpts.reconstructionPass.value.c_str(), callst);
766+
if (!callst) {
767+
f.ls();
768+
LOG(fatal) << "No calibration list " << internalOpts.reconstructionPass.value << " found.";
769+
}
770+
} else {
771+
if (internalOpts.reconstructionPass.value == "") {
772+
callst = ccdb->template getForRun<TList>(internalOpts.ccdbPathCentrality, bc.runNumber());
773+
} else if (internalOpts.reconstructionPass.value == "metadata") {
774+
std::map<std::string, std::string> metadata;
775+
metadata["RecoPassName"] = metadataInfo.get("RecoPassName");
776+
LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName"));
777+
callst = ccdb->template getSpecificForRun<TList>(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata);
778+
} else {
779+
std::map<std::string, std::string> metadata;
780+
metadata["RecoPassName"] = internalOpts.reconstructionPass.value;
781+
LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value);
782+
callst = ccdb->template getSpecificForRun<TList>(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata);
783+
}
784+
}
785+
786+
fv0aInfo.mCalibrationStored = false;
787+
ft0mInfo.mCalibrationStored = false;
788+
ft0aInfo.mCalibrationStored = false;
789+
ft0cInfo.mCalibrationStored = false;
790+
ft0cVariant1Info.mCalibrationStored = false;
791+
fddmInfo.mCalibrationStored = false;
792+
ntpvInfo.mCalibrationStored = false;
793+
nGlobalInfo.mCalibrationStored = false;
794+
mftInfo.mCalibrationStored = false;
795+
if (callst != nullptr) {
796+
LOGF(info, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber());
797+
auto getccdb = [callst, bc](struct CalibrationInfo& estimator, const o2::framework::Configurable<std::string> generatorName) { // TODO: to consider the name inside the estimator structure
798+
estimator.mhMultSelCalib = reinterpret_cast<TH1*>(callst->FindObject(TString::Format("hCalibZeq%s", estimator.name.c_str()).Data()));
799+
estimator.mMCScale = reinterpret_cast<TFormula*>(callst->FindObject(TString::Format("%s-%s", generatorName->c_str(), estimator.name.c_str()).Data()));
800+
if (estimator.mhMultSelCalib != nullptr) {
801+
if (generatorName->length() != 0) {
802+
LOGF(info, "Retrieving MC calibration for %d, generator name: %s", bc.runNumber(), generatorName->c_str());
803+
if (estimator.mMCScale != nullptr) {
804+
for (int ixpar = 0; ixpar < 6; ++ixpar) {
805+
estimator.mMCScalePars[ixpar] = estimator.mMCScale->GetParameter(ixpar);
806+
LOGF(info, "Parameter index %i value %.5f", ixpar, estimator.mMCScalePars[ixpar]);
807+
}
808+
} else {
809+
LOGF(warning, "MC Scale information from %s for run %d not available", estimator.name.c_str(), bc.runNumber());
810+
}
811+
}
812+
estimator.mCalibrationStored = true;
813+
estimator.isSane();
814+
} else {
815+
LOGF(info, "Calibration information from %s for run %d not available, will fill this estimator with invalid values and continue (no crash).", estimator.name.c_str(), bc.runNumber());
816+
}
817+
};
818+
819+
// invoke loading only for requested centralities
820+
if(internalOpts.mEnabledTables[kCentFV0As])
821+
getccdb(fv0aInfo, internalOpts.generatorName);
822+
if(internalOpts.mEnabledTables[kCentFT0Ms])
823+
getccdb(ft0mInfo, internalOpts.generatorName);
824+
if(internalOpts.mEnabledTables[kCentFT0As])
825+
getccdb(ft0aInfo, internalOpts.generatorName);
826+
if(internalOpts.mEnabledTables[kCentFT0Cs])
827+
getccdb(ft0cInfo, internalOpts.generatorName);
828+
if(internalOpts.mEnabledTables[kCentFT0CVariant1s])
829+
getccdb(ft0cVariant1Info, internalOpts.generatorName);
830+
if(internalOpts.mEnabledTables[kCentFDDMs])
831+
getccdb(fddmInfo, internalOpts.generatorName);
832+
if(internalOpts.mEnabledTables[kCentNTPVs])
833+
getccdb(ntpvInfo, internalOpts.generatorName);
834+
if(internalOpts.mEnabledTables[kCentNGlobals])
835+
getccdb(nGlobalInfo, internalOpts.generatorName);
836+
if(internalOpts.mEnabledTables[kCentMFTs])
837+
getccdb(mftInfo, internalOpts.generatorName);
838+
} else {
839+
LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp());
840+
}
841+
}
842+
}
843+
844+
//__________________________________________________
845+
template <typename TCCDB, typename TMetadata, typename TBC, typename TMultBuffer, typename TOutputGroup>
846+
void generateCentralities(TCCDB& ccdb, TMetadata const& metadataInfo, TBC const& bc, TMultBuffer const& mults, TOutputGroup& cursors){
847+
// takes multiplicity buffer and generates the desirable centrality values (if any)
848+
849+
// first step: did someone actually ask for it? Otherwise, go home
850+
if(
851+
internalOpts.mEnabledTables[kCentRun2V0Ms] || internalOpts.mEnabledTables[kCentRun2V0As] ||
852+
internalOpts.mEnabledTables[kCentRun2SPDTrks] || internalOpts.mEnabledTables[kCentRun2SPDClss] ||
853+
internalOpts.mEnabledTables[kCentRun2CL0s] || internalOpts.mEnabledTables[kCentRun2CL1s] ||
854+
internalOpts.mEnabledTables[kCentFV0As] || internalOpts.mEnabledTables[kCentFT0Ms] ||
855+
internalOpts.mEnabledTables[kCentFT0As] || internalOpts.mEnabledTables[kCentFT0Cs] ||
856+
internalOpts.mEnabledTables[kCentFT0CVariant1s] || internalOpts.mEnabledTables[kCentFDDMs] ||
857+
internalOpts.mEnabledTables[kCentNTPVs] || internalOpts.mEnabledTables[kCentNGlobals] ||
858+
internalOpts.mEnabledTables[kCentMFTs])
859+
{
860+
// check and update centrality calibration objects for Run 3
861+
ConfigureCentralityRun3(ccdb, metadataInfo, bc);
862+
863+
/************************************************************
864+
* @brief Populates a table with data based on the given calibration information and multiplicity.
865+
*
866+
* @param table The table to populate.
867+
* @param estimator The calibration information.
868+
* @param multiplicity The multiplicity value.
869+
*************************************************************/
870+
871+
auto populateTable = [&](auto& table, struct CalibrationInfo& estimator, float multiplicity, bool isInelGt0) {
872+
const bool assignOutOfRange = internalOpts.embedINELgtZEROselection && !isInelGt0;
873+
auto scaleMC = [](float x, float pars[6]) {
874+
return std::pow(((pars[0] + pars[1] * std::pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]);
875+
};
876+
877+
float percentile = 105.0f;
878+
float scaledMultiplicity = multiplicity;
879+
if (estimator.mCalibrationStored) {
880+
if (estimator.mMCScale != nullptr) {
881+
scaledMultiplicity = scaleMC(multiplicity, estimator.mMCScalePars);
882+
LOGF(debug, "Unscaled %s multiplicity: %f, scaled %s multiplicity: %f", estimator.name.c_str(), multiplicity, estimator.name.c_str(), scaledMultiplicity);
883+
}
884+
percentile = estimator.mhMultSelCalib->GetBinContent(estimator.mhMultSelCalib->FindFixBin(scaledMultiplicity));
885+
if (assignOutOfRange)
886+
percentile = 100.5f;
887+
}
888+
LOGF(debug, "%s centrality/multiplicity percentile = %.0f for a zvtx eq %s value %.0f", estimator.name.c_str(), percentile, estimator.name.c_str(), scaledMultiplicity);
889+
table(percentile);
890+
return percentile;
891+
};
892+
893+
// populate centralities
894+
for (size_t iEv = 0; iEv < mults.size(); iEv++) {
895+
bool isInelGt0 = (mults[iEv].multNContribsEta1 > 0);
896+
if(internalOpts.mEnabledTables[kCentFV0As])
897+
populateTable(cursors.centFV0A, fv0aInfo, mults[iEv].multFV0AZeq, isInelGt0);
898+
if(internalOpts.mEnabledTables[kCentFT0Ms])
899+
populateTable(cursors.centFT0M, ft0mInfo, mults[iEv].multFT0AZeq + mults[iEv].multFT0CZeq, isInelGt0);
900+
if(internalOpts.mEnabledTables[kCentFT0As])
901+
populateTable(cursors.centFT0A, ft0aInfo, mults[iEv].multFT0AZeq, isInelGt0);
902+
if(internalOpts.mEnabledTables[kCentFT0Cs])
903+
populateTable(cursors.centFT0C, ft0cInfo, mults[iEv].multFT0CZeq, isInelGt0);
904+
if(internalOpts.mEnabledTables[kCentFT0CVariant1s])
905+
populateTable(cursors.centFT0CVariant1, ft0cVariant1Info, mults[iEv].multFT0CZeq, isInelGt0);
906+
if(internalOpts.mEnabledTables[kCentFDDMs])
907+
populateTable(cursors.centFDDM, fddmInfo, mults[iEv].multFDDAZeq + mults[iEv].multFDDCZeq, isInelGt0);
908+
if(internalOpts.mEnabledTables[kCentNTPVs])
909+
populateTable(cursors.centNTPV, ntpvInfo, mults[iEv].multNContribs, isInelGt0);
910+
if(internalOpts.mEnabledTables[kCentNGlobals])
911+
populateTable(cursors.centNGlobals, nGlobalInfo, mults[iEv].multGlobalTracks, isInelGt0);
912+
if(internalOpts.mEnabledTables[kCentMFTs])
913+
populateTable(cursors.centMFTs, mftInfo, mults[iEv].multMFTTracks, isInelGt0);
914+
}
915+
}
916+
}
668917
}; // end BuilderModule
669918

670919
} // namespace multiplicity

0 commit comments

Comments
 (0)