From 6598f93e6d11398c79500c34f02af945421a2fd3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 6 Feb 2024 21:03:05 +0100 Subject: [PATCH 01/50] Disable CTPLumi request in absence of CTP --- prodtests/full-system-test/dpl-workflow.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 936a2e0583836..70b2dcf306f6e 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -271,6 +271,7 @@ GPU_CONFIG_SELF="--severity $SEVERITY_TPC" parse_TPC_CORR_SCALING() { local IGNOREIDC=1 +local CTPLUMY_DISABLED=0 while [[ $# -gt 0 ]]; do case "$1" in --lumi-type=*) TPC_CORR_OPT+=" --lumi-type ${1#*=}"; [[ ${1#*=} == "2" ]] && { NEED_TPC_SCALERS_WF=1; IGNOREIDC=0; }; shift 1;; @@ -278,11 +279,12 @@ while [[ $# -gt 0 ]]; do --enable-M-shape-correction) TPC_CORR_OPT+=" --enable-M-shape-correction"; NEED_TPC_SCALERS_WF=1; TPC_SCALERS_CONF+=" --enable-M-shape-correction" ; shift 1;; --corrmap-lumi-mode=*) TPC_CORR_OPT+=" --corrmap-lumi-mode ${1#*=}"; shift 1;; --corrmap-lumi-mode) TPC_CORR_OPT+=" --corrmap-lumi-mode ${2}"; shift 2;; - --disable-ctp-lumi-request) TPC_CORR_OPT+=" --disable-ctp-lumi-request"; shift 1;; + --disable-ctp-lumi-request) TPC_CORR_OPT+=" --disable-ctp-lumi-request"; CTPLUMY_DISABLED=1; shift 1;; *) TPC_CORR_KEY+="$1;"; shift 1;; esac done [[ ${NEED_TPC_SCALERS_WF:-} == 1 ]] && [[ $IGNOREIDC == 1 ]] && TPC_SCALERS_CONF+=" --disable-IDC-scalers" +! has_detector CTP && [[ ${CTPLUMY_DISABLED:-} != 1 ]] && TPC_CORR_OPT+=" --disable-ctp-lumi-request" } parse_TPC_CORR_SCALING $TPC_CORR_SCALING From 10b3d0e3f1ab4d50050b30eb5b9380f957edbf7a Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 5 Feb 2024 03:00:59 +0100 Subject: [PATCH 02/50] Adjust TrackParComp ELoss contribution to sigma(q/pt)^2 --- .../Reconstruction/src/TrackParametrizationWithError.cxx | 2 +- GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 2 +- GPU/GPUTracking/SliceTracker/GPUTPCTrackParam.cxx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index ab8999f8bdccf..087e662fe41ff 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -1103,7 +1103,7 @@ GPUd() bool TrackParametrizationWithError::correctForMaterial(value_t x } // the energy loss correction contribution to cov.matrix: approximate energy loss fluctuation (M.Ivanov) - constexpr value_t knst = 0.07f; // To be tuned. + constexpr value_t knst = 0.0007f; // To be tuned. value_t sigmadE = knst * gpu::CAMath::Sqrt(gpu::CAMath::Abs(dETot)) * e0 / p02 * this->getCharge2Pt(); cC44 += sigmadE * sigmadE; diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index fba36a69d10b4..1939a58f64a1e 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -840,7 +840,7 @@ GPUd() void GPUTPCCompressionTrackModel::calculateMaterialCorrection() // Approximate energy loss fluctuation (M.Ivanov) - const float knst = 0.07f; // To be tuned. + const float knst = 0.0007f; // To be tuned. mMaterial.sigmadE2 = knst * mMaterial.EP2 * qpt; mMaterial.sigmadE2 = mMaterial.sigmadE2 * mMaterial.sigmadE2; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 54cccf74c271c..201da0b490767 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -929,7 +929,7 @@ GPUd() void GPUTPCGMPropagator::CalculateMaterialCorrection() // Approximate energy loss fluctuation (M.Ivanov) - const float knst = 0.07f; // To be tuned. + const float knst = 0.0007f; // To be tuned. mMaterial.sigmadE2 = knst * mMaterial.EP2 * qpt; mMaterial.sigmadE2 = mMaterial.sigmadE2 * mMaterial.sigmadE2; diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackParam.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackParam.cxx index fcbba6764a3c8..9834037f9e51a 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackParam.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackParam.cxx @@ -463,7 +463,7 @@ GPUd() void MEM_LG(GPUTPCTrackParam)::CalculateFitParameters(GPUTPCTrackFitParam // Approximate energy loss fluctuation (M.Ivanov) - const float knst = 0.07f; // To be tuned. + const float knst = 0.0007f; // To be tuned. par.sigmadE2 = knst * par.EP2 * qpt; par.sigmadE2 = par.sigmadE2 * par.sigmadE2; From 56ff84c4f2616b11b54de56e76fa3822031cab93 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 6 Feb 2024 21:05:28 +0100 Subject: [PATCH 03/50] account for TPC/ITS PID difference in propagation to ref.X --- .../include/GlobalTracking/MatchTPCITS.h | 13 +- .../GlobalTracking/MatchTPCITSParams.h | 2 + Detectors/GlobalTracking/src/MatchTPCITS.cxx | 132 ++++++++++++++---- 3 files changed, 114 insertions(+), 33 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index db7b3934513c3..156321ba359a9 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -113,7 +113,8 @@ enum TrackRejFlag : int { RejectOnTgl, RejectOnQ2Pt, RejectOnChi2, - NSigmaShift = 10 + NSigmaShift = 10, + RejectoOnPIDCorr = 20 }; ///< TPC track parameters propagated to reference X, with time bracket and index of @@ -139,7 +140,7 @@ struct TrackLocTPC : public o2::track::TrackParCov { return constraint == Constrained ? 0. : (constraint == ASide ? dt : -dt); } - ClassDefNV(TrackLocTPC, 1); + ClassDefNV(TrackLocTPC, 2); }; ///< ITS track outward parameters propagated to reference X, with time bracket and index of @@ -151,6 +152,8 @@ struct TrackLocITS : public o2::track::TrackParCov { int sourceID = 0; ///< track origin id int roFrame = MinusOne; ///< ITS readout frame assigned to this track int matchID = MinusOne; ///< entry (non if MinusOne) of its matchCand struct in the mMatchesITS + float xrho = 0; ///< x*rho seen during propagation to reference X (as pion) + float dL = 0; ///< distance integrated during propagation to reference X (as pion) bool hasCloneBefore() const { return getUserField() & CloneBefore; } bool hasCloneAfter() const { return getUserField() & CloneAfter; } int getCloneShift() const { return hasCloneBefore() ? -1 : (hasCloneAfter() ? 1 : 0); } @@ -479,8 +482,8 @@ class MatchTPCITS int compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& tTPC, float& chi2) const; float getPredictedChi2NoZ(const o2::track::TrackParCov& trITS, const o2::track::TrackParCov& trTPC) const; - bool propagateToRefX(o2::track::TrackParCov& trc); - void addLastTrackCloneForNeighbourSector(int sector); + bool propagateToRefX(o2::track::TrackParCov& trc, o2::track::TrackLTIntegral* lti = nullptr); + void addLastTrackCloneForNeighbourSector(int sector, o2::track::TrackLTIntegral* trackLTInt = nullptr); ///------------------- manipulations with matches records ---------------------- bool registerMatchRecordTPC(int iITS, int iTPC, float chi2, int candIC = MinusOne); @@ -575,7 +578,7 @@ class MatchTPCITS float YMaxAtXMatchingRef = 999.; ///< max Y in the sector at reference X - float mSectEdgeMargin2 = 0.; ///< crude check if ITS track should be matched also in neighbouring sector + float mSectEdgeMargin = 0.; ///< crude check if ITS track should be matched also in neighbouring sector ///< safety margin in TPC time bins when estimating TPC track tMin and tMax from ///< assigned time0 and its track Z position (converted from mTPCTimeEdgeZSafeMargin) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h index a9d382cdbf18f..3ec189deff54b 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITSParams.h @@ -41,6 +41,8 @@ struct MatchTPCITSParams : public o2::conf::ConfigurableParamHelperfillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2GRot) | o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L)); - mSectEdgeMargin2 = mParams->crudeAbsDiffCut[o2::track::kY] * mParams->crudeAbsDiffCut[o2::track::kY]; ///< precalculated ^2 + mSectEdgeMargin = mParams->crudeAbsDiffCut[o2::track::kY] / std::sqrt(Cos70I2); #ifdef _ALLOW_DEBUG_TREES_ // debug streamer @@ -446,7 +446,6 @@ void MatchTPCITS::addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float if (mMCTruthON) { mTPCLblWork.emplace_back(mTPCTrkLabels[tpcID]); } - // cache work track index mTPCSectIndexCache[o2::math_utils::angle2Sector(trc.getAlpha())].push_back(mTPCWork.size() - 1); } @@ -638,6 +637,8 @@ bool MatchTPCITS::prepareITSData() } long nHBF = o2::base::GRPGeomHelper::getNHBFPerTF(); long maxBCs = nHBF * long(o2::constants::lhc::LHCMaxBunches); + o2::track::TrackLTIntegral trackLTInt; + trackLTInt.setTimeNotNeeded(); for (int irof = 0; irof < nROFs; irof++) { const auto& rofRec = mITSTrackROFRec[irof]; @@ -685,10 +686,14 @@ bool MatchTPCITS::prepareITSData() continue; } // make sure the track is at the ref. radius - if (!propagateToRefX(trc)) { + trackLTInt.clearFast(); + if (!propagateToRefX(trc, &trackLTInt)) { mITSWork.pop_back(); // discard failed track continue; // add to cache only those ITS tracks which reached ref.X and have reasonable snp } + trc.xrho = trackLTInt.getXRho(); // we collect seen x*rho and distance to the reference X for further PID correcrions + trc.dL = trackLTInt.getL(); + if (mMCTruthON) { mITSLblWork.emplace_back(mITSTrkLabels[it]); } @@ -702,19 +707,16 @@ bool MatchTPCITS::prepareITSData() // when propagated to Xr (in this neighbouring sector) and the edge will be (neglecting the curvature) // [(Xr*tg(10)-Yr)/(tgPhir+tg70)]^2 / cos(70)^2 // for the next sector // [(Xr*tg(10)+Yr)/(tgPhir-tg70)]^2 / cos(70)^2 // for the prev sector - // Distances to the sector edges in neighbourings sectors (at Xref in theit proper frames) + // Distances to the sector edges in neighbourings sectors (at Xref in their proper frames) float trcY = trc.getY(), tgp = trc.getSnp(); tgp /= std::sqrt((1.f - tgp) * (1.f + tgp)); // tan of track direction XY - // sector up - float dy2Up = (YMaxAtXMatchingRef - trcY) / (tgp + Tan70); - if ((dy2Up * dy2Up * Cos70I2) < mSectEdgeMargin2) { // need to check this track for matching in sector up - addLastTrackCloneForNeighbourSector(sector < (o2::constants::math::NSectors - 1) ? sector + 1 : 0); - } - // sector down - float dy2Dn = (YMaxAtXMatchingRef + trcY) / (tgp - Tan70); - if ((dy2Dn * dy2Dn * Cos70I2) < mSectEdgeMargin2) { // need to check this track for matching in sector down - addLastTrackCloneForNeighbourSector(sector > 1 ? sector - 1 : o2::constants::math::NSectors - 1); + float dyUpDn[2] = {std::abs((YMaxAtXMatchingRef - trcY) / (tgp + Tan70)), std::abs((YMaxAtXMatchingRef + trcY) / (tgp - Tan70))}; // sector up, down edge distances + // we do the cloning for closest edge only + int sel = dyUpDn[0] < dyUpDn[1] ? 0 : 1; + if (dyUpDn[sel] < mSectEdgeMargin) { // need to check this track for matching in sector up or down + int sectNeib = sel == 0 ? (sector < (o2::constants::math::NSectors - 1) ? sector + 1 : 0) : (sector > 1 ? sector - 1 : o2::constants::math::NSectors - 1); + addLastTrackCloneForNeighbourSector(sectNeib, &trackLTInt); } } } @@ -1014,7 +1016,7 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2, int can } //______________________________________________ -void MatchTPCITS::registerMatchRecordITS(int iITS, int iTPC, float chi2, int candIC) +void MatchTPCITS::registerMatchRecordITS(const int iITS, int iTPC, float chi2, int candIC) { ///< register TPC match in ITS tracks match records, ordering them in quality auto& tITS = mITSWork[iITS]; @@ -1068,7 +1070,26 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kTgl], RejectOnTgl + NSigmaShift))) { return rejFlag; } - diff = tITS.getParam(o2::track::kY) - tTPC.getParam(o2::track::kY); + // do we need to account for different PID hypotheses used for ITS and TPC tracks propagation to ref. X? + bool testOtherPID = false; + float itsParam[5] = {tITS.getY(), tITS.getZ(), tITS.getSnp(), tITS.getTgl(), tITS.getQ2Pt()}; + if (tTPC.getPID() > tITS.getPID() && tITS.dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->minBetaGammaForPIDDiff) { + o2::track::TrackPar tPID(mITSTracksArray[tITS.sourceID].getParamOut()); // clone original ITS track at highest update point + tPID.setPID(tTPC.getPID(), true); + if (!tPID.correctForELoss(tITS.xrho)) { + return RejectoOnPIDCorr; + } + float dCurv = (tPID.getQ2Pt() - tITS.getQ2Pt()) * mBz * o2::constants::math::B2C, dLEff = tITS.dL * mParams->ITSStepEffFraction, dCurvL = dCurv * dLEff; + itsParam[o2::track::kQ2Pt] = tPID.getQ2Pt(); + itsParam[o2::track::kSnp] += dCurvL; + if (std::abs(itsParam[o2::track::kSnp]) >= 1.) { + itsParam[o2::track::kSnp] = std::copysign(0.99, itsParam[o2::track::kSnp]); + } + itsParam[o2::track::kY] += dCurvL * dLEff * 0.5; + testOtherPID = true; + } + + diff = itsParam[o2::track::kY] - tTPC.getParam(o2::track::kY); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kY], RejectOnY))) { return rejFlag; } @@ -1078,7 +1099,7 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& } if (tTPC.constraint == TrackLocTPC::Constrained) { // in continuous only constrained tracks can be compared in Z - diff = tITS.getParam(o2::track::kZ) - tTPC.getParam(o2::track::kZ); + diff = itsParam[o2::track::kZ] - tTPC.getParam(o2::track::kZ); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kZ], RejectOnZ))) { return rejFlag; } @@ -1088,7 +1109,7 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& } } - diff = tITS.getParam(o2::track::kSnp) - tTPC.getParam(o2::track::kSnp); + diff = itsParam[o2::track::kSnp] - tTPC.getParam(o2::track::kSnp); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kSnp], RejectOnSnp))) { return rejFlag; } @@ -1097,7 +1118,7 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& return rejFlag; } - diff = tITS.getParam(o2::track::kQ2Pt) - tTPC.getParam(o2::track::kQ2Pt); + diff = itsParam[o2::track::kQ2Pt] - tTPC.getParam(o2::track::kQ2Pt); if ((rejFlag = roughCheckDif(diff, mParams->crudeAbsDiffCut[o2::track::kQ2Pt], RejectOnQ2Pt))) { return rejFlag; } @@ -1105,9 +1126,18 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC& if ((rejFlag = roughCheckDif(diff, mParams->crudeNSigma2Cut[o2::track::kQ2Pt], RejectOnQ2Pt + NSigmaShift))) { return rejFlag; } - // calculate mutual chi2 excluding Z in continuos mode - chi2 = getPredictedChi2NoZ(tITS, tTPC); - if (chi2 > mParams->cutMatchingChi2 || chi2 < 0.) { // sometime due to the numerical stability the chi2 is negative, reject it. + // calculate mutual chi2 excluding Z in continuous mode + if (testOtherPID) { // temporarily substitute pion params by alternative ones + auto tITSAlt = tITS; + tITSAlt.setPID(tTPC.getPID()); + tITSAlt.setParam(itsParam[o2::track::kY], o2::track::kY); + tITSAlt.setParam(itsParam[o2::track::kSnp], o2::track::kSnp); + tITSAlt.setParam(itsParam[o2::track::kQ2Pt], o2::track::kQ2Pt); + chi2 = getPredictedChi2NoZ(tITSAlt, tTPC); + } else { + chi2 = getPredictedChi2NoZ(tITS, tTPC); + } + if (chi2 > mParams->cutMatchingChi2 || chi2 < 0.) { // sometimes due to the numerical stability the chi2 is negative, reject it. return RejectOnChi2; } @@ -1206,7 +1236,7 @@ float MatchTPCITS::getPredictedChi2NoZ(const o2::track::TrackParCov& trITS, cons } //______________________________________________ -void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) +void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector, o2::track::TrackLTIntegral* trackLTInt) { // add clone of the src ITS track cache, propagate it to ref.X in requested sector // and register its index in the sector cache. Used for ITS tracks which are so close @@ -1214,11 +1244,15 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) mITSWork.push_back(mITSWork.back()); // clone the last track defined in given sector auto& trc = mITSWork.back(); if (trc.rotate(o2::math_utils::sector2Angle(sector)) && - o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, mParams->XMatchingRef, MaxSnp, 2., MatCorrType::USEMatCorrNONE)) { + o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, mParams->XMatchingRef, MaxSnp, 2., mUseMatCorrFlag, trackLTInt)) { // TODO: use faster prop here, no 3d field, materials mITSSectIndexCache[sector].push_back(mITSWork.size() - 1); // register track CLONE // flag clone mITSWork.back().setCloneBefore(); + if (trackLTInt) { + mITSWork.back().xrho = trackLTInt->getXRho(); // we collect seen x*rho and distance to the reference X for further PID correcrions + mITSWork.back().dL = trackLTInt->getL(); + } mITSWork[mITSWork.size() - 2].setCloneAfter(); if (mMCTruthON) { mITSLblWork.emplace_back(mITSTrkLabels[trc.sourceID]); @@ -1229,7 +1263,7 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector) } //______________________________________________ -bool MatchTPCITS::propagateToRefX(o2::track::TrackParCov& trc) +bool MatchTPCITS::propagateToRefX(o2::track::TrackParCov& trc, o2::track::TrackLTIntegral* lti) { // propagate track to matching reference X, making sure its assigned alpha // is consistent with TPC sector @@ -1237,7 +1271,7 @@ bool MatchTPCITS::propagateToRefX(o2::track::TrackParCov& trc) bool refReached = false; refReached = mParams->XMatchingRef < 10.; // RS: tmp, to cover XMatchingRef~0 int trialsLeft = 2; - while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, mParams->XMatchingRef, MaxSnp, 2., mUseMatCorrFlag)) { + while (o2::base::Propagator::Instance()->PropagateToXBxByBz(trc, mParams->XMatchingRef, MaxSnp, 2., mUseMatCorrFlag, lti)) { if (refReached) { break; } @@ -1422,10 +1456,30 @@ bool MatchTPCITS::refitTrackTPCITS(int iTPC, int& iITS, pmr::vector tITS.getPID() && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->minBetaGammaForPIDDiff) { + // in case the TPC track hypothesis is not pion, we redo the outward propagation to ref.x with TPC PID + tracOut = mITSTracksArray[tITS.sourceID].getParamOut(); + tracOut.setPID(tTPC.getPID(), true); + if (!tracOut.rotate(tTPC.getAlpha()) || !o2::base::Propagator::Instance()->PropagateToXBxByBz(tracOut, mParams->XMatchingRef, MaxSnp, 2., mUseMatCorrFlag)) { + LOGP(debug, "Failed to rotate ITSouter with imposed PID to TPC alpha {} or propagate to X={}: {:s}", tTPC.getAlpha(), mParams->XMatchingRef, tracOut.asString()); + matchedTracks.pop_back(); // destroy failed track + return false; + } +#ifdef _ALLOW_DEBUG_TREES_ + if (mDBGOut) { + itsRefAltPID = tracOut; + } +#endif + } { float xtogo = 0; if (!tracOut.getXatLabR(o2::constants::geom::XTPCInnerRef, xtogo, mBz, o2::track::DirOutward) || @@ -1510,14 +1564,36 @@ bool MatchTPCITS::refitTrackTPCITS(int iTPC, int& iITS, pmr::vector tITS.getPID() && tITS.dL > 0.f && tTPC.getP2() / tTPC.getPID().getMass2() < mParams->minBetaGammaForPIDDiff) { + itsRefPIDCorr = mITSTracksArray[tITS.sourceID].getParamOut(); // clone original ITS track at highest update point + itsRefPIDCorr.setPID(tTPC.getPID(), true); + if (!itsRefPIDCorr.correctForELoss(tITS.xrho)) { + itsRefPIDCorr.setX(-10); + } else { + float q2ptPID = itsRefPIDCorr.getQ2Pt(); + float dCurv = (q2ptPID - tITS.getQ2Pt()) * mBz * o2::constants::math::B2C, dLEff = tITS.dL * mParams->ITSStepEffFraction, dCurvL = dCurv * dLEff; + itsRefPIDCorr = tITS; + itsRefPIDCorr.setPID(tTPC.getPID(), true); + itsRefPIDCorr.setQ2Pt(q2ptPID); + auto snp = tITS.getSnp() + dCurvL; + if (std::abs(snp) >= 1.) { + snp = std::copysign(0.99, snp); + } + itsRefPIDCorr.setSnp(snp); + itsRefPIDCorr.setY(tITS.getY() + dCurvL * dLEff * 0.5); + } + } (*mDBGOut) << "refit" - << "tpcOrig=" << mTPCTracksArray[tTPC.sourceID] << "itsOrig=" << itsTrOrig << "itsRef=" << tITS << "tpcRef=" << tTPC << "matchRefit=" << trfit << "timeCorr=" << timeC << "dTimeFT0=" << minDiffFT0 << "dTimes=" << dtimes; + << "tpcOrig=" << mTPCTracksArray[tTPC.sourceID] << "itsOrig=" << itsTrOrig << "itsRef=" << tITS << "tpcRef=" << tTPC << "matchRefit=" << trfit << "timeCorr=" << timeC << "dTimeFT0=" << minDiffFT0 << "dTimes=" << dtimes + << "itsRefAltPID=" << itsRefAltPID << "itsRefPIDCorr=" << itsRefPIDCorr; if (mMCTruthON) { (*mDBGOut) << "refit" << "itsLbl=" << mITSLblWork[iITS] << "tpcLbl=" << mTPCLblWork[iTPC]; } (*mDBGOut) << "refit" - << "\n"; + << "tf=" << mTFCount << "\n"; } #endif From 8482d12b674b52c5010f1c369e86e8ad1268ae52 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 7 Feb 2024 10:59:39 +0100 Subject: [PATCH 04/50] Restore eloss contribution to C14 in PCCompressionTrackModel --- GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index 1939a58f64a1e..fba36a69d10b4 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -840,7 +840,7 @@ GPUd() void GPUTPCCompressionTrackModel::calculateMaterialCorrection() // Approximate energy loss fluctuation (M.Ivanov) - const float knst = 0.0007f; // To be tuned. + const float knst = 0.07f; // To be tuned. mMaterial.sigmadE2 = knst * mMaterial.EP2 * qpt; mMaterial.sigmadE2 = mMaterial.sigmadE2 * mMaterial.sigmadE2; From a919d1fbbb08cd0baeb667eaed67fb2373bbf134 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 7 Feb 2024 08:54:50 +0100 Subject: [PATCH 05/50] DPL Analysis: avoid extra cursorHelper methods --- .../Core/include/Framework/TableBuilder.h | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index 2b19b43785d70..7de45f58d2e62 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -795,13 +795,17 @@ class TableBuilder template auto cursor() { - return cursorHelper(typename T::table_t::persistent_columns_t{}); + return [this](pack) { + return this->template persist({Cs::columnLabel()...}); + }(typename T::table_t::persistent_columns_t{}); } template auto cursor() { - return cursorHelper2(typename T::table_t::persistent_columns_t{}); + return [this](pack) { + return this->template persist({Cs::columnLabel()...}); + }(typename T::table_t::persistent_columns_t{}); } template @@ -861,21 +865,6 @@ class TableBuilder std::shared_ptr finalize(); private: - /// Helper which actually creates the insertion cursor. Notice that the - /// template argument T is a o2::soa::Table which contains only the - /// persistent columns. - template - auto cursorHelper(framework::pack) - { - return this->template persist({Cs::columnLabel()...}); - } - - template - auto cursorHelper2(framework::pack) - { - return this->template persist({Cs::columnLabel()...}); - } - bool (*mFinalizer)(std::vector>& arrays, void* holders); void (*mDestructor)(void* holders); void* mHolders; From 1c7eb18b1d730fd1ce7fa8a9919c4127d5de2dfe Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Wed, 7 Feb 2024 14:38:25 +0100 Subject: [PATCH 06/50] DPL Analysis: make BindingNodes constexpr (#12661) --- Framework/Core/include/Framework/ASoA.h | 327 +++++++++--------- .../Core/include/Framework/AnalysisTask.h | 12 +- .../Core/include/Framework/Expressions.h | 21 +- .../include/Framework/GroupedCombinations.h | 3 +- .../Core/include/Framework/StringHelpers.h | 6 - Framework/Core/src/Expressions.cxx | 4 +- .../include/Framework/TypeIdHelpers.h | 47 ++- 7 files changed, 219 insertions(+), 201 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 4d07fd124a8fe..57b00a06003ad 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -53,13 +52,13 @@ struct Binding { void bind(T const* table) { ptr = table; - hash = typeHash(); + hash = o2::framework::TypeIdHelpers::uniqueId(); } template T const* get() const { - if (hash == typeHash()) { + if (hash == o2::framework::TypeIdHelpers::uniqueId()) { return static_cast(ptr); } return nullptr; @@ -1386,7 +1385,7 @@ class Table static constexpr auto hashes() { - return std::set{{typeid(C).hash_code()...}}; + return std::set{{o2::framework::TypeIdHelpers::uniqueId()...}}; } template @@ -1886,8 +1885,8 @@ std::tuple getRowData(arrow::Table* table, T rowIterator, return _Getter_(); \ } \ }; \ - static const o2::framework::expressions::BindingNode _Getter_ { _Label_, typeid(_Name_).hash_code(), \ - o2::framework::expressions::selectArrowType<_Type_>() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ + o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_COLUMN(_Name_, _Getter_, _Type_) \ DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_) @@ -1921,41 +1920,41 @@ std::tuple getRowData(arrow::Table* table, T rowIterator, return (*mColumnIterator & (static_cast(1) << bit)) >> bit; \ } \ }; \ - static const o2::framework::expressions::BindingNode _Getter_ { _Label_, typeid(_Name_).hash_code(), \ - o2::framework::expressions::selectArrowType() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ + o2::framework::expressions::selectArrowType() } #define DECLARE_SOA_BITMAP_COLUMN(_Name_, _Getter_, _Size_) \ DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, "f" #_Name_) /// An 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on supplied C++ expression. -#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - static o2::framework::expressions::Projector Projector() \ - { \ - return _Expression_; \ - } \ - }; \ - static const o2::framework::expressions::BindingNode _Getter_ { _Label_, typeid(_Name_).hash_code(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + static o2::framework::expressions::Projector Projector() \ + { \ + return _Expression_; \ + } \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ + o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Expression_) \ DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_, _Expression_); @@ -2215,139 +2214,139 @@ std::tuple getRowData(arrow::Table* table, T rowIterator, #define DECLARE_SOA_ARRAY_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "") /// NORMAL -#define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ - static constexpr const char* mLabel = "fIndex" #_Table_ _Suffix_; \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using binding_t = _Table_; \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ - o2::soa::notBoundTable(#_Table_); \ - } \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - auto _Getter_() const \ - { \ - return _Getter_##_as(); \ - } \ - \ - template \ - bool setCurrent(T* current) \ - { \ - if constexpr (o2::soa::is_binding_compatible_v()) { \ - assert(current != nullptr); \ - this->mBinding.bind(current); \ - return true; \ - } \ - return false; \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - binding_t const* getCurrent() const { return mBinding.get(); } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ - static const o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, typeid(_Name_##Id).hash_code(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ + static constexpr const char* mLabel = "fIndex" #_Table_ _Suffix_; \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using binding_t = _Table_; \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ + o2::soa::notBoundTable(#_Table_); \ + } \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + auto _Getter_() const \ + { \ + return _Getter_##_as(); \ + } \ + \ + template \ + bool setCurrent(T* current) \ + { \ + if constexpr (o2::soa::is_binding_compatible_v()) { \ + assert(current != nullptr); \ + this->mBinding.bind(current); \ + return true; \ + } \ + return false; \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + binding_t const* getCurrent() const { return mBinding.get(); } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, o2::framework::TypeIdHelpers::uniqueId<_Name_##Id>(), \ + o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "") /// SELF -#define DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static constexpr const char* mLabel = "fIndex" _Label_; \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using self_index_t = std::true_type; \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ - static const o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, typeid(_Name_##Id).hash_code(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static constexpr const char* mLabel = "fIndex" _Label_; \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using self_index_t = std::true_type; \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_##Id>(), \ + o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_SELF_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, #_Name_) /// SELF SLICE diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 9809ed0068729..0e570a49c3ccf 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -126,7 +126,7 @@ struct AnalysisDataProcessorBuilder { DataSpecUtils::updateInputList(inputs, std::move(newInput)); } - static void doAppendEnumeration(const char* name, int64_t begin, int64_t end, int64_t step, std::vector& inputs) + static void doAppendEnumeration(const char*, int64_t, int64_t, int64_t, std::vector& inputs) { std::vector inputMetadata; // FIXME: for the moment we do not support begin, end and step. @@ -148,11 +148,11 @@ struct AnalysisDataProcessorBuilder { if constexpr (is_enumeration_v
== false) { if constexpr (soa::is_soa_filtered_v
) { auto fields = createFieldsFromColumns(typename dT::table_t::persistent_columns_t{}); - eInfos.push_back({ai, hash, dT::hashes(), std::make_shared(fields), nullptr}); + eInfos.emplace_back(ai, hash, dT::hashes(), std::make_shared(fields)); } else if constexpr (soa::is_soa_iterator_v
) { auto fields = createFieldsFromColumns(typename dT::parent_t::persistent_columns_t{}); if constexpr (std::is_same_v) { - eInfos.push_back({ai, hash, dT::parent_t::hashes(), std::make_shared(fields), nullptr}); + eInfos.emplace_back(ai, hash, dT::parent_t::hashes(), std::make_shared(fields)); } } doAppendInputWithMetadata(soa::make_originals_from_type
(), name, value, inputs); @@ -189,7 +189,7 @@ struct AnalysisDataProcessorBuilder { static void inputsFromArgs(R (C::*)(Args...), const char* name, bool value, std::vector& inputs, std::vector& eInfos, std::vector& bk, std::vector& bku) { int ai = 0; - auto hash = typeHash(); + auto hash = o2::framework::TypeIdHelpers::uniqueId(); if constexpr (soa::is_soa_iterator_v>>>) { appendGroupingCandidates(bk, bku, framework::pack{}); } @@ -205,7 +205,7 @@ struct AnalysisDataProcessorBuilder { template static auto bindGroupingTable(InputRecord& record, R (C::*)(Grouping, Args...), std::vector& infos) { - auto hash = typeHash(); + auto hash = o2::framework::TypeIdHelpers::uniqueId(); return extractSomethingFromRecord(record, infos, hash); } @@ -291,7 +291,7 @@ struct AnalysisDataProcessorBuilder { static auto bindAssociatedTables(InputRecord& record, R (C::*)(Grouping, Args...), std::vector& infos) { constexpr auto p = pack{}; - auto hash = typeHash(); + auto hash = o2::framework::TypeIdHelpers::uniqueId(); return std::make_tuple(extractSomethingFromRecord(p) + 1>(record, infos, hash)...); } diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index 21c786846ea6c..349549badf0e8 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -50,13 +50,20 @@ using FilterPtr = std::shared_ptr; using atype = arrow::Type; struct ExpressionInfo { + ExpressionInfo(int ai, size_t hash, std::set&& hs, gandiva::SchemaPtr sc) + : argumentIndex(ai), + processHash(hash), + hashes(hs), + schema(sc) + { + } int argumentIndex; size_t processHash; - std::set hashes; + std::set hashes; gandiva::SchemaPtr schema; - gandiva::NodePtr tree; - gandiva::FilterPtr filter; - gandiva::Selection selection; + gandiva::NodePtr tree = nullptr; + gandiva::FilterPtr filter = nullptr; + gandiva::Selection selection = nullptr; bool resetSelection = false; }; @@ -122,9 +129,9 @@ struct LiteralNode { struct BindingNode { BindingNode(BindingNode const&) = default; BindingNode(BindingNode&&) = delete; - BindingNode(std::string const& name_, std::size_t hash_, atype::type type_) : name{name_}, hash{hash_}, type{type_} {} - std::string name; - std::size_t hash; + constexpr BindingNode(const char* name_, uint32_t hash_, atype::type type_) : name{name_}, hash{hash_}, type{type_} {} + const char* name; + uint32_t hash; atype::type type; }; diff --git a/Framework/Core/include/Framework/GroupedCombinations.h b/Framework/Core/include/Framework/GroupedCombinations.h index 5904916613d2e..f88a534cc9727 100644 --- a/Framework/Core/include/Framework/GroupedCombinations.h +++ b/Framework/Core/include/Framework/GroupedCombinations.h @@ -44,8 +44,7 @@ expressions::BindingNode getMatchingIndexNode() using selected_indices_t = selected_pack_multicondition, external_index_columns_pack>; static_assert(pack_size(selected_indices_t{}) == 1, "No matching index column from associated to grouping"); using index_column_t = pack_head_t; - auto label = std::string(index_column_t::mLabel); - return expressions::BindingNode{label, typeid(typename index_column_t::column_t).hash_code(), expressions::selectArrowType()}; + return expressions::BindingNode{index_column_t::mLabel, o2::framework::TypeIdHelpers::uniqueId(), expressions::selectArrowType()}; } template diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index 26d572d934257..5eb5ce0cd88ab 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -163,10 +163,4 @@ constexpr auto get_size(const std::string_view& str) return const_str_details::as_chars(); \ }() -template -constexpr auto typeHash() -{ - return compile_time_hash(typeid(T).name()); -} - #endif // O2_FRAMEWORK_STRINGHELPERS_H diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index b09ddc97cf756..b30bf5049f0d3 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -700,9 +700,9 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, return tree; } -bool isTableCompatible(std::set const& hashes, Operations const& specs) +bool isTableCompatible(std::set const& hashes, Operations const& specs) { - std::set opHashes; + std::set opHashes; for (auto const& spec : specs) { if (spec.left.datum.index() == 3) { opHashes.insert(spec.left.hash); diff --git a/Framework/Foundation/include/Framework/TypeIdHelpers.h b/Framework/Foundation/include/Framework/TypeIdHelpers.h index f08670ea1ed03..82203fad66d7b 100644 --- a/Framework/Foundation/include/Framework/TypeIdHelpers.h +++ b/Framework/Foundation/include/Framework/TypeIdHelpers.h @@ -14,11 +14,12 @@ #include #include +#include #include "Framework/StringHelpers.h" namespace o2::framework { - +#ifdef __CLING__ template struct unique_type_id { static constexpr auto get() noexcept @@ -32,28 +33,33 @@ struct unique_type_id { template inline constexpr auto unique_type_id_v = unique_type_id::value; +#endif -struct TypeIdHelpers { - /// Return a unique id for a given type - /// This works just fine with GCC and CLANG, - /// C++20 will allow us to use: - /// std::source_location::current().function_name(); - template - constexpr static uint32_t uniqueId() - { - constexpr uint32_t r = crc32(unique_type_id_v.data(), unique_type_id_v.size()); - return r; - } -}; +#ifndef __CLING__ +/// Workaround GCC optimizing out unused template parameter +template +consteval static std::string_view type_name_impl(T*) +{ + return std::source_location::current().function_name(); +} +#endif /// Return pure type name with no namespaces etc. -/// Works fine with GCC and CLANG +/// Works with GCC and CLANG template constexpr static std::string_view type_name() { +#ifdef __CLING__ constexpr std::string_view wrapped_name{unique_type_id_v}; +#else + constexpr std::string_view wrapped_name = type_name_impl(nullptr); +#endif const std::string_view left_marker{"T = "}; +#ifdef __clang__ const std::string_view right_marker{"]"}; +#else + const std::string_view right_marker{";"}; +#endif const auto left_marker_index = wrapped_name.find(left_marker); const auto start_index = left_marker_index + left_marker.size(); const auto end_index = wrapped_name.find(right_marker, left_marker_index); @@ -61,6 +67,19 @@ constexpr static std::string_view type_name() return wrapped_name.substr(start_index, length); } +struct TypeIdHelpers { + template + constexpr static uint32_t uniqueId() + { +#ifdef __CLING__ + constexpr uint32_t r = crc32(unique_type_id_v.data(), unique_type_id_v.size()); + return r; +#else + return compile_time_hash(type_name().data()); +#endif + } +}; + /// Convert a CamelCase task struct name to snake-case task name inline static std::string type_to_task_name(std::string_view& camelCase) { From 29619cc9a4b41340eda03b47d23f3d8d816d8668 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner Date: Wed, 7 Feb 2024 18:51:56 +0100 Subject: [PATCH 07/50] TPC: Fixing timestamp in file name when storing scaler to file --- Detectors/TPC/calibration/src/TPCScaler.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/TPC/calibration/src/TPCScaler.cxx b/Detectors/TPC/calibration/src/TPCScaler.cxx index d387f1d0b74af..75938d3fbfb1b 100644 --- a/Detectors/TPC/calibration/src/TPCScaler.cxx +++ b/Detectors/TPC/calibration/src/TPCScaler.cxx @@ -87,7 +87,7 @@ void TPCScaler::dumpToFileSlices(const char* file, const char* name, int minutes const long tsCCDBStart = mTimeStampMS + i * timePerSliceMS; const long tsCCDBStartMargin = (i == 0) ? (tsCCDBStart - marginCCDBMS) : tsCCDBStart; const long tsCCDBEnd = (i == nSlices - 1) ? (getEndTimeStampMS(o2::tpc::Side::A) + marginCCDBMS) : (tsCCDBStart + timePerSliceMS); - const std::string fileOut = fmt::format("{}_{}_{}_{}.root", file, i, tsCCDBStartMargin, tsCCDBEnd - 1); + const std::string fileOut = fmt::format("{}_{}_{}_{}.root", file, i, tsCCDBStartMargin, tsCCDBEnd); scaler.dumpToFile(fileOut.data(), name); } } From 49fa3103fe318e82d96ed50f6d2947763bf998ac Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Thu, 8 Feb 2024 09:11:30 +0100 Subject: [PATCH 08/50] ALICE3: Add TRK services (#12367) * Add TRK services * Add xX0 scan macro * Please consider the following formatting changes (#70) * Homogenize material naming * Add scan over all materials * Add polyurthane and polyethilene * Start synchronisation with Corrado's work * Finalise three structures for services --------- Co-authored-by: ALICE Builder --- Detectors/Upgrades/ALICE3/CMakeLists.txt | 3 +- .../ALICE3/FCT/simulation/src/Detector.cxx | 8 +- .../ALICE3/FCT/simulation/src/FCTLayer.cxx | 4 +- .../include/FT3Simulation/Detector.h | 1 + .../ALICE3/FT3/simulation/src/Detector.cxx | 134 ++++-- .../ALICE3/FT3/simulation/src/FT3Layer.cxx | 8 +- .../ALICE3/IOTOF/simulation/src/Detector.cxx | 4 +- .../ALICE3/IOTOF/simulation/src/Layer.cxx | 8 +- .../Upgrades/ALICE3/Passive/src/Absorber.cxx | 42 +- .../Upgrades/ALICE3/Passive/src/Magnet.cxx | 20 +- .../Upgrades/ALICE3/Passive/src/Pipe.cxx | 25 +- .../ALICE3/RICH/simulation/src/Detector.cxx | 4 +- .../ALICE3/RICH/simulation/src/RICHRing.cxx | 2 +- .../ALICE3/TRK/simulation/CMakeLists.txt | 1 + .../include/TRKSimulation/TRKServices.h | 45 +- .../ALICE3/TRK/simulation/src/Detector.cxx | 10 +- .../ALICE3/TRK/simulation/src/TRKLayer.cxx | 2 +- .../ALICE3/TRK/simulation/src/TRKServices.cxx | 350 +++++++++++++++- .../Upgrades/ALICE3/macros/CMakeLists.txt | 13 + Detectors/Upgrades/ALICE3/macros/scanXX0.C | 395 ++++++++++++++++++ 20 files changed, 953 insertions(+), 126 deletions(-) create mode 100644 Detectors/Upgrades/ALICE3/macros/CMakeLists.txt create mode 100644 Detectors/Upgrades/ALICE3/macros/scanXX0.C diff --git a/Detectors/Upgrades/ALICE3/CMakeLists.txt b/Detectors/Upgrades/ALICE3/CMakeLists.txt index c8cd09d5c1b1a..8330005c3b2e7 100644 --- a/Detectors/Upgrades/ALICE3/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/CMakeLists.txt @@ -15,4 +15,5 @@ add_subdirectory(FT3) add_subdirectory(FCT) add_subdirectory(AOD) add_subdirectory(IOTOF) -add_subdirectory(RICH) \ No newline at end of file +add_subdirectory(RICH) +add_subdirectory(macros) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx index d227e9f58d4c5..f5d5255be1c0c 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx @@ -434,12 +434,12 @@ void Detector::createMaterials() o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir); // Add Silicon - o2::base::Detector::Material(3, "SI$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); - o2::base::Detector::Medium(3, "SI$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); + o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); // Add Lead (copied from EMCAL) - o2::base::Detector::Material(2, "Pb$", 207.2, 82, 11.35, 0.56, 0.); - o2::base::Detector::Medium(2, "Pb$", 2, 0, ifield, fieldm, tmaxfdPb, stemaxPb, deemaxPb, epsilPb, stminPb); + o2::base::Detector::Material(2, "LEAD$", 207.2, 82, 11.35, 0.56, 18.5); + o2::base::Detector::Medium(2, "LEAD$", 2, 0, ifield, fieldm, tmaxfdPb, stemaxPb, deemaxPb, epsilPb, stminPb); } //_________________________________________________________________________________________________ diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx index 9448d353b4ec9..a0d1896c42266 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx @@ -95,7 +95,7 @@ void FCTLayer::createDiskLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("FCT_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("FCT_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("FCT_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); @@ -175,7 +175,7 @@ void FCTLayer::createConverterLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2); - TGeoMedium* medPb = gGeoManager->GetMedium("FCT_Pb$"); + TGeoMedium* medPb = gGeoManager->GetMedium("FCT_LEAD$"); TGeoMedium* medAir = gGeoManager->GetMedium("FCT_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medPb); diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h b/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h index 1fbcd02272d30..ec735a66f4390 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h @@ -114,6 +114,7 @@ class Detector : public o2::base::DetImpl void buildBasicFT3(const FT3BaseParam& param); void buildFT3V1(); void buildFT3V3b(); + void buildFT3Scoping(); void buildFT3FromFile(std::string); GeometryTGeo* mGeometryTGeo; //! access to geometry details diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx index 7c1691a9b0124..888be687b9f0f 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx @@ -65,7 +65,7 @@ void Detector::buildFT3FromFile(std::string configFileName) // This simple file reader is not failproof. Do not add empty lines! /* - # Sample MFT configuration + # Sample FT3 configuration # z_layer r_in r_out Layerx2X0 -45.3 2.5 9.26 0.0042 -46.7 2.5 9.26 0.0042 @@ -160,15 +160,15 @@ void Detector::buildBasicFT3(const FT3BaseParam& param) mLayerID.clear(); mLayers.resize(2); - for (Int_t direction : {0, 1}) { - for (Int_t layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) { + for (int direction : {0, 1}) { + for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) { std::string layerName = GeometryTGeo::getFT3LayerPattern() + std::to_string(layerNumber + mNumberOfLayers * direction); mLayerName[direction][layerNumber] = layerName; // Adds evenly spaced layers - Float_t layerZ = z_first + (layerNumber * z_length / (mNumberOfLayers - 1)) * std::copysign(1, z_first); - Float_t rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn)))); - Float_t rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut)))); + float layerZ = z_first + (layerNumber * z_length / (mNumberOfLayers - 1)) * std::copysign(1, z_first); + float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn)))); + float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut)))); auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0); } } @@ -183,9 +183,9 @@ void Detector::buildFT3V1() LOG(info) << "Building FT3 Detector: V1"; mNumberOfLayers = 10; - Float_t sensorThickness = 30.e-4; - Float_t layersx2X0 = 1.e-2; - std::vector> layersConfig{ + float sensorThickness = 30.e-4; + float layersx2X0 = 1.e-2; + std::vector> layersConfig{ {26., .5, 3., 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} {30., .5, 3., 0.1f * layersx2X0}, {34., .5, 3., 0.1f * layersx2X0}, @@ -230,9 +230,9 @@ void Detector::buildFT3V3b() LOG(info) << "Building FT3 Detector: V3b"; mNumberOfLayers = 12; - Float_t sensorThickness = 30.e-4; - Float_t layersx2X0 = 1.e-2; - std::vector> layersConfig{ + float sensorThickness = 30.e-4; + float layersx2X0 = 1.e-2; + std::vector> layersConfig{ {26., .5, 3., 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} {30., .5, 3., 0.1f * layersx2X0}, {34., .5, 3., 0.1f * layersx2X0}, @@ -271,7 +271,55 @@ void Detector::buildFT3V3b() } //_________________________________________________________________________________________________ -Detector::Detector(Bool_t active) +void Detector::buildFT3Scoping() +{ + // Build FT3 detector according to the scoping document + + LOG(info) << "Building FT3 Detector: Scoping document version"; + + mNumberOfLayers = 12; + float sensorThickness = 30.e-4; + float layersx2X0 = 1.e-2; + std::vector> layersConfig{ + {26., .5, 2.5, 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} + {30., .5, 2.5, 0.1f * layersx2X0}, + {34., .5, 2.5, 0.1f * layersx2X0}, + {77., 5.0, 35., layersx2X0}, + {100., 5.0, 35., layersx2X0}, + {122., 5.0, 35., layersx2X0}, + {150., 5.0, 68.f, layersx2X0}, + {180., 5.0, 68.f, layersx2X0}, + {220., 5.0, 68.f, layersx2X0}, + {260., 5.0, 68.f, layersx2X0}, + {300., 5.0, 68.f, layersx2X0}, + {350., 5.0, 68.f, layersx2X0}}; + + mLayerName.resize(2); + mLayerName[0].resize(mNumberOfLayers); + mLayerName[1].resize(mNumberOfLayers); + mLayerID.clear(); + mLayers.resize(2); + + for (auto direction : {0, 1}) { + for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) { + std::string directionName = std::to_string(direction); + std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber); + mLayerName[direction][layerNumber] = layerName; + auto& z = layersConfig[layerNumber][0]; + + auto& rIn = layersConfig[layerNumber][1]; + auto& rOut = layersConfig[layerNumber][2]; + auto& x0 = layersConfig[layerNumber][3]; + + LOG(info) << "Adding Layer " << layerName << " at z = " << z; + // Add layers + auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0); + } + } +} + +//_________________________________________________________________________________________________ +Detector::Detector(bool active) : o2::base::DetImpl("FT3", active), mTrackData(), mHits(o2::utils::createSimVector()) @@ -287,7 +335,7 @@ Detector::Detector(Bool_t active) } else { switch (ft3BaseParam.geoModel) { case Default: - buildFT3V3b(); // FT3V3b + buildFT3Scoping(); // FT3Scoping break; case Telescope: buildBasicFT3(ft3BaseParam); // BasicFT3 = Parametrized telescopic detector (equidistant layers) @@ -365,14 +413,14 @@ void Detector::InitializeO2Detector() } //_________________________________________________________________________________________________ -Bool_t Detector::ProcessHits(FairVolume* vol) +bool Detector::ProcessHits(FairVolume* vol) { // This method is called from the MC stepping if (!(fMC->TrackCharge())) { return kFALSE; } - Int_t lay = 0, volID = vol->getMCid(); + int lay = 0, volID = vol->getMCid(); while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) { ++lay; } @@ -443,33 +491,33 @@ Bool_t Detector::ProcessHits(FairVolume* vol) //_________________________________________________________________________________________________ void Detector::createMaterials() { - Int_t ifield = 2; - Float_t fieldm = 10.0; + int ifield = 2; + float fieldm = 10.0; o2::base::Detector::initFieldTrackingParams(ifield, fieldm); - Float_t tmaxfdSi = 0.1; // .10000E+01; // Degree - Float_t stemaxSi = 0.0075; // .10000E+01; // cm - Float_t deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.)); } else { // If beampipe is enabled append inner disks to beampipe filling volume, this should be temporary. - for (Int_t direction : {0, 1}) { + for (int direction : {0, 1}) { std::string directionString = direction ? "Forward" : "Backward"; LOG(info) << "Creating FT3 " << directionString << " layers:"; - for (Int_t iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) { + for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) { if (iLayer < 3) { mLayers[direction][iLayer].createLayer(volIFT3); } else { @@ -569,7 +617,7 @@ void Detector::createGeometry() if (mLayers.size() == 1) { // All layers registered at mLayers[0], used when building from file LOG(info) << "Creating FT3 layers:"; if (A3IPvac) { - for (Int_t iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { + for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { if (std::abs(mLayers[0][iLayer].getZ()) < 25) { mLayers[0][iLayer].createLayer(volIFT3); } else { @@ -579,7 +627,7 @@ void Detector::createGeometry() A3IPvac->AddNode(volIFT3, 2, new TGeoTranslation(0., 0., 0.)); vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.)); } else { - for (Int_t iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { + for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { mLayers[0][iLayer].createLayer(volFT3); } vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.)); @@ -604,8 +652,8 @@ void Detector::defineSensitiveVolumes() // The names of the FT3 sensitive volumes have the format: FT3Sensor_(0,1)_(0...sNumberLayers-1) if (mLayers.size() == 2) { - for (Int_t direction : {0, 1}) { - for (Int_t iLayer = 0; iLayer < mNumberOfLayers; iLayer++) { + for (int direction : {0, 1}) { + for (int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) { volumeName = o2::ft3::GeometryTGeo::getFT3SensorPattern() + std::to_string(iLayer); v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), direction, iLayer)); LOG(info) << "Adding FT3 Sensitive Volume => " << v->GetName(); @@ -615,7 +663,7 @@ void Detector::defineSensitiveVolumes() } if (mLayers.size() == 1) { - for (Int_t iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { + for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { volumeName = o2::ft3::GeometryTGeo::getFT3SensorPattern() + std::to_string(iLayer); v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), 0, iLayer)); LOG(info) << "Adding FT3 Sensitive Volume => " << v->GetName(); diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/src/FT3Layer.cxx b/Detectors/Upgrades/ALICE3/FT3/simulation/src/FT3Layer.cxx index 064bfc2efd679..317dcd8c60aee 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/src/FT3Layer.cxx +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/src/FT3Layer.cxx @@ -70,15 +70,15 @@ void FT3Layer::createLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mChipThickness / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("FT3_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("FT3_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); - sensVol->SetLineColor(kBlue - 4); + sensVol->SetLineColor(kBlue - 7); TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi); - chipVol->SetLineColor(kBlue - 4); + chipVol->SetLineColor(kBlue - 7); TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir); - layerVol->SetLineColor(kBlue - 4); + layerVol->SetLineColor(kBlue - 7); LOG(info) << "Inserting " << sensVol->GetName() << " inside " << chipVol->GetName(); chipVol->AddNode(sensVol, 1, nullptr); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx index fb53d3388e616..f30c1cb4a10c5 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx @@ -103,8 +103,8 @@ void Detector::createMaterials() o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir); o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir); - o2::base::Detector::Material(3, "SI$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); - o2::base::Detector::Medium(3, "SI$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); + o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); } void Detector::createGeometry() diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index a6bfff03a7157..fc1b5f1607232 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -43,7 +43,7 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$"); LOGP(info, "Media: {} {}", (void*)medSi, (void*)medAir); @@ -74,7 +74,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); @@ -103,7 +103,7 @@ void FTOFLayer::createLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); @@ -135,7 +135,7 @@ void BTOFLayer::createLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); diff --git a/Detectors/Upgrades/ALICE3/Passive/src/Absorber.cxx b/Detectors/Upgrades/ALICE3/Passive/src/Absorber.cxx index 7b350c0131100..6226ab2425e34 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/Absorber.cxx +++ b/Detectors/Upgrades/ALICE3/Passive/src/Absorber.cxx @@ -53,16 +53,22 @@ void Alice3Absorber::createMaterials() auto& matmgr = o2::base::MaterialManager::Instance(); // Define materials for muon absorber // - Int_t isxfld = 2.; - Float_t sxmgmx = 10.; + int isxfld = 2.; + float sxmgmx = 10.; o2::base::Detector::initFieldTrackingParams(isxfld, sxmgmx); // // Steel // - Float_t asteel[4] = {55.847, 51.9961, 58.6934, 28.0855}; - Float_t zsteel[4] = {26., 24., 28., 14.}; - Float_t wsteel[4] = {.715, .18, .1, .005}; + float asteel[4] = {55.847, 51.9961, 58.6934, 28.0855}; + float zsteel[4] = {26., 24., 28., 14.}; + float wsteel[4] = {.715, .18, .1, .005}; + + // Iron + float airon[2] = {55.845, 56.}; + float ziron[2] = {26., 26.}; + float wiron[2] = {.923, .077}; + // // Air // @@ -75,7 +81,7 @@ void Alice3Absorber::createMaterials() // **************** // Defines tracking media parameters. // - Float_t epsil, stmin, tmaxfd, deemax, stemax; + float epsil, stmin, tmaxfd, deemax, stemax; epsil = .001; // Tracking precision, stemax = -0.01; // Maximum displacement for multiple scat tmaxfd = -20.; // Maximum angle due to field deflection @@ -84,17 +90,18 @@ void Alice3Absorber::createMaterials() // *************** // - matmgr.Mixture("ALICE3ABSO", 16, "VACUUM0$", aAir, zAir, dAir1, 4, wAir); - matmgr.Medium("ALICE3ABSO", 16, "VA_C0", 16, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + matmgr.Mixture("ALICE3_ABSORBER", 16, "VACUUM$", aAir, zAir, dAir1, 4, wAir); + matmgr.Medium("ALICE3_ABSORBER", 16, "VA_C0", 16, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); // // Steel - matmgr.Mixture("ALICE3ABSO", 19, "STAINLESS STEEL0$", asteel, zsteel, 7.88, 4, wsteel); - matmgr.Mixture("ALICE3ABSO", 39, "STAINLESS STEEL1$", asteel, zsteel, 7.88, 4, wsteel); - matmgr.Mixture("ALICE3ABSO", 59, "STAINLESS STEEL2$", asteel, zsteel, 7.88, 4, wsteel); - matmgr.Medium("ALICE3ABSO", 19, "ST_C0", 19, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("ALICE3ABSO", 39, "ST_C1", 39, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("ALICE3ABSO", 59, "ST_C3", 59, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + // matmgr.Mixture("ALICE3_ABSORBER", 19, "STAINLESS_STEEL$", asteel, zsteel, 7.88, 4, wsteel); + // matmgr.Medium("ALICE3_ABSORBER", 19, "ST_C0", 19, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + + // + // Iron + matmgr.Material("ALICE3_ABSORBER", 26, "IRON$", 55.845, 26., 7.874, 1.757, 17.1); + matmgr.Medium("ALICE3_ABSORBER", 26, "FE", 26, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); } void Alice3Absorber::ConstructGeometry() @@ -112,9 +119,8 @@ void Alice3Absorber::ConstructGeometry() // Media // - auto kMedVac = matmgr.getTGeoMedium("ALICE3ABSO_VA_C0"); - auto kMedSteel = matmgr.getTGeoMedium("ALICE3ABSO_ST_C0"); - auto kMedSteelSh = matmgr.getTGeoMedium("ALICE3ABSO_ST_C3"); + auto kMedVac = matmgr.getTGeoMedium("ALICE3_ABSORBER_VA_C0"); + auto kMedIron = matmgr.getTGeoMedium("ALICE3_ABSORBER_FE"); // The top volume TGeoVolume* top = gGeoManager->GetVolume("cave"); @@ -147,7 +153,7 @@ void Alice3Absorber::ConstructGeometry() // Insert absorings->SetName("absorings"); - TGeoVolume* abso = new TGeoVolume("Absorber", absorings, kMedSteel); + TGeoVolume* abso = new TGeoVolume("Absorber", absorings, kMedIron); abso->SetVisibility(1); abso->SetTransparency(50); diff --git a/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx b/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx index 69c5694851aa7..a44d922dba383 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx +++ b/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx @@ -22,7 +22,7 @@ using namespace o2::passive; Alice3Magnet::~Alice3Magnet() = default; -Alice3Magnet::Alice3Magnet() : Alice3PassiveBase("A3MAG", "") {} +Alice3Magnet::Alice3Magnet() : Alice3PassiveBase("ALICE3_MAGNET", "") {} Alice3Magnet::Alice3Magnet(const char* name, const char* title) : Alice3PassiveBase(name, title) {} Alice3Magnet::Alice3Magnet(const Alice3Magnet& rhs) = default; @@ -77,13 +77,13 @@ void Alice3Magnet::createMaterials() deemax = -.3; // Maximum fractional energy loss, DLS stmin = -.8; - matmgr.Mixture("A3MAG", 1, "VACUUM$ ", aAir, zAir, dAir1, 4, wAir); - matmgr.Material("A3MAG", 9, "Al1$", 26.98, 13., 2.7, 8.9, 37.2); - matmgr.Material("A3MAG", 19, "Cu1$", 63.55, 29., 8.96, 1.6, 18.8); + matmgr.Mixture("ALICE3_MAGNET", 1, "VACUUM$ ", aAir, zAir, dAir1, 4, wAir); + matmgr.Material("ALICE3_MAGNET", 9, "ALUMINIUM$", 26.98, 13., 2.7, 8.9, 37.2); + matmgr.Material("ALICE3_MAGNET", 19, "COPPER$", 63.55, 29., 8.96, 1.436, 15.1); - matmgr.Medium("A3MAG", 1, "VACUUM", 1, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("A3MAG", 9, "ALU_C0", 9, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("A3MAG", 19, "CU_C0", 19, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + matmgr.Medium("ALICE3_MAGNET", 1, "VACUUM", 1, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + matmgr.Medium("ALICE3_MAGNET", 9, "ALUMINIUM", 9, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + matmgr.Medium("ALICE3_MAGNET", 19, "COPPER", 19, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); } void Alice3Magnet::ConstructGeometry() @@ -97,9 +97,9 @@ void Alice3Magnet::ConstructGeometry() } auto& matmgr = o2::base::MaterialManager::Instance(); - auto kMedAl = matmgr.getTGeoMedium("A3MAG_ALU_C0"); - auto kMedCu = matmgr.getTGeoMedium("A3MAG_CU_C0"); - auto kMedVac = matmgr.getTGeoMedium("A3MAG_VACUUM"); + auto kMedAl = matmgr.getTGeoMedium("ALICE3_MAGNET_ALUMINIUM"); + auto kMedCu = matmgr.getTGeoMedium("ALICE3_MAGNET_COPPER"); + auto kMedVac = matmgr.getTGeoMedium("ALICE3_MAGNET_VACUUM"); // inner wrap LOGP(debug, "Alice 3 magnet: creating inner wrap with inner radius {} and thickness {}", mInnerWrapInnerRadius, mInnerWrapThickness); diff --git a/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx b/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx index 93b24c5f36d22..a5bc1d059fde0 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx +++ b/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx @@ -83,11 +83,8 @@ void Alice3Pipe::ConstructGeometry() // Media auto& matmgr = o2::base::MaterialManager::Instance(); - const TGeoMedium* kMedBe = matmgr.getTGeoMedium("ALICE3PIPE_BE"); - const TGeoMedium* kMedVac = matmgr.getTGeoMedium("ALICE3PIPE_VACUUM"); - const TGeoMedium* kMedVacNF = matmgr.getTGeoMedium("ALICE3PIPE_VACUUM_NF"); - const TGeoMedium* kMedVacHC = matmgr.getTGeoMedium("ALICE3PIPE_VACUUM_HC"); - const TGeoMedium* kMedVacNFHC = matmgr.getTGeoMedium("ALICE3PIPE_VACUUM_NFHC"); + const TGeoMedium* kMedBe = matmgr.getTGeoMedium("ALICE3_PIPE_BE"); + const TGeoMedium* kMedVac = matmgr.getTGeoMedium("ALICE3_PIPE_VACUUM"); // Top volume TGeoVolume* top = gGeoManager->GetVolume("cave"); @@ -197,20 +194,14 @@ void Alice3Pipe::createMaterials() auto& matmgr = o2::base::MaterialManager::Instance(); - // Beryllium - matmgr.Material("ALICE3PIPE", 5, "BERILLIUM$", 9.01, 4., 1.848, 35.3, 36.7); - matmgr.Medium("ALICE3PIPE", 5, "BE", 5, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + // Beryllium + matmgr.Material("ALICE3_PIPE", 5, "BERILLIUM$", 9.01, 4., 1.848, 35.3, 36.7); + matmgr.Medium("ALICE3_PIPE", 5, "BE", 5, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - // Vacuum - matmgr.Mixture("ALICE3PIPE", 16, "VACUUM$ ", aAir, zAir, dAir1, 4, wAir); - matmgr.Mixture("ALICE3PIPE", 36, "VACUUM$_NF", aAir, zAir, dAir1, 4, wAir); - matmgr.Mixture("ALICE3PIPE", 56, "VACUUM$_HC ", aAir, zAir, dAir1, 4, wAir); - matmgr.Mixture("ALICE3PIPE", 76, "VACUUM$_NFHC", aAir, zAir, dAir1, 4, wAir); + // Vacuum + matmgr.Mixture("ALICE3_PIPE", 16, "VACUUM$ ", aAir, zAir, dAir1, 4, wAir); - matmgr.Medium("ALICE3PIPE", 16, "VACUUM", 16, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("ALICE3PIPE", 36, "VACUUM_NF", 36, 0, 0, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("ALICE3PIPE", 56, "VACUUM_HC", 56, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); - matmgr.Medium("ALICE3PIPE", 76, "VACUUM_NFHC", 76, 0, 0, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); + matmgr.Medium("ALICE3_PIPE", 16, "VACUUM", 16, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin); } // ---------------------------------------------------------------------------- diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx index ef6761ab88f0b..68789cf5eb357 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx @@ -120,8 +120,8 @@ void Detector::createMaterials() o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir); o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir); - o2::base::Detector::Material(3, "SI$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); - o2::base::Detector::Medium(3, "SI$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); + o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); o2::base::Detector::Mixture(2, "AEROGEL$", aAerogel, zAerogel, dAerogel, 3, wAerogel); o2::base::Detector::Medium(2, "AEROGEL$", 2, 0, ifield, fieldm, tmaxfdAerogel, stemaxAerogel, deemaxAerogel, epsilAerogel, stminAerogel); diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx b/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx index 9843cf12154d4..091e03ec03a6c 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx @@ -49,7 +49,7 @@ Ring::Ring(int rPosId, if (!medAerogel) { LOGP(fatal, "RICH: Aerogel medium not found"); } - TGeoMedium* medSi = gGeoManager->GetMedium("RCH_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("RCH_SILICON$"); if (!medSi) { LOGP(fatal, "RICH: Silicon medium not found"); } diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt index bd39704203713..7706c0e10d778 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(TRKSimulation src/Detector.cxx src/TRKServices.cxx PUBLIC_LINK_LIBRARIES O2::TRKBase + O2::FT3Simulation O2::ITSMFTSimulation) o2_target_root_dictionary(TRKSimulation diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h index 99d2653c19fc2..129fb74d38867 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h @@ -12,6 +12,14 @@ #ifndef O2_TRK_SERVICES_H #define O2_TRK_SERVICES_H +////// Inputs from F. Reidt, 11-2023 +// Material 1 Fraction X_0 (cm) Material 2 Fraction X_0 (cm) +// Fiber SiO2 0,5 12,29 PE 0,5 45 +// Power bundle, no jacket Cu 0,09 1,44 PE 0,91 45 +// Power bundle Cu 0,06 1,44 PE 0,94 45 +// Water bundle PU 0,56 19 H2O 0,44 36,08 +// Water bundle disk PU 0,44 19 H2O 0,56 36,08 + #include #include @@ -22,17 +30,46 @@ namespace trk class TRKServices : public FairModule { + enum class Orientation { kASide = 1, + kCSide = -1 }; + // TRK services overview: three componenets + // + // ================================================== + // ============|| Outer ||============ + // =========|| || Tracker || ||========= + // || ||======================|| || + // || Inner + Middle || + // || Tracker || + // || ||======================|| || + // =========|| || || ||========= ---> createDisksServices + // ============|| ||============ ---> createMiddleBarrelServices + // ================================================== ---> createOuterServices public: TRKServices() = default; TRKServices(float rMin, float zLength, float thickness); void createMaterials(); void createServices(TGeoVolume* motherVolume); + void createColdplate(TGeoVolume* motherVolume); + void createMiddleServices(TGeoVolume* motherVolume); + void createOuterDisksServices(TGeoVolume* motherVolume); + void createOuterBarrelServices(TGeoVolume* motherVolume); protected: - float mRMin; - float mZLength; - float mThickness; - float mX0; + // Coldplate + float mColdPlateRMin; + float mColdPlateZLength; + float mColdPlateThickness; + float mColdPlateX0; + + // Services + float mFiberComposition[2] = {0.5, 0.5}; // SiO2, PE + float mPowerBundleComposition[2] = {0.09, 0.91}; // Cu, PE + float mPowerBundleJacketComposition[2] = {0.06, 0.94}; // Cu, PE + float mWaterBundleComposition[2] = {0.56, 0.44}; // PU, H2O + float mWaterBundleDiskComposition[2] = {0.44, 0.56}; // PU, H2O + float mMiddleDiskThickness = 1.0; // cm + std::vector mCableFanWeights = {0.5, 0.3, 0.2}; // relative weights of the fan layers + ClassDefOverride(TRKServices, 1); }; } // namespace trk diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 0440ebeaa8fe3..5e46e791cf6b9 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -85,9 +85,9 @@ void Detector::configDefault() mLayers.emplace_back(5, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(5)}, 12.f, 124.f, 100.e-3); mLayers.emplace_back(6, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(6)}, 20.f, 124.f, 100.e-3); mLayers.emplace_back(7, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(7)}, 30.f, 124.f, 100.e-3); - mLayers.emplace_back(8, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(8)}, 45.f, 264.f, 100.e-3); - mLayers.emplace_back(9, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(9)}, 60.f, 264.f, 100.e-3); - mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 264.f, 100.e-3); + mLayers.emplace_back(8, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(8)}, 45.f, 258.f, 100.e-3); + mLayers.emplace_back(9, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(9)}, 60.f, 258.f, 100.e-3); + mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3); } void Detector::configFromFile(std::string fileName) @@ -173,8 +173,8 @@ void Detector::createMaterials() o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir); o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir); - o2::base::Detector::Material(3, "SI$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); - o2::base::Detector::Medium(3, "SI$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); + o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03); + o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi); } void Detector::createGeometry() diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx index 4bd639c49c5dc..5e24181bb0fe0 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx @@ -47,7 +47,7 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume) TGeoTube* chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); TGeoTube* layer = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); - TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SI$"); + TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$"); TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$"); TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx index 59fcaf1f512da..99d7bee98f56b 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx @@ -11,9 +11,14 @@ #include #include +#include +#include #include +#include #include +#include #include +#include #include @@ -23,9 +28,9 @@ namespace trk { TRKServices::TRKServices(float rMin, float zLength, float thickness) { - mRMin = rMin; - mZLength = zLength; - mThickness = thickness; + mColdPlateRMin = rMin; + mColdPlateZLength = zLength; + mColdPlateThickness = thickness; } void TRKServices::createMaterials() @@ -48,18 +53,81 @@ void TRKServices::createMaterials() float wCer[2] = {0.5294, 0.4706}; // Mass %, which makes sense. TODO: check if Mixture needs mass% or comp% float dCer = 3.97; - matmgr.Mixture("COLDPLATE", 66, "CERAMIC$", aCer, zCer, dCer, 2, wCer); // Ceramic for cold plate - matmgr.Medium("COLDPLATE", 66, "CER", 66, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); + // Air + float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948}; + float zAir[4] = {6., 7., 8., 18.}; + float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827}; + float dAir = 1.20479E-3; + + // Water + float aWater[2] = {1.00794, 15.9994}; + float zWater[2] = {1., 8.}; + float wWater[2] = {0.111894, 0.888106}; + float dWater = 1.0; + + // Fused silica SiO2 https://pdg.lbl.gov/2023/AtomicNuclearProperties/HTML/silicon_dioxide_fused_quartz.html + float aSiO2[2] = {28.0855, 15.9990}; + float zSiO2[2] = {14., 8.}; + float wSiO2[2] = {0.467, 0.533}; + float dSiO2 = 2.2; + + // Polyethylene from alice 2 absorber + float aPolyethylene[2] = {12.01, 1.}; + float zPolyethylene[2] = {6., 1.}; + float wPolyethylene[2] = {.33, .67}; + + // Polyurethane [HN-CO-O] from alice 2 mft + int nPolyurethane = 4; + float aPolyurethane[4] = {1.00794, 14.010, 12.0107, 15.9994}; + float zPolyurethane[4] = {1.0, 7.0, 6.0, 8.0}; + float wPolyurethane[4] = {0.017077588, 0.237314387, 0.203327619, 0.542280405}; + float dPolyurethane = 1.25; + + matmgr.Mixture("ALICE3_TRKSERVICES", 66, "CERAMIC", aCer, zCer, dCer, 2, wCer); // Ceramic for cold plate + matmgr.Mixture("ALICE3_TRKSERVICES", 68, "AIR", aAir, zAir, dAir, 4, wAir); // Air for placeholding cables + matmgr.Mixture("ALICE3_TRKSERVICES", 69, "POLYETHYLENE", aPolyethylene, zPolyethylene, .95, 2, wPolyethylene); // Polyethylene for fibers + matmgr.Mixture("ALICE3_TRKSERVICES", 70, "POLYURETHANE", aPolyurethane, zPolyurethane, dPolyurethane, nPolyurethane, wPolyurethane); // Polyurethane for cooling pipes + matmgr.Mixture("ALICE3_TRKSERVICES", 71, "SILICONDIOXIDE", aSiO2, zSiO2, dSiO2, 2, wSiO2); // Fused silica SiO2 + matmgr.Mixture("ALICE3_TRKSERVICES", 72, "WATER", aWater, zWater, dWater, 2, wWater); // Water for cooling pipes + matmgr.Material("ALICE3_TRKSERVICES", 67, "COPPER", 63.546, 29, 8.96, 1.43, 15.1); // Copper for cables + + // Danger zone: following mixtures do not use the interface of MaterialManager + // TGeoMixture* fiber = new TGeoMixture("ALICE3_TRKSERVICES_FIBER", 2 /*nel*/); + // fiber->AddElement(gGeoManager->GetMaterial("SILICONDIOXIDE"), 0.5); + // fiber->AddElement(gGeoManager->GetMaterial("POLYETHYLENE"), 0.5); + + // TGeoMixture* powerBundleNoJacket = new TGeoMixture("ALICE3_TRKSERVICES_POWERBUNDLENOJACKET", 2 /*nel*/); + // powerBundleNoJacket->AddElement(gGeoManager->GetMaterial("COPPER"), 0.09); + // powerBundleNoJacket->AddElement(gGeoManager->GetMaterial("POLYETHYLENE"), 0.91); + + // TGeoMixture* coolingBundle = new TGeoMixture("ALICE3_TRKSERVICES_COOLINGBUNDLE", 2 /*nel*/); + // coolingBundle->AddElement(gGeoManager->GetMaterial("POLYURETHANE"), 0.56); + // coolingBundle->AddElement(gGeoManager->GetMaterial("WATER"), 0.44); + + matmgr.Medium("ALICE3_TRKSERVICES", 1, "CERAMIC", 66, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Ceramic for cold plate + matmgr.Medium("ALICE3_TRKSERVICES", 2, "COPPER", 67, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Copper for cables + matmgr.Medium("ALICE3_TRKSERVICES", 3, "AIR", 68, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Air for placeholding cables + matmgr.Medium("ALICE3_TRKSERVICES", 4, "POLYETHYLENE", 69, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Polyethylene for fibers + matmgr.Medium("ALICE3_TRKSERVICES", 5, "POLYURETHANE", 70, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Polyurethane for cooling pipes + matmgr.Medium("ALICE3_TRKSERVICES", 6, "SILICONDIOXIDE", 71, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Fused silica SiO2 + matmgr.Medium("ALICE3_TRKSERVICES", 7, "WATER", 72, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Water for cooling pipes } void TRKServices::createServices(TGeoVolume* motherVolume) { createMaterials(); + createColdplate(motherVolume); + createMiddleServices(motherVolume); + createOuterDisksServices(motherVolume); + createOuterBarrelServices(motherVolume); +} +void TRKServices::createColdplate(TGeoVolume* motherVolume) +{ auto& matmgr = o2::base::MaterialManager::Instance(); - const TGeoMedium* medCeramic = matmgr.getTGeoMedium("COLDPLATE_CER"); + const TGeoMedium* medCeramic = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_CERAMIC"); - TGeoTube* coldPlate = new TGeoTube("TRK_COLDPLATEsh", mRMin, mRMin + mThickness, mZLength / 2.); + TGeoTube* coldPlate = new TGeoTube("TRK_COLDPLATEsh", mColdPlateRMin, mColdPlateRMin + mColdPlateThickness, mColdPlateZLength / 2.); TGeoVolume* coldPlateVolume = new TGeoVolume("TRK_COLDPLATE", coldPlate, medCeramic); coldPlateVolume->SetVisibility(1); coldPlateVolume->SetLineColor(kYellow); @@ -69,6 +137,272 @@ void TRKServices::createServices(TGeoVolume* motherVolume) LOGP(info, "Inserting {} in {} ", coldPlateVolume->GetName(), motherVolume->GetName()); motherVolume->AddNode(coldPlateVolume, 1, nullptr); } -// ClassImp(o2::trk::TRKServices); + +void TRKServices::createOuterDisksServices(TGeoVolume* motherVolume) +{ + // This method hardcoes the pink shape for the inner services + auto& matmgr = o2::base::MaterialManager::Instance(); + + TGeoMedium* medSiO2 = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_SILICONDIOXIDE"); + TGeoMedium* medPE = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_POLYETHYLENE"); + TGeoMedium* medCu = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_COPPER"); + TGeoMedium* medPU = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_POLYURETHANE"); + TGeoMedium* medH2O = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_WATER"); + + for (auto& orientation : {Orientation::kASide, Orientation::kCSide}) { + // Create fibers: 2.12mm + float siO2FiberThick = 0.5 * 0.212; + float peFiberThick = 0.5 * 0.212; + + float rMinInnerServices = 68.5f; // 68.5cm + float zLengthInnerServices = 201.f; // 201cm + float translation = (int)orientation * (149.f + zLengthInnerServices / 2); // ±149cm + + TGeoTube* outerDisksFiberSIO2 = new TGeoTube("TRK_OUTERDISKS_FIBER_SIO2sh", rMinInnerServices, rMinInnerServices + siO2FiberThick, zLengthInnerServices / 2); + TGeoTube* outerDisksFiberPE = new TGeoTube("TRK_OUTERDISKS_FIBER_PEsh", rMinInnerServices + siO2FiberThick, rMinInnerServices + siO2FiberThick + peFiberThick, zLengthInnerServices / 2); + rMinInnerServices += siO2FiberThick + peFiberThick; + TGeoVolume* outerDisksFiberSIO2Volume = new TGeoVolume("TRK_OUTERDISKS_FIBER_SIO2", outerDisksFiberSIO2, medSiO2); + TGeoVolume* outerDisksFiberPEVolume = new TGeoVolume("TRK_OUTERDISKS_FIBER_PE", outerDisksFiberPE, medPE); + outerDisksFiberSIO2Volume->SetLineColor(kPink); + outerDisksFiberPEVolume->SetLineColor(kPink); + auto* combiTrans = new TGeoCombiTrans(0, 0, translation, nullptr); + motherVolume->AddNode(outerDisksFiberSIO2Volume, 1, combiTrans); + motherVolume->AddNode(outerDisksFiberPEVolume, 1, combiTrans); + + // Create power lines: 11.86mm + float cuPowerThick = 0.09 * 1.186; + float pePowerThick = 0.91 * 1.186; + + TGeoTube* outerDisksPowerCu = new TGeoTube("TRK_OUTERDISKS_POWER_CUsh", rMinInnerServices, rMinInnerServices + cuPowerThick, zLengthInnerServices / 2); + TGeoTube* outerDisksPowerPE = new TGeoTube("TRK_OUTERDISKS_POWER_PEsh", rMinInnerServices + cuPowerThick, rMinInnerServices + cuPowerThick + pePowerThick, zLengthInnerServices / 2); + rMinInnerServices += cuPowerThick + pePowerThick; + TGeoVolume* outerDisksPowerCuVolume = new TGeoVolume("TRK_OUTERDISKS_POWER_CU", outerDisksPowerCu, medCu); + TGeoVolume* outerDisksPowerPEVolume = new TGeoVolume("TRK_OUTERDISKS_POWER_PE", outerDisksPowerPE, medPE); + outerDisksPowerCuVolume->SetLineColor(kPink); + outerDisksPowerPEVolume->SetLineColor(kPink); + motherVolume->AddNode(outerDisksPowerCuVolume, 1, combiTrans); + motherVolume->AddNode(outerDisksPowerPEVolume, 1, combiTrans); + + // Create cooling: 6.47mm + float puCoolingThick = 0.56 * 0.647; + float h2oCoolingThick = 0.44 * 0.647; + + TGeoTube* outerDisksCoolingPU = new TGeoTube("TRK_OUTERDISKS_COOLING_PUsh", rMinInnerServices, rMinInnerServices + puCoolingThick, zLengthInnerServices / 2); + TGeoTube* outerDisksCoolingH2O = new TGeoTube("TRK_OUTERDISKS_COOLING_H2Osh", rMinInnerServices + puCoolingThick, rMinInnerServices + puCoolingThick + h2oCoolingThick, zLengthInnerServices / 2); + // rMinInnerServices += puCoolingThick + h2oCoolingThick; + TGeoVolume* outerDisksCoolingPUVolume = new TGeoVolume("TRK_OUTERDISKS_COOLING_PU", outerDisksCoolingPU, medPU); + TGeoVolume* outerDisksCoolingH2OVolume = new TGeoVolume("TRK_OUTERDISKS_COOLING_H2O", outerDisksCoolingH2O, medH2O); + outerDisksCoolingPUVolume->SetLineColor(kPink); + outerDisksCoolingH2OVolume->SetLineColor(kPink); + motherVolume->AddNode(outerDisksCoolingPUVolume, 1, combiTrans); + motherVolume->AddNode(outerDisksCoolingH2OVolume, 1, combiTrans); + } +} + +void TRKServices::createMiddleServices(TGeoVolume* motherVolume) +{ + // This method hardcoes the yellow shape for the middle services + auto& matmgr = o2::base::MaterialManager::Instance(); + + TGeoMedium* medSiO2 = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_SILICONDIOXIDE"); + TGeoMedium* medPE = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_POLYETHYLENE"); + TGeoMedium* medCu = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_COPPER"); + TGeoMedium* medPU = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_POLYURETHANE"); + TGeoMedium* medH2O = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_WATER"); + + // Create fibers: 3.07mm, 50% SiO2, 50% PE + float siO2FiberThick = 0.5 * 0.307; + float peFiberThick = 0.5 * 0.307; + float puCoolingThick = 0.56 * 0.474; + float h2oCoolingThick = 0.44 * 0.474; + float cuPowerThick = 0.09 * 1.09; + float pePowerThick = 0.91 * 1.09; + const float totalThickness = siO2FiberThick + peFiberThick + cuPowerThick + pePowerThick + puCoolingThick + h2oCoolingThick; + + // Get geometry information from TRK which is already present + float rMinMiddleServices = 35.f; // ((TGeoTube*)motherVolume->GetNode(Form("%s7_1", GeometryTGeo::getTRKLayerPattern()))->GetVolume()->GetShape())->GetRmax(); + const float rMinMiddleBarrel = rMinMiddleServices; + const float zLengthMiddleServices = 143.f; // ((TGeoTube*)motherVolume->GetNode(Form("%s7_1", GeometryTGeo::getTRKLayerPattern()))->GetVolume()->GetShape())->GetDz(); + + LOGP(info, "Building service disk for Middle Tracker rminMiddleServices is: {} Dz is {}", rMinMiddleServices, /* rMaxMiddleServices,*/ zLengthMiddleServices + totalThickness); + TGeoTube* middleBarrelFiberSIO2 = new TGeoTube("TRK_MID_FIBER_SIO2sh", rMinMiddleServices, rMinMiddleServices + siO2FiberThick, zLengthMiddleServices + totalThickness); + TGeoTube* middleBarrelFiberPE = new TGeoTube("TRK_MID_FIBER_PEsh", rMinMiddleServices + siO2FiberThick, rMinMiddleServices + siO2FiberThick + peFiberThick, zLengthMiddleServices + totalThickness); + rMinMiddleServices = rMinMiddleServices + siO2FiberThick + peFiberThick; + TGeoVolume* middleBarrelFiberSIO2Volume = new TGeoVolume("TRK_MID_FIBER_SIO2", middleBarrelFiberSIO2, medSiO2); + TGeoVolume* middleBarrelFiberPEVolume = new TGeoVolume("TRK_MID_FIBER_PE", middleBarrelFiberPE, medPE); + middleBarrelFiberSIO2Volume->SetLineColor(kYellow); + middleBarrelFiberPEVolume->SetLineColor(kYellow); + motherVolume->AddNode(middleBarrelFiberSIO2Volume, 1, nullptr); + motherVolume->AddNode(middleBarrelFiberPEVolume, 1, nullptr); + + // Create powerlines: 10.9mm, 9% Cu, 91% PE + TGeoTube* middleBarrelPowerCu = new TGeoTube("TRK_MID_POWER_CUsh", rMinMiddleServices, rMinMiddleServices + cuPowerThick, zLengthMiddleServices + totalThickness); + TGeoTube* middleBarrelPowerPE = new TGeoTube("TRK_MID_POWER_PEsh", rMinMiddleServices + cuPowerThick, rMinMiddleServices + cuPowerThick + pePowerThick, zLengthMiddleServices + totalThickness); + rMinMiddleServices = rMinMiddleServices + cuPowerThick + pePowerThick; + TGeoVolume* middleBarrelPowerCuVolume = new TGeoVolume("TRK_MID_POWER_CU", middleBarrelPowerCu, medCu); + TGeoVolume* middleBarrelPowerPEVolume = new TGeoVolume("TRK_MID_POWER_PE", middleBarrelPowerPE, medPE); + middleBarrelPowerCuVolume->SetLineColor(kYellow); + middleBarrelPowerPEVolume->SetLineColor(kYellow); + motherVolume->AddNode(middleBarrelPowerCuVolume, 1, nullptr); + motherVolume->AddNode(middleBarrelPowerPEVolume, 1, nullptr); + + // Create cooling pipes: 4.74mm, 56% PU, 44% H2O + TGeoTube* middleBarrelCoolingPU = new TGeoTube("TRK_MID_COOLING_PUsh", rMinMiddleServices, rMinMiddleServices + puCoolingThick, zLengthMiddleServices + totalThickness); + TGeoTube* middleBarrelCoolingH2O = new TGeoTube("TRK_MID_COOLING_H2Osh", rMinMiddleServices + puCoolingThick, rMinMiddleServices + puCoolingThick + h2oCoolingThick, zLengthMiddleServices + totalThickness); + rMinMiddleServices = rMinMiddleServices + puCoolingThick + h2oCoolingThick; + TGeoVolume* middleBarrelCoolingPUVolume = new TGeoVolume("TRK_MID_COOLING_PU", middleBarrelCoolingPU, medPU); + TGeoVolume* middleBarrelCoolingH2OVolume = new TGeoVolume("TRK_MID_COOLING_H2O", middleBarrelCoolingH2O, medH2O); + middleBarrelCoolingPUVolume->SetLineColor(kYellow); + middleBarrelCoolingH2OVolume->SetLineColor(kYellow); + motherVolume->AddNode(middleBarrelCoolingPUVolume, 1, nullptr); + motherVolume->AddNode(middleBarrelCoolingH2OVolume, 1, nullptr); + + // Barrel to forward connection disks + float rMaxMiddleServicesBarFwd = 74.5f + siO2FiberThick + peFiberThick + cuPowerThick + pePowerThick + puCoolingThick + h2oCoolingThick; + for (auto& orientation : {Orientation::kASide, Orientation::kCSide}) { + // Create fibers: 3.07mm, 50% SiO2, 50% PE + TGeoTube* middleBarFwdFiberSIO2 = new TGeoTube("TRK_MIDBARFWD_FIBER_SIO2sh", rMinMiddleBarrel, rMaxMiddleServicesBarFwd, siO2FiberThick); + TGeoTube* middleBarFwdFiberPE = new TGeoTube("TRK_MIDBARFWD_FIBER_PEsh", rMinMiddleBarrel, rMaxMiddleServicesBarFwd, peFiberThick); + TGeoVolume* middleBarFwdFiberSIO2Volume = new TGeoVolume("TRK_MIDBARFWD_FIBER_SIO2", middleBarFwdFiberSIO2, medSiO2); + TGeoVolume* middleBarFwdFiberPEVolume = new TGeoVolume("TRK_MIDBARFWD_FIBER_PE", middleBarFwdFiberPE, medPE); + middleBarFwdFiberSIO2Volume->SetLineColor(kYellow); + middleBarFwdFiberPEVolume->SetLineColor(kYellow); + auto* rot = new TGeoRotation("", 0, 0, 180); + auto* combiTransSIO2 = new TGeoCombiTrans(0, 0, (int)orientation * (siO2FiberThick / 2 + zLengthMiddleServices), rot); + auto* combiTransPE = new TGeoCombiTrans(0, 0, (int)orientation * (siO2FiberThick + peFiberThick / 2 + zLengthMiddleServices), rot); + motherVolume->AddNode(middleBarFwdFiberSIO2Volume, 1, combiTransSIO2); + motherVolume->AddNode(middleBarFwdFiberPEVolume, 1, combiTransPE); + + // Create powerlines: 10.9mm, 9% Cu, 91% PE + TGeoTube* middleBarFwdPowerCu = new TGeoTube("TRK_MIDBARFWD_POWER_CUsh", rMinMiddleBarrel, rMaxMiddleServicesBarFwd, cuPowerThick); + TGeoTube* middleBarFwdPowerPE = new TGeoTube("TRK_MIDBARFWD_POWER_PEsh", rMinMiddleBarrel, rMaxMiddleServicesBarFwd, pePowerThick); + TGeoVolume* middleBarFwdPowerCuVolume = new TGeoVolume("TRK_MIDBARFWD_POWER_CU", middleBarFwdPowerCu, medCu); + TGeoVolume* middleBarFwdPowerPEVolume = new TGeoVolume("TRK_MIDBARFWD_POWER_PE", middleBarFwdPowerPE, medPE); + middleBarFwdPowerCuVolume->SetLineColor(kYellow); + middleBarFwdPowerPEVolume->SetLineColor(kYellow); + auto* combiTransCu = new TGeoCombiTrans(0, 0, (int)orientation * (siO2FiberThick + peFiberThick + cuPowerThick / 2 + zLengthMiddleServices), rot); + auto* combiTransPEPower = new TGeoCombiTrans(0, 0, (int)orientation * (siO2FiberThick + peFiberThick + cuPowerThick + pePowerThick / 2 + zLengthMiddleServices), rot); + motherVolume->AddNode(middleBarFwdPowerCuVolume, 1, combiTransCu); + motherVolume->AddNode(middleBarFwdPowerPEVolume, 1, combiTransPEPower); + + // Create cooling pipes: 4.74mm, 56% PU, 44% H2O + TGeoTube* middleBarFwdCoolingPU = new TGeoTube("TRK_MIDBARFWD_COOLING_PUsh", rMinMiddleBarrel, rMaxMiddleServicesBarFwd, puCoolingThick); + TGeoTube* middleBarFwdCoolingH2O = new TGeoTube("TRK_MIDBARFWD_COOLING_H2Osh", rMinMiddleBarrel, rMaxMiddleServicesBarFwd, h2oCoolingThick); + TGeoVolume* middleBarFwdCoolingPUVolume = new TGeoVolume("TRK_MIDBARFWD_COOLING_PU", middleBarFwdCoolingPU, medPU); + TGeoVolume* middleBarFwdCoolingH2OVolume = new TGeoVolume("TRK_MIDBARFWD_COOLING_H2O", middleBarFwdCoolingH2O, medH2O); + middleBarFwdCoolingPUVolume->SetLineColor(kYellow); + middleBarFwdCoolingH2OVolume->SetLineColor(kYellow); + auto* combiTransCoolingPU = new TGeoCombiTrans(0, 0, (int)orientation * (siO2FiberThick + peFiberThick + cuPowerThick + pePowerThick + puCoolingThick / 2 + zLengthMiddleServices), rot); + auto* combiTransCoolingH2O = new TGeoCombiTrans(0, 0, (int)orientation * (siO2FiberThick + peFiberThick + cuPowerThick + pePowerThick + puCoolingThick + h2oCoolingThick / 2 + zLengthMiddleServices), rot); + motherVolume->AddNode(middleBarFwdCoolingPUVolume, 1, combiTransCoolingPU); + motherVolume->AddNode(middleBarFwdCoolingH2OVolume, 1, combiTransCoolingH2O); + } + + // Forward part + const float zLengthMiddleServicesFwd = 350.f - (143.f + totalThickness); + + for (auto& orientation : {Orientation::kASide, Orientation::kCSide}) { + // Create fibers: 3.07mm, 50% SiO2, 50% PE + float siO2FiberThick = 0.5 * 0.307; + float peFiberThick = 0.5 * 0.307; + float rMinMiddleServicesFwd = 74.5f; // 74.5cm + + float translation = (int)orientation * (143.f + totalThickness + zLengthMiddleServicesFwd / 2); + + TGeoTube* middleFwdFiberSIO2 = new TGeoTube("TRK_MIDFWD_FIBER_SIO2sh", rMinMiddleServicesFwd, rMinMiddleServicesFwd + siO2FiberThick, zLengthMiddleServicesFwd / 2); + TGeoTube* middleFwdFiberPE = new TGeoTube("TRK_MIDFWD_FIBER_PEsh", rMinMiddleServicesFwd + siO2FiberThick, rMinMiddleServicesFwd + siO2FiberThick + peFiberThick, zLengthMiddleServicesFwd / 2); + rMinMiddleServicesFwd += siO2FiberThick + peFiberThick; + TGeoVolume* middleFwdFiberSIO2Volume = new TGeoVolume("TRK_MIDFWD_FIBER_SIO2", middleFwdFiberSIO2, medSiO2); + TGeoVolume* middleFwdFiberPEVolume = new TGeoVolume("TRK_MIDFWD_FIBER_PE", middleFwdFiberPE, medPE); + middleFwdFiberSIO2Volume->SetLineColor(kYellow); + middleFwdFiberPEVolume->SetLineColor(kYellow); + auto* combiTrans = new TGeoCombiTrans(0, 0, translation, nullptr); + motherVolume->AddNode(middleFwdFiberSIO2Volume, 1, combiTrans); + motherVolume->AddNode(middleFwdFiberPEVolume, 1, combiTrans); + + // Create powerlines: 10.9mm, 9% Cu, 91% PE + float cuPowerThick = 0.09 * 1.09; + float pePowerThick = 0.91 * 1.09; + + TGeoTube* middleFwdPowerCu = new TGeoTube("TRK_MIDFWD_POWER_CUsh", rMinMiddleServicesFwd, rMinMiddleServicesFwd + cuPowerThick, zLengthMiddleServicesFwd / 2); + TGeoTube* middleFwdPowerPE = new TGeoTube("TRK_MIDFWD_POWER_PEsh", rMinMiddleServicesFwd + cuPowerThick, rMinMiddleServicesFwd + cuPowerThick + pePowerThick, zLengthMiddleServicesFwd / 2); + rMinMiddleServicesFwd += cuPowerThick + pePowerThick; + TGeoVolume* middleFwdPowerCuVolume = new TGeoVolume("TRK_MIDFWD_POWER_CU", middleFwdPowerCu, medCu); + TGeoVolume* middleFwdPowerPEVolume = new TGeoVolume("TRK_MIDFWD_POWER_PE", middleFwdPowerPE, medPE); + middleFwdPowerCuVolume->SetLineColor(kYellow); + middleFwdPowerPEVolume->SetLineColor(kYellow); + motherVolume->AddNode(middleFwdPowerCuVolume, 1, combiTrans); + motherVolume->AddNode(middleFwdPowerPEVolume, 1, combiTrans); + + // Create cooling pipes: 4.74mm, 56% PU, 44% H2O + float puCoolingThick = 0.56 * 0.474; + float h2oCoolingThick = 0.44 * 0.474; + + TGeoTube* middleFwdCoolingPU = new TGeoTube("TRK_MIDFWD_COOLING_PUsh", rMinMiddleServicesFwd, rMinMiddleServicesFwd + puCoolingThick, zLengthMiddleServicesFwd / 2); + TGeoTube* middleFwdCoolingH2O = new TGeoTube("TRK_MIDFWD_COOLING_H2Osh", rMinMiddleServicesFwd + puCoolingThick, rMinMiddleServicesFwd + puCoolingThick + h2oCoolingThick, zLengthMiddleServicesFwd / 2); + // rMinMiddleServicesFwd += puCoolingThick + h2oCoolingThick; + TGeoVolume* middleFwdCoolingPUVolume = new TGeoVolume("TRK_MIDFWD_COOLING_PU", middleFwdCoolingPU, medPU); + TGeoVolume* middleFwdCoolingH2OVolume = new TGeoVolume("TRK_MIDFWD_COOLING_H2O", middleFwdCoolingH2O, medH2O); + middleFwdCoolingPUVolume->SetLineColor(kYellow); + middleFwdCoolingH2OVolume->SetLineColor(kYellow); + motherVolume->AddNode(middleFwdCoolingPUVolume, 1, combiTrans); + motherVolume->AddNode(middleFwdCoolingH2OVolume, 1, combiTrans); + } +} + +void TRKServices::createOuterBarrelServices(TGeoVolume* motherVolume) +{ + auto& matmgr = o2::base::MaterialManager::Instance(); + + TGeoMedium* medSiO2 = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_SILICONDIOXIDE"); + TGeoMedium* medPE = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_POLYETHYLENE"); + TGeoMedium* medCu = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_COPPER"); + TGeoMedium* medPU = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_POLYURETHANE"); + TGeoMedium* medH2O = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_WATER"); + + // Fiber 0.269 cm + const float siO2FiberThick = 0.5 * 0.269; + const float peFiberThick = 0.5 * 0.269; + float rMinOuterBarrelServices = ((TGeoTube*)motherVolume->GetNode(Form("%s10_1", GeometryTGeo::getTRKLayerPattern()))->GetVolume()->GetShape())->GetRmax(); + const float zLengthOuterBarrelServices = 350.f; // 175cm + + TGeoTube* outerBarrelFiberSIO2 = new TGeoTube("TRK_OUTERBARREL_FIBER_SIO2sh", rMinOuterBarrelServices, rMinOuterBarrelServices + siO2FiberThick, zLengthOuterBarrelServices); + TGeoTube* outerBarrelFiberPE = new TGeoTube("TRK_OUTERBARREL_FIBER_PEsh", rMinOuterBarrelServices + siO2FiberThick, rMinOuterBarrelServices + siO2FiberThick + peFiberThick, zLengthOuterBarrelServices); + rMinOuterBarrelServices += siO2FiberThick + peFiberThick; + TGeoVolume* outerBarrelFiberSIO2Volume = new TGeoVolume("TRK_OUTERBARREL_FIBER_SIO2", outerBarrelFiberSIO2, medSiO2); + TGeoVolume* outerBarrelFiberPEVolume = new TGeoVolume("TRK_OUTERBARREL_FIBER_PE", outerBarrelFiberPE, medPE); + outerBarrelFiberSIO2Volume->SetLineColor(kCyan); + outerBarrelFiberPEVolume->SetLineColor(kCyan); + motherVolume->AddNode(outerBarrelFiberSIO2Volume, 1, nullptr); + motherVolume->AddNode(outerBarrelFiberPEVolume, 1, nullptr); + + // Power 0.430 cm + const float cuPowerThick = 0.09 * 0.430; + const float pePowerThick = 0.91 * 0.430; + + TGeoTube* outerBarrelPowerCu = new TGeoTube("TRK_OUTERBARREL_POWER_CUsh", rMinOuterBarrelServices, rMinOuterBarrelServices + cuPowerThick, zLengthOuterBarrelServices); + TGeoTube* outerBarrelPowerPE = new TGeoTube("TRK_OUTERBARREL_POWER_PEsh", rMinOuterBarrelServices + cuPowerThick, rMinOuterBarrelServices + cuPowerThick + pePowerThick, zLengthOuterBarrelServices); + rMinOuterBarrelServices += cuPowerThick + pePowerThick; + TGeoVolume* outerBarrelPowerCuVolume = new TGeoVolume("TRK_OUTERBARREL_POWER_CU", outerBarrelPowerCu, medCu); + TGeoVolume* outerBarrelPowerPEVolume = new TGeoVolume("TRK_OUTERBARREL_POWER_PE", outerBarrelPowerPE, medPE); + outerBarrelPowerCuVolume->SetLineColor(kCyan); + outerBarrelPowerPEVolume->SetLineColor(kCyan); + motherVolume->AddNode(outerBarrelPowerCuVolume, 1, nullptr); + motherVolume->AddNode(outerBarrelPowerPEVolume, 1, nullptr); + + // Cooling 1.432 cm + const float puCoolingThick = 0.56 * 1.432; + const float h2oCoolingThick = 0.44 * 1.432; + + TGeoTube* outerBarrelCoolingPU = new TGeoTube("TRK_OUTERBARREL_COOLING_PUsh", rMinOuterBarrelServices, rMinOuterBarrelServices + puCoolingThick, zLengthOuterBarrelServices); + TGeoTube* outerBarrelCoolingH2O = new TGeoTube("TRK_OUTERBARREL_COOLING_H2Osh", rMinOuterBarrelServices + puCoolingThick, rMinOuterBarrelServices + puCoolingThick + h2oCoolingThick, zLengthOuterBarrelServices); + // rMinOuterBarrelServices += puCoolingThick + h2oCoolingThick; + TGeoVolume* outerBarrelCoolingPUVolume = new TGeoVolume("TRK_OUTERBARREL_COOLING_PU", outerBarrelCoolingPU, medPU); + TGeoVolume* outerBarrelCoolingH2OVolume = new TGeoVolume("TRK_OUTERBARREL_COOLING_H2O", outerBarrelCoolingH2O, medH2O); + outerBarrelCoolingPUVolume->SetLineColor(kCyan); + outerBarrelCoolingH2OVolume->SetLineColor(kCyan); + motherVolume->AddNode(outerBarrelCoolingPUVolume, 1, nullptr); + motherVolume->AddNode(outerBarrelCoolingH2OVolume, 1, nullptr); +} } // namespace trk } // namespace o2 \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/macros/CMakeLists.txt b/Detectors/Upgrades/ALICE3/macros/CMakeLists.txt new file mode 100644 index 0000000000000..4c6f16c9ffca4 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/macros/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2_add_test_root_macro(scanXX0.C + LABELS alice3) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/macros/scanXX0.C b/Detectors/Upgrades/ALICE3/macros/scanXX0.C new file mode 100644 index 0000000000000..2cef4f0fe7dbc --- /dev/null +++ b/Detectors/Upgrades/ALICE3/macros/scanXX0.C @@ -0,0 +1,395 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Original authors: M. Sitta, F. Grosa +// Author: M. Concas + +#if !defined(__CLING__) || defined(__ROOTCLING__) + +#include "DetectorsBase/GeometryManager.h" +#include "ITSBase/GeometryTGeo.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include "FairGeoParSet.h" // for FairGeoParSet +#include // for LOG, LOG_IF + +#include +#include +#include +#endif + +constexpr int nBinsPhiScan = 90; +constexpr int nBinsEtaScan = 200; +constexpr int nBinsZvtxScan = 300; +constexpr float maxEtaScan = 8.; +constexpr int n = 1e4; // testtracks +constexpr float len = 1000; // cm + +void vacuumFormMaterial(TGeoMaterial* mat) +{ + constexpr double kAirA = 14.00674; + constexpr double kAirZ = 7.; + constexpr double kAirDensity = 0.0; // set for vacuum + constexpr double kAirRadLen = std::numeric_limits::max(); + // LOGP(info, "Vacuum forming {} ...", mat->GetName()); + // std::cout << "\t A = " << mat->GetA() << " -> " << kAirA << std::endl; + // std::cout << "\t Z = " << mat->GetZ() << " -> " << kAirZ << std::endl; + // std::cout << "\t Density = " << mat->GetDensity() << " -> " << kAirDensity << std::endl; + // std::cout << "\t RadLen = " << mat->GetRadLen() << " -> " << kAirRadLen << std::endl; + + // Make this material air-like + mat->SetA(kAirA); + mat->SetZ(kAirZ); + mat->SetDensity(kAirDensity); + mat->SetRadLen(kAirRadLen); +} + +//______________________________________________________________________ +void ComputeMaterialBudget(double rmin, double rmax, double etaPos, + double phiMin, double phiMax, TH1F* xOverX0VsPhi, + TH1F* xOverX0VsEta, TH1F* xOverX0VsZvtx, TH2F* xOverX02d = nullptr) +{ + // Ancillary function to compute material budget between rmin and rmax + + TH1F* nParticlesVsPhi = new TH1F("", "", nBinsPhiScan, phiMin, phiMax); + TH1F* nParticlesVsEta = new TH1F("", "", nBinsEtaScan, -maxEtaScan, maxEtaScan); + TH1F* nParticlesVsZvtx = new TH1F("", "", nBinsZvtxScan, -len / 2, len / 2); + TH2F* nParticlesVsPhiEta = new TH2F("", "", nBinsZvtxScan, -maxEtaScan, maxEtaScan, nBinsPhiScan, phiMax, phiMax); + + double x1, y1, z1, x2, y2, z2; + + for (int it = 0; it < n; it++) { // we simulate flat in phi and eta, from Zvtx=0 + + // PHI VS ETA + double phi = gRandom->Uniform(phiMin, phiMax); + double eta = gRandom->Uniform(-maxEtaScan, maxEtaScan); + double theta = TMath::ATan(TMath::Exp(-eta)) * 2; + x1 = rmin * TMath::Cos(phi); + y1 = rmin * TMath::Sin(phi); + z1 = rmin / TMath::Tan(theta); + x2 = rmax * TMath::Cos(phi); + y2 = rmax * TMath::Sin(phi); + z2 = rmax / TMath::Tan(theta); + + auto mparam = o2::base::GeometryManager::meanMaterialBudget(x1, y1, z1, x2, y2, z2); + + if (std::abs(eta) < etaPos) { + xOverX0VsPhi->Fill(phi, mparam.meanX2X0 * 100); + nParticlesVsPhi->Fill(phi); + } + xOverX0VsEta->Fill(eta, mparam.meanX2X0 * 100); + nParticlesVsEta->Fill(eta); + + if (xOverX02d != 0) { + xOverX02d->Fill(eta, phi, mparam.meanX2X0 * 100); + nParticlesVsPhiEta->Fill(eta, phi); + } + } + + for (int it = 0; it < n; it++) { // then we simulate flat in Zvtx with eta = 0 and flat in phi + + double phi = TMath::Pi() / 2; + double eta = 0.; + double theta = TMath::ATan(TMath::Exp(-eta)) * 2; + double z = gRandom->Uniform(-len / 2, len / 2); + x1 = rmin * TMath::Cos(phi); + y1 = rmin * TMath::Sin(phi); + x2 = rmax * TMath::Cos(phi); + y2 = rmax * TMath::Sin(phi); + + auto mparam = o2::base::GeometryManager::meanMaterialBudget(x1, y1, z, x2, y2, z); + + xOverX0VsZvtx->Fill(z, mparam.meanX2X0 * 100); + nParticlesVsZvtx->Fill(z); + } + + // normalization to number of particles in case of phi vs eta + double theta = TMath::ATan(TMath::Exp(-etaPos / 2)) * 2; + LOGP(info, "<η>={} -> Sin(θ) {}", etaPos / 2, TMath::Sin(theta)); + + for (int ix = 1; ix <= nParticlesVsPhi->GetNbinsX(); ix++) { + if (nParticlesVsPhi->GetBinContent(ix) > 0) + xOverX0VsPhi->SetBinContent(ix, xOverX0VsPhi->GetBinContent(ix) / nParticlesVsPhi->GetBinContent(ix) * TMath::Sin(theta)); + } + + for (int ix = 1; ix <= nParticlesVsEta->GetNbinsX(); ix++) { + if (nParticlesVsEta->GetBinContent(ix) > 0) + xOverX0VsEta->SetBinContent(ix, xOverX0VsEta->GetBinContent(ix) / nParticlesVsEta->GetBinContent(ix)); + } + + for (int ix = 1; ix <= nParticlesVsZvtx->GetNbinsX(); ix++) { + if (nParticlesVsZvtx->GetBinContent(ix) > 0) + xOverX0VsZvtx->SetBinContent(ix, xOverX0VsZvtx->GetBinContent(ix) / nParticlesVsZvtx->GetBinContent(ix)); + } + + if (xOverX02d) { + for (int ix = 1; ix <= nParticlesVsPhiEta->GetNbinsX(); ix++) { + for (int iy = 1; iy <= nParticlesVsPhiEta->GetNbinsY(); iy++) { + if (nParticlesVsPhiEta->GetBinContent(ix, iy) > 0) + xOverX02d->SetBinContent(ix, iy, xOverX02d->GetBinContent(ix, iy) / nParticlesVsPhiEta->GetBinContent(ix, iy)); + } + } + } +} + +std::vector printMaterialDefinitions(TGeoManager* gman) +{ + std::vector materialNames; + TGeoMedium* med; + TGeoMaterial* mat; + char mediaName[50], matName[50], shortName[50]; + + int nMedia = gman->GetListOfMedia()->GetEntries(); + + LOGP(info, " =================== ALICE 3 Material Properties ================= "); + LOGP(info, " A Z d (g/cm3) RadLen (cm) IntLen (cm)\t Name\n"); + + for (int i = 0; i < nMedia; i++) { + med = (TGeoMedium*)(gman->GetListOfMedia()->At(i)); + mat = med->GetMaterial(); + LOGP(info, "{:5.1f} {:6.1f} {:8.3f} {:13.1f} {:11.1f}\t {}", mat->GetA(), mat->GetZ(), mat->GetDensity(), mat->GetRadLen(), mat->GetIntLen(), mat->GetName()); + + std::vector tokens; + std::string matNameStr(mat->GetName()); + if (matNameStr.back() == '$') { + matNameStr.pop_back(); + } + size_t pos = 0; + while ((pos = matNameStr.find("_")) != std::string::npos) { + std::string part = matNameStr.substr(0, pos); + tokens.push_back(part); + matNameStr.erase(0, pos + 1); + } + std::transform(matNameStr.begin(), matNameStr.end(), matNameStr.begin(), ::toupper); + tokens.push_back(matNameStr); + if (tokens.back() == "NF") { // Manually manage air_NF + continue; + } + if (std::find(materialNames.begin(), materialNames.end(), tokens.back()) == materialNames.end()) { + materialNames.push_back(tokens.back()); + } + } + + // print material names for debug + for (auto& name : materialNames) { + LOGP(info, "Unique material name: {}", name); + } + + return materialNames; +} + +void scanXX0(const float rmax = 200, const float rmin = 0.2, const std::string OnlyMat = "all", const string fileName = "o2sim_geometry.root", const string path = "./") +{ + gStyle->SetPadTopMargin(0.035); + gStyle->SetPadRightMargin(0.035); + gStyle->SetPadBottomMargin(0.14); + gStyle->SetPadLeftMargin(0.14); + gStyle->SetTitleOffset(1.4, "y"); + gStyle->SetPadTickX(1); + gStyle->SetPadTickY(1); + gStyle->SetOptStat(0); + gStyle->SetOptTitle(0); + gStyle->SetPalette(kSolar); + + double etaPos = 1.; + + TCanvas* canvStack = new TCanvas("canvStack", "canvStack", 2400, 800); + canvStack->Divide(3, 1); + + TCanvas* canv = new TCanvas("canv", "canv", 2400, 800); + canv->Divide(3, 1); + + TLegend* legVsPhi = new TLegend(0.25, 0.6, 0.85, 0.9); + legVsPhi->SetFillColor(kWhite); + legVsPhi->SetTextSize(0.045); + legVsPhi->SetHeader(Form("ALICE 3, |#it{#eta}| < %0.f, #it{Z}_{vtx} = 0", etaPos)); + + TLegend* legVsEta = new TLegend(0.25, 0.6, 0.85, 0.9); + legVsEta->SetFillColor(kWhite); + legVsEta->SetTextSize(0.045); + legVsEta->SetHeader("ALICE 3, 0 < #it{#varphi} < #pi, #it{Z}_{vtx} = 0"); + + TLegend* legVsZvtx = new TLegend(0.25, 0.6, 0.85, 0.9); + legVsZvtx->SetFillColor(kWhite); + legVsZvtx->SetTextSize(0.045); + legVsZvtx->SetHeader("ALICE 3, #it{#varphi} = #pi/2, #it{#eta} = 0"); + + auto* xOverX0VsPhiStack = new THStack("xOverX0VsPhi", ""); + auto* xOverX0VsEtaStack = new THStack("xOverX0VsEta", ""); + auto* xOverX0VsZvtxStack = new THStack("xOverX0VsZvtx", ""); + + std::vector xOverX0VsPhi; + std::vector xOverX0VsEta; + std::vector xOverX0VsZvtx; + + TGeoManager::Import((path + fileName).c_str()); + auto materials = printMaterialDefinitions(gGeoManager); + + const double phiMin = 0; + const double phiMax = 2 * TMath::Pi(); + const double len = 1000.; + std::vector colors = {kAzure + 4, kRed + 1}; + + // delete gGeoManager; // We re-import the geometry at each iteration + int count = 2; + auto cols = TColor::GetPalette(); + + for (size_t iMaterial{0}; iMaterial < materials.size(); ++iMaterial) { + if (OnlyMat != "all" && materials[iMaterial] != OnlyMat) { + continue; + } + TGeoManager::Import((path + fileName).c_str()); + LOGP(info, " ********* Processing material: {} ********* ", materials[iMaterial]); + auto nMedia = gGeoManager->GetListOfMedia()->GetEntries(); + for (int i = 0; i < nMedia; i++) { + auto* med = (TGeoMedium*)(gGeoManager->GetListOfMedia()->At(i)); + auto* mat = med->GetMaterial(); + std::string matname{mat->GetName()}; + std::transform(matname.begin(), matname.end(), matname.begin(), ::toupper); + if (matname.find(materials[iMaterial]) == std::string::npos) { + vacuumFormMaterial(mat); + } else { + LOGP(info, "\t {} found as {} element.", materials[iMaterial], iMaterial); + } + } + + xOverX0VsPhi.emplace_back(new TH1F(Form("xOverX0VsPhi_step%zu", iMaterial), "", nBinsPhiScan, phiMin, phiMax)); + xOverX0VsEta.emplace_back(new TH1F(Form("xOverX0VsEta_step%zu", iMaterial), "", nBinsEtaScan, -maxEtaScan, maxEtaScan)); + xOverX0VsZvtx.emplace_back(new TH1F(Form("xOverX0VsZvtx_step%zu", iMaterial), "", nBinsZvtxScan, -len / 2, len / 2)); + + ComputeMaterialBudget(rmin, rmax, etaPos, phiMin, phiMax, xOverX0VsPhi.back(), xOverX0VsEta.back(), xOverX0VsZvtx.back()); + + double meanX0vsPhi = 0, meanX0vsEta = 0, meanX0vsZvtx = 0; + for (int ix = 1; ix <= xOverX0VsPhi.back()->GetNbinsX(); ix++) { + meanX0vsPhi += xOverX0VsPhi.back()->GetBinContent(ix); + } + meanX0vsPhi /= xOverX0VsPhi.back()->GetNbinsX(); + + for (int ix = 1; ix <= xOverX0VsEta.back()->GetNbinsX(); ix++) { + meanX0vsEta += xOverX0VsEta.back()->GetBinContent(ix); + } + meanX0vsEta /= xOverX0VsEta.back()->GetNbinsX(); + + for (int ix = 1; ix <= xOverX0VsZvtx.back()->GetNbinsX(); ix++) { + meanX0vsZvtx += xOverX0VsZvtx.back()->GetBinContent(ix); + } + meanX0vsZvtx /= xOverX0VsZvtx.back()->GetNbinsX(); + + LOGP(info, "Mean X/X0 vs. phi: {}", meanX0vsPhi); + LOGP(info, "Mean X/X0 vs. eta: {}", meanX0vsEta); + LOGP(info, "Mean X/X0 vs. Zvtx: {}", meanX0vsZvtx); + + xOverX0VsPhi.back()->GetXaxis()->SetTitle("#it{#varphi} (rad)"); + xOverX0VsPhi.back()->GetXaxis()->SetTitleSize(0.05); + xOverX0VsPhi.back()->GetXaxis()->SetLabelSize(0.045); + xOverX0VsPhi.back()->GetYaxis()->SetTitle("#it{X}/#it{X}_{0} (%)"); + xOverX0VsPhi.back()->GetYaxis()->SetTitleSize(0.05); + xOverX0VsPhi.back()->GetYaxis()->SetLabelSize(0.045); + xOverX0VsPhi.back()->GetYaxis()->SetDecimals(); + xOverX0VsPhi.back()->SetFillColorAlpha(iMaterial + 2, 0.5); + xOverX0VsPhi.back()->SetLineColor(iMaterial + 2); + xOverX0VsPhi.back()->SetLineWidth(2); + + xOverX0VsEta.back()->GetXaxis()->SetTitle("#it{#eta}"); + xOverX0VsEta.back()->GetXaxis()->SetTitleSize(0.05); + xOverX0VsEta.back()->GetXaxis()->SetLabelSize(0.045); + xOverX0VsEta.back()->GetYaxis()->SetTitle("#it{X}/#it{X}_{0} (%)"); + xOverX0VsEta.back()->GetYaxis()->SetTitleSize(0.05); + xOverX0VsEta.back()->GetYaxis()->SetLabelSize(0.045); + xOverX0VsEta.back()->GetYaxis()->SetDecimals(); + xOverX0VsEta.back()->SetFillColorAlpha(iMaterial + 2, 0.5); + xOverX0VsEta.back()->SetLineColor(iMaterial + 2); + xOverX0VsEta.back()->SetLineWidth(2); + + xOverX0VsZvtx.back()->GetXaxis()->SetTitle("#it{Z}_{vtx} (cm)"); + xOverX0VsZvtx.back()->GetXaxis()->SetTitleSize(0.05); + xOverX0VsZvtx.back()->GetXaxis()->SetLabelSize(0.045); + xOverX0VsZvtx.back()->GetYaxis()->SetTitle("#it{X}/#it{X}_{0} (%)"); + xOverX0VsZvtx.back()->GetYaxis()->SetTitleSize(0.05); + xOverX0VsZvtx.back()->GetYaxis()->SetLabelSize(0.045); + xOverX0VsZvtx.back()->GetYaxis()->SetDecimals(); + xOverX0VsZvtx.back()->SetFillColorAlpha(iMaterial + 2, 0.5); + xOverX0VsZvtx.back()->SetLineColor(iMaterial + 2); + xOverX0VsZvtx.back()->SetLineWidth(2); + + if (xOverX0VsPhi.size() == 1) { + legVsPhi->AddEntry("", Form("#LT #it{X}/#it{X}_{0} #GT = %0.3f %%", meanX0vsPhi), ""); + legVsEta->AddEntry("", Form("#LT #it{X}/#it{X}_{0} #GT = %0.3f %%", meanX0vsEta), ""); + legVsZvtx->AddEntry("", Form("#LT #it{X}/#it{X}_{0} #GT = %0.3f %%", meanX0vsZvtx), ""); + } + legVsPhi->AddEntry(xOverX0VsPhi.back(), materials[iMaterial].c_str(), "f"); + legVsEta->AddEntry(xOverX0VsPhi.back(), materials[iMaterial].c_str(), "f"); + legVsZvtx->AddEntry(xOverX0VsZvtx.back(), materials[iMaterial].c_str(), "f"); + + canv->cd(1)->SetGrid(); + if (xOverX0VsPhi.size() == 1) { + xOverX0VsPhi.back()->SetMinimum(1.e-4); + // xOverX0VsPhi.back()->SetMaximum(20.f); + xOverX0VsPhi.back()->DrawCopy("HISTO"); + legVsPhi->Draw(); + xOverX0VsPhiStack->Add(xOverX0VsPhi.back()); + } else { + xOverX0VsPhi.back()->DrawCopy("HISTO SAME"); + xOverX0VsPhiStack->Add(xOverX0VsPhi.back()); + } + + canv->cd(2)->SetGrid(); + if (xOverX0VsEta.size() == 1) { + xOverX0VsEta.back()->SetMinimum(1.e-4); + // xOverX0VsEta.back()->SetMaximum(60.f); + xOverX0VsEta.back()->DrawCopy("HISTO"); + legVsEta->Draw(); + xOverX0VsEtaStack->Add(xOverX0VsEta.back()); + } else { + xOverX0VsEta.back()->DrawCopy("HISTO SAME"); + xOverX0VsEtaStack->Add(xOverX0VsEta.back()); + } + + canv->cd(3)->SetGrid(); + if (xOverX0VsZvtx.size() == 1) { + xOverX0VsZvtx.back()->SetMinimum(1.e-4); + // xOverX0VsZvtx.back()->SetMaximum(120.f); + xOverX0VsZvtx.back()->DrawCopy("HISTO"); + legVsZvtx->Draw(); + xOverX0VsZvtxStack->Add(xOverX0VsZvtx.back()); + } else { + xOverX0VsZvtx.back()->DrawCopy("HISTO SAME"); + xOverX0VsZvtxStack->Add(xOverX0VsZvtx.back()); + } + delete gGeoManager; + } + canvStack->cd(1)->SetGrid(); + xOverX0VsPhiStack->Draw("HISTO"); + canvStack->cd(2)->SetGrid(); + xOverX0VsEtaStack->Draw("HISTO"); + canvStack->cd(3)->SetGrid(); + xOverX0VsZvtxStack->Draw("HISTO"); + canvStack->BuildLegend(0.25, 0.6, 0.85, 0.9); + + canv->SaveAs("alice3_material_vsphietaz.pdf"); + canvStack->SaveAs("alice3_material_vsphietaz_stack.pdf"); +} \ No newline at end of file From 0667094a4bed1beaacfaa5fdba154ed01e37de10 Mon Sep 17 00:00:00 2001 From: Francesco Noferini Date: Thu, 8 Feb 2024 09:19:14 +0100 Subject: [PATCH 09/50] bug fix when creating diagnostic frequency (clear was missing) (#12672) Co-authored-by: noferini <9963644+noferini@users.noreply.github.com> --- DataFormats/Detectors/TOF/src/Diagnostic.cxx | 2 +- Detectors/TOF/base/src/WindowFiller.cxx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DataFormats/Detectors/TOF/src/Diagnostic.cxx b/DataFormats/Detectors/TOF/src/Diagnostic.cxx index 464013afe566a..27ca65d124dd7 100644 --- a/DataFormats/Detectors/TOF/src/Diagnostic.cxx +++ b/DataFormats/Detectors/TOF/src/Diagnostic.cxx @@ -104,7 +104,7 @@ void Diagnostic::merge(const Diagnostic* prev) { LOG(debug) << "Merging diagnostic words"; for (auto const& el : prev->mVector) { - fill(el.first, el.second + getFrequency(el.first)); + fill(el.first, el.second); } } diff --git a/Detectors/TOF/base/src/WindowFiller.cxx b/Detectors/TOF/base/src/WindowFiller.cxx index cd6f2e653943a..829fd05f97629 100644 --- a/Detectors/TOF/base/src/WindowFiller.cxx +++ b/Detectors/TOF/base/src/WindowFiller.cxx @@ -448,6 +448,7 @@ void WindowFiller::checkIfReuseFutureDigitsRO() // the same but using readout in void WindowFiller::fillDiagnosticFrequency() { bool isTOFempty = true; + mDiagnosticFrequency.clear(); // fill diagnostic frequency for (int j = 0; j < mReadoutWindowData.size(); j++) { mDiagnosticFrequency.fillROW(); From 4d5481e375480d08c68cebfb114acc9b3dbca902 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:50:28 +0100 Subject: [PATCH 10/50] [EMCAL-688] Inclusion of EMCal Cell and Cluster labels (#12660) - Add CellLabel class to handle the pairs of MC particle IDs and amplitdue fraction on cell level which the ClusterFactory now uses as a new container inside the `buildCluster` function. For this function an additional argument was added, more info next bullet. - Add ClusterLabel class to handel the paris of MC particle IDs and amplitude fraction on cluster level. They get filled inside the `buildCluster` function of the cluster factory where a point to an object of ClusterLabel is now an optional 2nd argument to the function. If one pointer is give, the ClusterLabel is filled with the labels and amplitude fractions and orderer inside the ClusterFactory. --- DataFormats/Detectors/EMCAL/CMakeLists.txt | 6 +- .../include/DataFormatsEMCAL/CellLabel.h | 66 +++++++++++++ .../include/DataFormatsEMCAL/ClusterLabel.h | 95 +++++++++++++++++++ DataFormats/Detectors/EMCAL/src/CellLabel.cxx | 23 +++++ .../Detectors/EMCAL/src/ClusterLabel.cxx | 75 +++++++++++++++ .../EMCAL/src/DataFormatsEMCALLinkDef.h | 2 - .../base/include/EMCALBase/ClusterFactory.h | 20 ++-- Detectors/EMCAL/base/src/ClusterFactory.cxx | 15 ++- 8 files changed, 292 insertions(+), 10 deletions(-) create mode 100644 DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h create mode 100644 DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ClusterLabel.h create mode 100644 DataFormats/Detectors/EMCAL/src/CellLabel.cxx create mode 100644 DataFormats/Detectors/EMCAL/src/ClusterLabel.cxx diff --git a/DataFormats/Detectors/EMCAL/CMakeLists.txt b/DataFormats/Detectors/EMCAL/CMakeLists.txt index 1e7c4f4739a3b..80b00474465b8 100644 --- a/DataFormats/Detectors/EMCAL/CMakeLists.txt +++ b/DataFormats/Detectors/EMCAL/CMakeLists.txt @@ -20,6 +20,8 @@ o2_add_library(DataFormatsEMCAL src/EventHandler.cxx src/CTF.cxx src/ErrorTypeFEE.cxx + src/CellLabel.cxx + src/ClusterLabel.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::MathUtils @@ -37,7 +39,9 @@ o2_target_root_dictionary(DataFormatsEMCAL include/DataFormatsEMCAL/EventHandler.h include/DataFormatsEMCAL/MCLabel.h include/DataFormatsEMCAL/CTF.h - include/DataFormatsEMCAL/ErrorTypeFEE.h) + include/DataFormatsEMCAL/ErrorTypeFEE.h + include/DataFormatsEMCAL/CellLabel.h + include/DataFormatsEMCAL/ClusterLabel.h) o2_add_test(Cell SOURCES test/testCell.cxx diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h new file mode 100644 index 0000000000000..f0181e01f84c5 --- /dev/null +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h @@ -0,0 +1,66 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_EMCAL_CELLLABEL_H_ +#define ALICEO2_EMCAL_CELLLABEL_H_ + +#include +#include +#include +#include "Rtypes.h" + +namespace o2 +{ + +namespace emcal +{ + +/// \class CellLabel +/// \brief cell class for MC particle IDs and their respective amplitude fraction +/// \ingroup EMCALDataFormat +/// \author Marvin Hemmer , Goethe university Frankfurt +/// \since December 13, 2023 +/// + +class CellLabel +{ + public: + // CellLabel() = default; + + /// \brief Constructor + /// \param labels list of mc labels + /// \param amplitudeFractions list of amplitude fractions + CellLabel(const gsl::span labels, const gsl::span amplitudeFractions); + + // ~CellLabel() = default; + // CellLabel(const CellLabel& clus) = default; + // CellLabel& operator=(const CellLabel& source) = default; + + /// \brief Getter of label size + /// \param index index which label to get + size_t GetLabelSize(void) const { return mLabels.size(); } + + /// \brief Getter for label + /// \param index index which label to get + int32_t GetLabel(size_t index) const { return mLabels[index]; } + + /// \brief Getter for amplitude fraction + /// \param index index which amplitude fraction to get + float GetAmplitudeFraction(size_t index) const { return mAmplitudeFraction[index]; } + + protected: + gsl::span mLabels; ///< List of MC particles that generated the cluster, ordered in deposited energy. + gsl::span mAmplitudeFraction; ///< List of the fraction of the cell energy coming from a MC particle. Index aligns with mLabels! +}; + +} // namespace emcal +} // namespace o2 +#endif // ALICEO2_EMCAL_CELLLABEL_H_ diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ClusterLabel.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ClusterLabel.h new file mode 100644 index 0000000000000..a52f018d3d8bc --- /dev/null +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ClusterLabel.h @@ -0,0 +1,95 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_EMCAL_CLUSTERLABEL_H_ +#define ALICEO2_EMCAL_CLUSTERLABEL_H_ + +#include +#include +#include +#include "Rtypes.h" + +namespace o2 +{ + +namespace emcal +{ + +/// \class ClusterLabel +/// \brief cluster class for MC particle IDs and their respective energy fraction +/// \ingroup EMCALDataFormat +/// \author Marvin Hemmer , Goethe university Frankfurt +/// \since December 13, 2023 +/// + +class ClusterLabel +{ + public: + /// \struct labelWithE + /// \brief Wrapper structure to make cluster label sortable in energy fraction + struct labelWithE { + + /// \brief Constructor + labelWithE() : energyFraction(0.), label(0) {} + + /// \brief Constructor + /// \param e Energy fraction + /// \param l MC label + labelWithE(float e, int l) : energyFraction(e), label(l) {} + + /// \brief Comparison lower operator comparing cells based on energy + /// + /// std::sort will require operator>= to compile. + /// + /// \param rhs Label to compare to + /// \return True if this cell is has a lower energy, false otherwise + bool operator>=(labelWithE const& rhs) const + { + return energyFraction >= rhs.energyFraction; + } + + float energyFraction; ///< Energy Fraction + int label; ///< MC label + }; + + // ClusterLabel() = default; + // ~ClusterLabel() = default; + // ClusterLabel(const ClusterLabel& clus) = default; + // ClusterLabel& operator=(const ClusterLabel& source) = default; + + /// \brief Clear the member variables + void clear(); + + /// \brief Add label and energy fraction to the + /// \param label MC label + /// \param energyFraction Energy fraction + void addValue(int label, float energyFraction); + + /// \brief Normalize the energy fraction + /// \param factor normalization factor + void normalize(float factor); + + /// \brief Getter for vector of labels + std::vector getLabels(); + + /// \brief Getter for vector of energy fractions + std::vector getEnergyFractions(); + + /// \brief Sort the labels and energy fraction in descending order (largest energy fraction to smallest) + void orderLabels(); + + protected: + std::vector mClusterLabels; ///< List of MC particles that generated the cluster, paired with energy fraction +}; + +} // namespace emcal +} // namespace o2 +#endif // ALICEO2_EMCAL_CLUSTERLABEL_H_ diff --git a/DataFormats/Detectors/EMCAL/src/CellLabel.cxx b/DataFormats/Detectors/EMCAL/src/CellLabel.cxx new file mode 100644 index 0000000000000..8dde7ea90c435 --- /dev/null +++ b/DataFormats/Detectors/EMCAL/src/CellLabel.cxx @@ -0,0 +1,23 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file CellLabel.cxx + +#include "DataFormatsEMCAL/CellLabel.h" + +using namespace o2::emcal; + +CellLabel::CellLabel(const gsl::span labels, const gsl::span amplitudeFractions) : mLabels(labels), mAmplitudeFraction(amplitudeFractions) +{ + if (labels.size() != amplitudeFractions.size()) { + LOG(error) << "Size of labels " << labels.size() << " does not match size of amplitude fraction " << amplitudeFractions.size() << " !"; + } +} diff --git a/DataFormats/Detectors/EMCAL/src/ClusterLabel.cxx b/DataFormats/Detectors/EMCAL/src/ClusterLabel.cxx new file mode 100644 index 0000000000000..6e3bd4f147447 --- /dev/null +++ b/DataFormats/Detectors/EMCAL/src/ClusterLabel.cxx @@ -0,0 +1,75 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file ClusterLabel.cxx + +#include "DataFormatsEMCAL/ClusterLabel.h" + +using namespace o2::emcal; + +//_______________________________________________________________________ +void ClusterLabel::clear() +{ + mClusterLabels.clear(); +} + +//_______________________________________________________________________ +void ClusterLabel::addValue(int label, float energyFraction) +{ + auto it = std::find_if(mClusterLabels.begin(), mClusterLabels.end(), + [label](const labelWithE& lWE) { return lWE.label == label; }); + + if (it != mClusterLabels.end()) { + // label already exists, accumulate energy fraction + it->energyFraction += energyFraction; + } else { + // label does not exist, add new energy fraction + mClusterLabels.emplace_back(label, energyFraction); + } +} + +//_______________________________________________________________________ +void ClusterLabel::normalize(float factor) +{ + for (auto& clusterlabel : mClusterLabels) { + clusterlabel.energyFraction = clusterlabel.energyFraction / factor; + } +} + +//_______________________________________________________________________ +std::vector ClusterLabel::getLabels() +{ + std::vector vLabels; + vLabels.reserve(mClusterLabels.size()); + for (auto& clusterlabel : mClusterLabels) { + vLabels.push_back(clusterlabel.label); + } + return vLabels; +} + +//_______________________________________________________________________ +std::vector ClusterLabel::getEnergyFractions() +{ + std::vector vEnergyFractions; + vEnergyFractions.reserve(mClusterLabels.size()); + for (auto& clusterlabel : mClusterLabels) { + vEnergyFractions.push_back(clusterlabel.energyFraction); + } + return vEnergyFractions; +} + +//_______________________________________________________________________ +void ClusterLabel::orderLabels() +{ + // Sort the pairs based on values in descending order + std::sort(mClusterLabels.begin(), mClusterLabels.end(), + [](const labelWithE& a, const labelWithE& b) { return a.label >= b.label; }); +} diff --git a/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h b/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h index 746af5987f442..a648dd9fbbdc1 100644 --- a/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h +++ b/DataFormats/Detectors/EMCAL/src/DataFormatsEMCALLinkDef.h @@ -42,8 +42,6 @@ // For channel type in digits and cells #pragma link C++ enum o2::emcal::ChannelType_t + ; -#pragma link C++ class std::vector < o2::emcal::Cluster> + ; - #pragma link C++ class o2::emcal::EventData < o2::emcal::Cell> + ; #pragma link C++ class o2::emcal::EventData < o2::emcal::Digit> + ; #pragma link C++ class o2::emcal::EventHandler < o2::emcal::Cell> + ; diff --git a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h index f0bb9f3db4480..2957eacb8d050 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h +++ b/Detectors/EMCAL/base/include/EMCALBase/ClusterFactory.h @@ -11,6 +11,8 @@ #ifndef ALICEO2_EMCAL_CLUSTERFACTORY_H_ #define ALICEO2_EMCAL_CLUSTERFACTORY_H_ #include +#include +#include #include #include #include "Rtypes.h" @@ -19,6 +21,8 @@ #include "DataFormatsEMCAL/Digit.h" #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/AnalysisCluster.h" +#include "DataFormatsEMCAL/CellLabel.h" +#include "DataFormatsEMCAL/ClusterLabel.h" #include "EMCALBase/Geometry.h" #include "MathUtils/Cartesian.h" @@ -230,7 +234,7 @@ class ClusterFactory /// /// evaluates cluster parameters: position, shower shape, primaries ... - AnalysisCluster buildCluster(int index) const; + AnalysisCluster buildCluster(int index, o2::emcal::ClusterLabel* clusterLabel = nullptr) const; void SetECALogWeight(Float_t w) { mLogWeight = w; } float GetECALogWeight() const { return mLogWeight; } @@ -331,7 +335,7 @@ class ClusterFactory bool getUseWeightExotic() const { return mUseWeightExotic; } void setUseWeightExotic(float useWeightExotic) { mUseWeightExotic = useWeightExotic; } - void setContainer(gsl::span clusterContainer, gsl::span cellContainer, gsl::span indicesContainer) + void setContainer(gsl::span clusterContainer, gsl::span cellContainer, gsl::span indicesContainer, std::optional> cellLabelContainer = std::nullopt) { mClustersContainer = clusterContainer; mInputsContainer = cellContainer; @@ -339,6 +343,9 @@ class ClusterFactory if (!getLookUpInit()) { setLookUpTable(); } + if (cellLabelContainer) { + mCellLabelContainer = cellLabelContainer.value(); + } } void setLookUpTable(void) @@ -425,10 +432,11 @@ class ClusterFactory float mExoticCellInCrossMinAmplitude = 0.1; ///< Minimum energy of cells in cross, if lower not considered in cross bool mUseWeightExotic = false; ///< States if weights should be used for exotic cell cut - gsl::span mClustersContainer; ///< Container for all the clusters in the event - gsl::span mInputsContainer; ///< Container for all the cells/digits in the event - gsl::span mCellsIndices; ///< Container for cells indices in the event - std::array mLoolUpTowerToIndex; ///< Lookup table to match tower id with cell index, needed for exotic check + gsl::span mClustersContainer; ///< Container for all the clusters in the event + gsl::span mInputsContainer; ///< Container for all the cells/digits in the event + gsl::span mCellsIndices; ///< Container for cells indices in the event + std::array mLoolUpTowerToIndex; ///< Lookup table to match tower id with cell index, needed for exotic check + gsl::span mCellLabelContainer; ///< Container for all the cell labels in the event ClassDefNV(ClusterFactory, 2); }; diff --git a/Detectors/EMCAL/base/src/ClusterFactory.cxx b/Detectors/EMCAL/base/src/ClusterFactory.cxx index 4b9cdd448fbda..734ed2a5d2eab 100644 --- a/Detectors/EMCAL/base/src/ClusterFactory.cxx +++ b/Detectors/EMCAL/base/src/ClusterFactory.cxx @@ -18,6 +18,8 @@ #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/AnalysisCluster.h" #include "DataFormatsEMCAL/Constants.h" +#include "DataFormatsEMCAL/CellLabel.h" +#include "DataFormatsEMCAL/ClusterLabel.h" #include "EMCALBase/Geometry.h" #include "MathUtils/Cartesian.h" @@ -38,13 +40,14 @@ void ClusterFactory::reset() mInputsContainer = gsl::span(); mCellsIndices = gsl::span(); mLookUpInit = false; + mCellLabelContainer = gsl::span(); } /// /// evaluates cluster parameters: position, shower shape, primaries ... //____________________________________________________________________________ template -o2::emcal::AnalysisCluster ClusterFactory::buildCluster(int clusterIndex) const +o2::emcal::AnalysisCluster ClusterFactory::buildCluster(int clusterIndex, o2::emcal::ClusterLabel* clusterLabel) const { if (clusterIndex >= mClustersContainer.size()) { throw ClusterRangeException(clusterIndex, mClustersContainer.size()); @@ -86,9 +89,19 @@ o2::emcal::AnalysisCluster ClusterFactory::buildCluster(int clusterIn std::vector cellsIdices; + size_t iCell = 0; for (auto cellIndex : inputsIndices) { cellsIdices.push_back(cellIndex); + if ((clusterLabel != nullptr) && (mCellLabelContainer.size() > 0)) { + for (size_t iLabel = 0; iLabel < mCellLabelContainer[iCell].GetLabelSize(); iLabel++) { + clusterLabel->addValue(mCellLabelContainer[iCell].GetLabel(iLabel), + mCellLabelContainer[iCell].GetAmplitudeFraction(iLabel) * mInputsContainer[iCell].getEnergy()); + } + iCell++; + } } + clusterLabel->orderLabels(); + clusterLabel->normalize(cellAmp); clusterAnalysis.setCellsIndices(cellsIdices); From 3134f2b34b388d5549b1ca62e921a9bb7fa059a9 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 8 Feb 2024 17:24:23 +0100 Subject: [PATCH 11/50] Suppress excessive logging in the TrackMethods used by TPC QC --- .../GlobalTracking/include/GlobalTracking/TrackMethods.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/TrackMethods.h b/Detectors/GlobalTracking/include/GlobalTracking/TrackMethods.h index 2d67a9595008e..d87d68dd122b2 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/TrackMethods.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/TrackMethods.h @@ -33,9 +33,9 @@ class TrackMethods const o2::tpc::ClusterNativeAccess& tpcClusAcc, uint8_t& shared, uint8_t& found, uint8_t& crossed) { - LOGP(info, "tpcClusRefs {}/{}", (void*)tpcClusRefs.data(), tpcClusRefs.size()); - LOGP(info, "tpcClusShMap {}/{}", (void*)tpcClusShMap.data(), tpcClusShMap.size()); - LOGP(info, " tpcClusAcc{}/{}", (void*)tpcClusAcc.clustersLinear, tpcClusAcc.nClustersTotal); + LOGP(debug, "tpcClusRefs {}/{}", (void*)tpcClusRefs.data(), tpcClusRefs.size()); + LOGP(debug, "tpcClusShMap {}/{}", (void*)tpcClusShMap.data(), tpcClusShMap.size()); + LOGP(debug, "tpcClusAcc {}/{}", (void*)tpcClusAcc.clustersLinear, tpcClusAcc.nClustersTotal); constexpr int maxRows = 152; constexpr int neighbour = 2; std::array clMap{}, shMap{}; @@ -93,4 +93,4 @@ class TrackMethods }; } // namespace o2 -#endif \ No newline at end of file +#endif From 331db1cd6c41ec79b87a55c306acb00de01d3c20 Mon Sep 17 00:00:00 2001 From: Benedikt Volkel Date: Thu, 8 Feb 2024 13:45:47 +0100 Subject: [PATCH 12/50] Force digitisation when not in GRP The reco workflow in data taking is agnostic, meaning that empty reco files are written for detectors that were not readout in data taking. To be able to resemble this in simulation, it should be possible to always run the digitisation workflow for desired detectors (--onlyDet, --skipDet) even if they are not in the GRP file which has previously been created by the transport code. This will open up the possibility to implicitly modularies our simulation workflow in the following sense: Digits will be present for all detectors that produced a hit file. On the other hand, empty digi files will be produced for ALL detectors such that the reco->match->AOD files will end up with the correct content derived from detectors that actually produced hit files. This will drastically reduce the need of specialising our simulation workflow graphs. In particular, this is a step forward to more resilient anchored simulation. --- .../src/SimpleDigitizerWorkflow.cxx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index fd5fc79830c79..523c1f2cf6af7 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -158,6 +158,13 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back( ConfigParamSpec{"skipDet", VariantType::String, "none", {skiphelp}}); + // especially useful if digit files are required later on in a simulation chain. + // so if --onlyDet is set, one can then be sure to find all those digi files, especially those for which the detector + // hit files do not exist (e.g. because the detector was not readout during data taking) + std::string forceaccepthelp("Whether or not to always rely on accept/skip filters for detectors, independent of GRP content"); + workflowOptions.push_back( + ConfigParamSpec{"forceSelectedDets", VariantType::Bool, false, {forceaccepthelp}}); + std::string onlyctxhelp("Produce only the digitization context; Don't actually digitize"); workflowOptions.push_back(ConfigParamSpec{"only-context", o2::framework::VariantType::Bool, false, {onlyctxhelp}}); @@ -547,13 +554,20 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) return false; } auto accepted = accept(id); + + // always comply with the filter choice? + auto forceAccepted = configcontext.options().get("forceSelectedDets"); bool is_ingrp = isInGRPReadout(id); + // final decision on whether or not this detector will be digitized + auto isRun = accepted && (forceAccepted || is_ingrp); if (gIsMaster) { LOG(info) << id.getName() << " is in grp? " << (is_ingrp ? "yes" : "no") << ";" - << " is skipped? " << (!accepted ? "yes" : "no"); + << " is taken although not in grp? " << (!is_ingrp && (accepted && forceAccepted) ? "yes" : "no") << ";" + << " is skipped? " << (!accepted ? "yes" : "no") << ";" + << " is run? " << (isRun ? "yes" : "no"); } - return accepted && is_ingrp; + return isRun; }; std::vector detList; // list of participating detectors From 515e51e8cf2bb870b02b8b9abf5f0678c6133285 Mon Sep 17 00:00:00 2001 From: Timo Wilken Date: Fri, 9 Feb 2024 16:01:54 +0000 Subject: [PATCH 13/50] Only override LD_LIBRARY_PATH for rootcling, not for CMake (#12683) CMake depends on more things that are in the customised LD_LIBRARY_PATH, such as OpenSSL. Therefore, the new LD_LIBRARY_PATH must only apply to the rootcling command, not to CMake. Assigning to an exported variable in bash changes the exported definition, so assigning to LD_LIBRARY_PATH directly (even without explicitly exporting) means the variable already takes effect for the wrapping cmake command. This does not seem to be intended, so use a temporary variable instead. --- cmake/rootcling_wrapper.sh.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/rootcling_wrapper.sh.in b/cmake/rootcling_wrapper.sh.in index 72e101cd1cbf8..8d4e3514a6e81 100755 --- a/cmake/rootcling_wrapper.sh.in +++ b/cmake/rootcling_wrapper.sh.in @@ -26,7 +26,7 @@ while [[ $# -gt 0 ]]; do shift 2 ;; --ld_library_path) - LD_LIBRARY_PATH="$2" + libpath="$2" shift 2 ;; --dictionary_file) @@ -82,7 +82,7 @@ esac LOGFILE=${DICTIONARY_FILE}.log -@CMAKE_COMMAND@ -E env LD_LIBRARY_PATH=${LD_LIBRARY_PATH} @ROOT_rootcling_CMD@ \ +@CMAKE_COMMAND@ -E env "LD_LIBRARY_PATH=$libpath" @ROOT_rootcling_CMD@ \ -f $DICTIONARY_FILE \ -inlineInputHeader \ -noGlobalUsingStd \ From b0eedd1444be5734eb626fd1065916ccb6ec8153 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Fri, 9 Feb 2024 16:15:28 +0000 Subject: [PATCH 14/50] ctpdev: new exe for FirstOrbit/OrbitReset and shiftOrbit for CTP scalers (#12666) * dev: new exe for writing FirstOrbit and OrbitReset and minor unrelated macro mods * clang * fix:missing copyright * dev:ctp-ccdb-orbit fixes * clang * dev: ctp-ccdb-orbit fixes * clang * fix: option to have full ccdb address as parameter * dev: orbit shift for scalers * clang --- .../CTP/include/DataFormatsCTP/Scalers.h | 18 ++- DataFormats/Detectors/CTP/src/Scalers.cxx | 20 ++- Detectors/CTP/macro/CMakeLists.txt | 4 + Detectors/CTP/macro/GetScalersForRun.C | 14 +- Detectors/CTP/macro/PlotOrbit.C | 94 ++++++++++++ Detectors/CTP/workflowScalers/CMakeLists.txt | 16 ++ .../workflowScalers/src/ctp-ccdb-orbit.cxx | 139 ++++++++++++++++++ 7 files changed, 296 insertions(+), 9 deletions(-) create mode 100644 Detectors/CTP/macro/PlotOrbit.C create mode 100644 Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx diff --git a/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h b/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h index 63462f90179b2..233e8bde294d2 100644 --- a/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h +++ b/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h @@ -110,7 +110,8 @@ class CTPRunScalers int printInputRateAndIntegral(int inp); int printClassBRateAndIntegralII(int icls); int printClassBRateAndIntegral(int iclsinscalers); - + // + int addOrbitOffset(uint32_t offset); // // static constexpr uint32_t NCOUNTERS = 1052; // v1 @@ -129,17 +130,26 @@ class CTPRunScalers /// same with absolute timestamp (not orbit) as argument std::pair getRateGivenT(double timestamp, int classindex, int type) const; - /// retrieves time boundaries of this scaler object + /// retrieves time boundaries of this scaler object from O2 scalers std::pair getTimeLimit() const { return std::make_pair((unsigned long)mScalerRecordO2[0].epochTime * 1000, (unsigned long)mScalerRecordO2[mScalerRecordO2.size() - 1].epochTime * 1000); } - - /// retrieves orbit boundaries of this scaler object + /// retrieves time boundaries of this scaler object from Raw: should be same as from O2 and can be used without convertRawToO2 call + std::pair getTimeLimitFromRaw() const + { + return std::make_pair((unsigned long)mScalerRecordRaw[0].epochTime * 1000, (unsigned long)mScalerRecordRaw[mScalerRecordRaw.size() - 1].epochTime * 1000); + } + /// retrieves orbit boundaries of this scaler object from O2 std::pair getOrbitLimit() const { return std::make_pair((unsigned long)mScalerRecordO2[0].intRecord.orbit, (unsigned long)mScalerRecordO2[mScalerRecordO2.size() - 1].intRecord.orbit); } + /// retrieves orbit boundaries of this scaler object from Raw: should be same as from O2 and can be used without convertRawToO2 call + std::pair getOrbitLimitFromRaw() const + { + return std::make_pair((unsigned long)mScalerRecordRaw[0].intRecord.orbit, (unsigned long)mScalerRecordRaw[mScalerRecordRaw.size() - 1].intRecord.orbit); + } private: // map from class index to overflow diff --git a/DataFormats/Detectors/CTP/src/Scalers.cxx b/DataFormats/Detectors/CTP/src/Scalers.cxx index 728ef1493ee0f..6ba75929fdedd 100644 --- a/DataFormats/Detectors/CTP/src/Scalers.cxx +++ b/DataFormats/Detectors/CTP/src/Scalers.cxx @@ -776,7 +776,25 @@ std::pair CTPRunScalers::getRateGivenT(double timestamp, int cla } return std::make_pair(-1., -1.); } - +// Offset orbit of all records +// +int CTPRunScalers::addOrbitOffset(uint32_t offset) +{ + LOG(info) << "Subtracting from orbit " << offset; + for (auto& screc : mScalerRecordRaw) { + uint32_t orbit = screc.intRecord.orbit; + uint32_t orbitnew = 0; + if (orbit >= offset) { + orbitnew = orbit - offset; + } else { + orbitnew = 0xffffffff - offset; + orbitnew = orbit + 1 + orbitnew; + LOG(error) << "Orbit overflow - should never happen. Run:" << mRunNumber; + } + screc.intRecord.orbit = orbitnew; + } + return 0; +} std::vector CTPRunScalers::scalerNames = { "runn0", "runn1", "runn2", "runn3", "runn4", "runn5", "runn6", "runn7", "runn8", "runn9", "runn10", "runn11", "runn12", "runn13", "runn14", "runn15", "ltg1_ORB", "ltg1_HB", "ltg1_HBr", "ltg1_HC", "ltg1_PH", "ltg1_PP", "ltg1_CAL", "ltg1_SOT", "ltg1_EOT", "ltg1_SOC", "ltg1_EOC", "ltg1_TF", "ltg1_FERST", "ltg1_RT", "ltg1_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg1_GAP1", "ltg1_GAP2", "ltg1_TPC_sync", "ltg1_TPC_rst", "ltg1_TOF", "ltg2_ORB", "ltg2_HB", "ltg2_HBr", "ltg2_HC", "ltg2_PH", "ltg2_PP", "ltg2_CAL", "ltg2_SOT", "ltg2_EOT", "ltg2_SOC", "ltg2_EOC", "ltg2_TF", "ltg2_FERST", "ltg2_RT", "ltg2_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg2_GAP1", "ltg2_GAP2", "ltg2_TPC_sync", "ltg2_TPC_rst", "ltg2_TOF", "ltg3_ORB", "ltg3_HB", "ltg3_HBr", "ltg3_HC", "ltg3_PH", "ltg3_PP", "ltg3_CAL", "ltg3_SOT", "ltg3_EOT", "ltg3_SOC", "ltg3_EOC", "ltg3_TF", "ltg3_FERST", "ltg3_RT", "ltg3_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg3_GAP1", "ltg3_GAP2", "ltg3_TPC_sync", "ltg3_TPC_rst", "ltg3_TOF", "ltg4_ORB", "ltg4_HB", "ltg4_HBr", "ltg4_HC", "ltg4_PH", "ltg4_PP", "ltg4_CAL", "ltg4_SOT", "ltg4_EOT", "ltg4_SOC", "ltg4_EOC", "ltg4_TF", "ltg4_FERST", "ltg4_RT", "ltg4_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg4_GAP1", "ltg4_GAP2", "ltg4_TPC_sync", "ltg4_TPC_rst", "ltg4_TOF", "ltg5_ORB", "ltg5_HB", "ltg5_HBr", "ltg5_HC", "ltg5_PH", "ltg5_PP", "ltg5_CAL", "ltg5_SOT", "ltg5_EOT", "ltg5_SOC", "ltg5_EOC", "ltg5_TF", "ltg5_FERST", "ltg5_RT", "ltg5_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg5_GAP1", "ltg5_GAP2", "ltg5_TPC_sync", "ltg5_TPC_rst", "ltg5_TOF", "ltg6_ORB", "ltg6_HB", "ltg6_HBr", "ltg6_HC", "ltg6_PH", "ltg6_PP", "ltg6_CAL", "ltg6_SOT", "ltg6_EOT", "ltg6_SOC", "ltg6_EOC", "ltg6_TF", "ltg6_FERST", "ltg6_RT", "ltg6_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg6_GAP1", "ltg6_GAP2", "ltg6_TPC_sync", "ltg6_TPC_rst", "ltg6_TOF", "ltg7_ORB", "ltg7_HB", "ltg7_HBr", "ltg7_HC", "ltg7_PH", "ltg7_PP", "ltg7_CAL", "ltg7_SOT", "ltg7_EOT", "ltg7_SOC", "ltg7_EOC", "ltg7_TF", "ltg7_FERST", "ltg7_RT", "ltg7_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg7_GAP1", "ltg7_GAP2", "ltg7_TPC_sync", "ltg7_TPC_rst", "ltg7_TOF", "ltg8_ORB", "ltg8_HB", "ltg8_HBr", "ltg8_HC", "ltg8_PH", "ltg8_PP", "ltg8_CAL", "ltg8_SOT", "ltg8_EOT", "ltg8_SOC", "ltg8_EOC", "ltg8_TF", "ltg8_FERST", "ltg8_RT", "ltg8_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg8_GAP1", "ltg8_GAP2", "ltg8_TPC_sync", "ltg8_TPC_rst", "ltg8_TOF", "ltg9_ORB", "ltg9_HB", "ltg9_HBr", "ltg9_HC", "ltg9_PH", "ltg9_PP", "ltg9_CAL", "ltg9_SOT", "ltg9_EOT", "ltg9_SOC", "ltg9_EOC", "ltg9_TF", "ltg9_FERST", "ltg9_RT", "ltg9_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg9_GAP1", "ltg9_GAP2", "ltg9_TPC_sync", "ltg9_TPC_rst", "ltg9_TOF", "ltg10_ORB", "ltg10_HB", "ltg10_HBr", "ltg10_HC", "ltg10_PH", "ltg10_PP", "ltg10_CAL", "ltg10_SOT", "ltg10_EOT", "ltg10_SOC", "ltg10_EOC", "ltg10_TF", "ltg10_FERST", "ltg10_RT", "ltg10_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg10_GAP1", "ltg10_GAP2", "ltg10_TPC_sync", "ltg10_TPC_rst", "ltg10_TOF", "ltg11_ORB", "ltg11_HB", "ltg11_HBr", "ltg11_HC", "ltg11_PH", "ltg11_PP", "ltg11_CAL", "ltg11_SOT", "ltg11_EOT", "ltg11_SOC", "ltg11_EOC", "ltg11_TF", "ltg11_FERST", "ltg11_RT", "ltg11_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg11_GAP1", "ltg11_GAP2", "ltg11_TPC_sync", "ltg11_TPC_rst", "ltg11_TOF", "ltg12_ORB", "ltg12_HB", "ltg12_HBr", "ltg12_HC", "ltg12_PH", "ltg12_PP", "ltg12_CAL", "ltg12_SOT", "ltg12_EOT", "ltg12_SOC", "ltg12_EOC", "ltg12_TF", "ltg12_FERST", "ltg12_RT", "ltg12_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg12_GAP1", "ltg12_GAP2", "ltg12_TPC_sync", "ltg12_TPC_rst", "ltg12_TOF", "ltg13_ORB", "ltg13_HB", "ltg13_HBr", "ltg13_HC", "ltg13_PH", "ltg13_PP", "ltg13_CAL", "ltg13_SOT", "ltg13_EOT", "ltg13_SOC", "ltg13_EOC", "ltg13_TF", "ltg13_FERST", "ltg13_RT", "ltg13_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg13_GAP1", "ltg13_GAP2", "ltg13_TPC_sync", "ltg13_TPC_rst", "ltg13_TOF", "ltg14_ORB", "ltg14_HB", "ltg14_HBr", "ltg14_HC", "ltg14_PH", "ltg14_PP", "ltg14_CAL", "ltg14_SOT", "ltg14_EOT", "ltg14_SOC", "ltg14_EOC", "ltg14_TF", "ltg14_FERST", "ltg14_RT", "ltg14_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg14_GAP1", "ltg14_GAP2", "ltg14_TPC_sync", "ltg14_TPC_rst", "ltg14_TOF", "ltg15_ORB", "ltg15_HB", "ltg15_HBr", "ltg15_HC", "ltg15_PH", "ltg15_PP", "ltg15_CAL", "ltg15_SOT", "ltg15_EOT", "ltg15_SOC", "ltg15_EOC", "ltg15_TF", "ltg15_FERST", "ltg15_RT", "ltg15_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg15_GAP1", "ltg15_GAP2", "ltg15_TPC_sync", "ltg15_TPC_rst", "ltg15_TOF", "ltg16_ORB", "ltg16_HB", "ltg16_HBr", "ltg16_HC", "ltg16_PH", "ltg16_PP", "ltg16_CAL", "ltg16_SOT", "ltg16_EOT", "ltg16_SOC", "ltg16_EOC", "ltg16_TF", "ltg16_FERST", "ltg16_RT", "ltg16_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg16_GAP1", "ltg16_GAP2", "ltg16_TPC_sync", "ltg16_TPC_rst", "ltg16_TOF", "ltg17_ORB", "ltg17_HB", "ltg17_HBr", "ltg17_HC", "ltg17_PH", "ltg17_PP", "ltg17_CAL", "ltg17_SOT", "ltg17_EOT", "ltg17_SOC", "ltg17_EOC", "ltg17_TF", "ltg17_FERST", "ltg17_RT", "ltg17_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg17_GAP1", "ltg17_GAP2", "ltg17_TPC_sync", "ltg17_TPC_rst", "ltg17_TOF", "ltg18_ORB", "ltg18_HB", "ltg18_HBr", "ltg18_HC", "ltg18_PH", "ltg18_PP", "ltg18_CAL", "ltg18_SOT", "ltg18_EOT", "ltg18_SOC", "ltg18_EOC", "ltg18_TF", "ltg18_FERST", "ltg18_RT", "ltg18_RS", "", "", "", "", "", "", "", "", "", "", "", "", "ltg18_GAP1", "ltg18_GAP2", "ltg18_TPC_sync", "ltg18_TPC_rst", "ltg18_TOF", "bc40", "clk240", "extorb", "PLSRin", "FastLMin", "BUSYin", "SPAREin", "inp1", "inp2", "inp3", "inp4", "inp5", "inp6", "inp7", "inp8", "inp9", "inp10", "inp11", "inp12", "inp13", "inp14", "inp15", "inp16", "inp17", "inp18", "inp19", "inp20", "inp21", "inp22", "inp23", "inp24", "inp25", "inp26", "inp27", "inp28", "inp29", "inp30", "inp31", "inp32", "inp33", "inp34", "inp35", "inp36", "inp37", "inp38", "inp39", "inp40", "inp41", "inp42", "inp43", "inp44", "inp45", "inp46", "inp47", "inp48", "clamb1", "clamb2", "clamb3", "clamb4", "clamb5", "clamb6", "clamb7", "clamb8", "clamb9", "clamb10", "clamb11", "clamb12", "clamb13", "clamb14", "clamb15", "clamb16", "clamb17", "clamb18", "clamb19", "clamb20", "clamb21", "clamb22", "clamb23", "clamb24", "clamb25", "clamb26", "clamb27", "clamb28", "clamb29", "clamb30", "clamb31", "clamb32", "clamb33", "clamb34", "clamb35", "clamb36", "clamb37", "clamb38", "clamb39", "clamb40", "clamb41", "clamb42", "clamb43", "clamb44", "clamb45", "clamb46", "clamb47", "clamb48", "clamb49", "clamb50", "clamb51", "clamb52", "clamb53", "clamb54", "clamb55", "clamb56", "clamb57", "clamb58", "clamb59", "clamb60", "clamb61", "clamb62", "clamb63", "clamb64", "clama1", "clama2", "clama3", "clama4", "clama5", "clama6", "clama7", "clama8", "clama9", "clama10", "clama11", "clama12", "clama13", "clama14", "clama15", "clama16", "clama17", "clama18", "clama19", "clama20", "clama21", "clama22", "clama23", "clama24", "clama25", "clama26", "clama27", "clama28", "clama29", "clama30", "clama31", "clama32", "clama33", "clama34", "clama35", "clama36", "clama37", "clama38", "clama39", "clama40", "clama41", "clama42", "clama43", "clama44", "clama45", "clama46", "clama47", "clama48", "clama49", "clama50", "clama51", "clama52", "clama53", "clama54", "clama55", "clama56", "clama57", "clama58", "clama59", "clama60", "clama61", "clama62", "clama63", "clama64", "cla0b1", "cla0b2", "cla0b3", "cla0b4", "cla0b5", "cla0b6", "cla0b7", "cla0b8", "cla0b9", "cla0b10", "cla0b11", "cla0b12", "cla0b13", "cla0b14", "cla0b15", "cla0b16", "cla0b17", "cla0b18", "cla0b19", "cla0b20", "cla0b21", "cla0b22", "cla0b23", "cla0b24", "cla0b25", "cla0b26", "cla0b27", "cla0b28", "cla0b29", "cla0b30", "cla0b31", "cla0b32", "cla0b33", "cla0b34", "cla0b35", "cla0b36", "cla0b37", "cla0b38", "cla0b39", "cla0b40", "cla0b41", "cla0b42", "cla0b43", "cla0b44", "cla0b45", "cla0b46", "cla0b47", "cla0b48", "cla0b49", "cla0b50", "cla0b51", "cla0b52", "cla0b53", "cla0b54", "cla0b55", "cla0b56", "cla0b57", "cla0b58", "cla0b59", "cla0b60", "cla0b61", "cla0b62", "cla0b63", "cla0b64", "cla0a1", "cla0a2", "cla0a3", "cla0a4", "cla0a5", "cla0a6", "cla0a7", "cla0a8", "cla0a9", "cla0a10", "cla0a11", "cla0a12", "cla0a13", "cla0a14", "cla0a15", "cla0a16", "cla0a17", "cla0a18", "cla0a19", "cla0a20", "cla0a21", "cla0a22", "cla0a23", "cla0a24", "cla0a25", "cla0a26", "cla0a27", "cla0a28", "cla0a29", "cla0a30", "cla0a31", "cla0a32", "cla0a33", "cla0a34", "cla0a35", "cla0a36", "cla0a37", "cla0a38", "cla0a39", "cla0a40", "cla0a41", "cla0a42", "cla0a43", "cla0a44", "cla0a45", "cla0a46", "cla0a47", "cla0a48", "cla0a49", "cla0a50", "cla0a51", "cla0a52", "cla0a53", "cla0a54", "cla0a55", "cla0a56", "cla0a57", "cla0a58", "cla0a59", "cla0a60", "cla0a61", "cla0a62", "cla0a63", "cla0a64", "cla1b1", "cla1b2", "cla1b3", "cla1b4", "cla1b5", "cla1b6", "cla1b7", "cla1b8", "cla1b9", "cla1b10", "cla1b11", "cla1b12", "cla1b13", "cla1b14", "cla1b15", "cla1b16", "cla1b17", "cla1b18", "cla1b19", "cla1b20", "cla1b21", "cla1b22", "cla1b23", "cla1b24", "cla1b25", "cla1b26", "cla1b27", "cla1b28", "cla1b29", "cla1b30", "cla1b31", "cla1b32", "cla1b33", "cla1b34", "cla1b35", "cla1b36", "cla1b37", "cla1b38", "cla1b39", "cla1b40", "cla1b41", "cla1b42", "cla1b43", "cla1b44", "cla1b45", "cla1b46", "cla1b47", "cla1b48", "cla1b49", "cla1b50", "cla1b51", "cla1b52", "cla1b53", "cla1b54", "cla1b55", "cla1b56", "cla1b57", "cla1b58", "cla1b59", "cla1b60", "cla1b61", "cla1b62", "cla1b63", "cla1b64", "cla1a1", "cla1a2", "cla1a3", "cla1a4", "cla1a5", "cla1a6", "cla1a7", "cla1a8", "cla1a9", "cla1a10", "cla1a11", "cla1a12", "cla1a13", "cla1a14", "cla1a15", "cla1a16", "cla1a17", "cla1a18", "cla1a19", "cla1a20", "cla1a21", "cla1a22", "cla1a23", "cla1a24", "cla1a25", "cla1a26", "cla1a27", "cla1a28", "cla1a29", "cla1a30", "cla1a31", "cla1a32", "cla1a33", "cla1a34", "cla1a35", "cla1a36", "cla1a37", "cla1a38", "cla1a39", "cla1a40", "cla1a41", "cla1a42", "cla1a43", "cla1a44", "cla1a45", "cla1a46", "cla1a47", "cla1a48", "cla1a49", "cla1a50", "cla1a51", "cla1a52", "cla1a53", "cla1a54", "cla1a55", "cla1a56", "cla1a57", "cla1a58", "cla1a59", "cla1a60", "cla1a61", "cla1a62", "cla1a63", "cla1a64", "l0_trigger", "l1_trigger", "l2_trigger", "clum1", "clum2", "clum3", "clum4", "clum5", "clum6", "clu01", "clu02", "clu03", "clu04", "clu05", "clu06", "clu11", "clu12", "clu13", "clu14", "clu15", "clu16", diff --git a/Detectors/CTP/macro/CMakeLists.txt b/Detectors/CTP/macro/CMakeLists.txt index 8aa0198adb065..052e1419cf9e6 100644 --- a/Detectors/CTP/macro/CMakeLists.txt +++ b/Detectors/CTP/macro/CMakeLists.txt @@ -61,3 +61,7 @@ o2_add_test_root_macro(PlotPbLumi.C PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP O2::CCDB LABELS ctp) +o2_add_test_root_macro(PlotOrbit.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP + O2::CCDB + LABELS ctp) diff --git a/Detectors/CTP/macro/GetScalersForRun.C b/Detectors/CTP/macro/GetScalersForRun.C index d1b977139ab02..a3fd33b02252e 100644 --- a/Detectors/CTP/macro/GetScalersForRun.C +++ b/Detectors/CTP/macro/GetScalersForRun.C @@ -12,6 +12,7 @@ #if !defined(__CLING__) || defined(__ROOTCLING__) #include #include +#include "ctpRateFetcher.h" #endif using namespace o2::ctp; @@ -34,7 +35,7 @@ void GetScalersForRun(int runNumber = 0, int fillN = 0, bool test = 1) std::string sfill = std::to_string(fillN); std::map metadata; metadata["fillNumber"] = sfill; - auto lhcifdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); + auto lhcifdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp); auto bfilling = lhcifdata->getBunchFilling(); std::vector bcs = bfilling.getFilledBCs(); std::cout << "Number of interacting bc:" << bcs.size() << std::endl; @@ -82,7 +83,8 @@ void GetScalersForRun(int runNumber = 0, int fillN = 0, bool test = 1) vch = cls.getIndex(); std::cout << cls.name << ":" << vch << std::endl; } - if (cls.name.find("C1ZNC-B-NOPF-CRU") != std::string::npos) { + // if (cls.name.find("C1ZNC-B-NOPF-CRU") != std::string::npos) { + if (cls.name.find("C1ZNC-B-NOPF") != std::string::npos) { iznc = cls.getIndex(); std::cout << cls.name << ":" << iznc << std::endl; } @@ -126,7 +128,11 @@ void GetScalersForRun(int runNumber = 0, int fillN = 0, bool test = 1) } if (iznc != 255) { std::cout << "ZNC class:"; - int64_t integral = recs[recs.size() - 1].scalers[iznc].l1After - recs[0].scalers[iznc].l1After; - std::cout << integral << std::endl; + // uint64_t integral = recs[recs.size() - 1].scalers[iznc].l1After - recs[0].scalers[iznc].l1After; + auto zncrate = ctpscalers->getRateGivenT(0, iznc, 6); + std::cout << "ZNC class rate:" << zncrate.first / 28. << std::endl; + } else { + std::cout << "ZNC class not available" << std::endl; } + // ctpRateFetcher ctprate; } diff --git a/Detectors/CTP/macro/PlotOrbit.C b/Detectors/CTP/macro/PlotOrbit.C new file mode 100644 index 0000000000000..c83263ea4f93c --- /dev/null +++ b/Detectors/CTP/macro/PlotOrbit.C @@ -0,0 +1,94 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file TestCTPScalers.C +/// \brief create CTP scalers, test it and add to database +/// \author Roman Lietava +// root -b -q "GetScalers.C(\"519499\", 1656286373953)" +#if !defined(__CLING__) || defined(__ROOTCLING__) + +#include +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCTP/Scalers.h" +#include "DataFormatsCTP/Configuration.h" +#include +#include +#include +#endif +//"http://ccdb-test.cern.ch:8080" +using namespace o2::ctp; +void PlotOrbit(int runNumber) +{ // + std::string mCCDBPathCTPScalers = "CTP/Calib/Scalers"; + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + // Timestamp + auto soreor = ccdbMgr.getRunDuration(runNumber); + uint64_t timeStamp = (soreor.second - soreor.first) / 2 + soreor.first; + std::cout << "Timestamp:" << timeStamp << std::endl; + // Scalers + std::string srun = std::to_string(runNumber); + std::map metadata; + metadata["runNumber"] = srun; + // ccdbMgr.setURL("http://ccdb-test.cern.ch:8080"); + auto scl = ccdbMgr.getSpecific(mCCDBPathCTPScalers, timeStamp, metadata); + if (scl == nullptr) { + LOG(info) << "CTPRunScalers not in database, timestamp:" << timeStamp; + return; + } + scl->convertRawToO2(); + std::vector recs = scl->getScalerRecordO2(); + // + // + // Anal + // + // Times + int64_t time0 = recs[0].epochTime; + int64_t timeL = recs[recs.size() - 1].epochTime; + double_t Trun = timeL - time0; + // double_t orbit0 = recs[0].intRecord.orbit; + int64_t orbit0 = scl->getOrbitLimit().first; + int64_t orbitL = scl->getOrbitLimit().second; + int n = recs.size() - 1; + std::cout << " Run duration:" << Trun << " Scalers size:" << n + 1 << std::endl; + Double_t x[n], orbit[n]; + // Double_t tcetsctoznc[n], tcetoznc[n], vchtoznc[n]; + for (int i = 0; i < n; i++) { + // x[i] = i; + x[i] = recs[i + 1].epochTime - time0; + orbit[i] = recs[i + 1].intRecord.orbit - orbit0; + } + // + gStyle->SetMarkerSize(0.5); + TGraph* gr1 = new TGraph(n, x, orbit); + // TGraph* gr2 = new TGraph(n, x, tcetsctoznc); + // TGraph* gr3 = new TGraph(n, x, tcetoznc); + // TGraph* gr4 = new TGraph(n, x, vchtoznc); + gr1->SetMarkerStyle(20); + // gr2->SetMarkerStyle(21); + // gr3->SetMarkerStyle(23); + // gr4->SetMarkerStyle(23); + std::string title = "Orbit vs EpochTime for run " + srun + " ;EpochTime[s]; Orbit"; + gr1->SetTitle(title.c_str()); + // gr2->SetTitle("R=(TSC+TCE)*TVTX*B*28/ZNC; time[sec]; R"); + // gr2->GetHistogram()->SetMaximum(1.1); + // gr2->GetHistogram()->SetMinimum(0.9); + // gr3->SetTitle("R=(TCE)*TVTX*B*28/ZNC; time[sec]; R"); + // gr3->GetHistogram()->SetMaximum(0.6); + // gr3->GetHistogram()->SetMinimum(0.4); + // gr4->SetTitle("R=(VCH)*TVTX*B*28/ZNC; time[sec]; R"); + // gr4->GetHistogram()->SetMaximum(0.6); + // gr4->GetHistogram()->SetMinimum(0.4); + TCanvas* c1 = new TCanvas("c1", srun.c_str(), 200, 10, 800, 500); + gr1->Draw("AP"); + std::cout << "epoch0:" << time0 << " epochL:" << timeL << " T:" << Trun << std::endl; + std::cout << "orbit0:" << orbit0 << " orbitL:" << orbitL << " T:" << (orbitL - orbit0) * 88e-6 << std::endl; +} diff --git a/Detectors/CTP/workflowScalers/CMakeLists.txt b/Detectors/CTP/workflowScalers/CMakeLists.txt index 716da7e596482..672bf328212cb 100644 --- a/Detectors/CTP/workflowScalers/CMakeLists.txt +++ b/Detectors/CTP/workflowScalers/CMakeLists.txt @@ -1,3 +1,13 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. o2_add_executable( proxy COMPONENT_NAME ctp @@ -10,3 +20,9 @@ o2_add_executable( SOURCES src/ctp-qc-proxy.cxx PUBLIC_LINK_LIBRARIES O2::DCStestWorkflow O2::DataFormatsCTP) +o2_add_executable( + ccdb-orbit + COMPONENT_NAME ctp + SOURCES src/ctp-ccdb-orbit.cxx + PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP + Boost::program_options) diff --git a/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx b/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx new file mode 100644 index 0000000000000..56f58f946fd22 --- /dev/null +++ b/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx @@ -0,0 +1,139 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// example to run: +// +#include +#include +#include +#include +#include "CommonUtils/StringUtils.h" +#include +#include +#include +#include +namespace bpo = boost::program_options; +// +// get object from ccdb auto pp = ccdbMgr.getSpecific>("CTP/Calib/OrbitResetTest") +int main(int argc, char** argv) +{ + const std::string testCCDB = "http://ccdb-test.cern.ch:8080"; + const std::string prodCCDB = "http://o2-ccdb.internal"; + bpo::variables_map vm; + bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) + + " Write orbit staff to ccdb\n"); + bpo::options_description opt_hidden(""); + bpo::options_description opt_all; + bpo::positional_options_description opt_pos; + try { + auto add_option = opt_general.add_options(); + add_option("help,h", "Print this help message"); + add_option("output-file,o", bpo::value()->default_value("none"), "output file name, none - file not created"); + add_option("output-dir,d", bpo::value()->default_value("./"), "output dir"); + add_option("ccdb", bpo::value()->default_value("test"), "choose databse: test- test ccdb; prod - production ccdb; else ccdb parameter"); + add_option("action,a", bpo::value()->default_value(""), "sox - first orbit otherwise orbit reset"); + add_option("run-number,r", bpo::value()->default_value(123), "run number"); + add_option("testReset,t", bpo::value()->default_value(0), "0 = CTP/Calib/OrbitReset; 1 = CTP/Calib/OrbitResetTest"); + add_option("sox-orbit,x", bpo::value()->default_value(0), "SOX orbit"); + + // + opt_all.add(opt_general).add(opt_hidden); + bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm); + if (vm.count("help")) { + std::cout << opt_general << std::endl; + exit(0); + } + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << "ERROR: " << e.what() << std::endl + << std::endl; + std::cerr << opt_general << std::endl; + exit(1); + } catch (std::exception& e) { + std::cerr << e.what() << ", application will now exit" << std::endl; + exit(2); + } + std::string action = vm["action"].as(); + std::vector vect; + std::string ccdbPath; + auto now = std::chrono::system_clock::now(); + long tt = std::chrono::duration_cast(now.time_since_epoch()).count(); + if (action == "sox") { + // write to CTP/Calib/FirstRunOrbit + std::cout << "===> FirsRunOrbit" << std::endl; + vect.push_back(tt); + vect.push_back(vm["run-number"].as()); + vect.push_back(vm["sox-orbit"].as()); + ccdbPath = "CTP/Calib/FirstRunOrbit"; + } else { + // write to CTP/Calib/OrbitReset + std::cout << "===> ResetOrbit" << std::endl; + vect.push_back(tt); + ccdbPath = "CTP/Calib/OrbitReset"; + if (vm["testReset"].as()) { + ccdbPath += "Test"; + } + } + // + std::string ccdbAddress; + if (vm["ccdb"].as() == "prod") { + ccdbAddress = prodCCDB; + } else if (vm["ccdb"].as() == "test") { + ccdbAddress = testCCDB; + } else { + ccdbAddress = vm["ccdb"].as(); + } + std::cout << " Writing to db:" << ccdbAddress << std::endl; + if (ccdbAddress != "none") { + // auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + o2::ccdb::CcdbApi api; + api.init(ccdbAddress.c_str()); + std::map metadata; + long tmin = tt; + long tmax = tmin + 381928219; + if (action == "sox") { + int64_t runnum = vm["run-number"].as(); + metadata["runNumber"] = std::to_string(runnum); + std::cout << "Storing:" << ccdbPath << " " << metadata["runNumber"] << " tmin:" << tmin << " tmax:" << tmax << std::endl; + api.storeAsTFileAny(&(vect), ccdbPath, metadata, tmin, tmax); + } else { + std::cout << "Storing:" << ccdbPath << " tmin:" << tmin << " tmax:" << tmax << std::endl; + api.storeAsTFileAny(&(vect), ccdbPath, metadata, tmin, tmax); + } + } + // + if (vm["output-file"].as() != "none") { + std::string file = vm["output-dir"].as() + vm["output-file"].as(); + TFile* f = TFile::Open(file.c_str(), "RECREATE"); + if (f == nullptr) { + std::cout << "Error: File" << file << " could not be open for writing !!!" << std::endl; + return 1; + } else { + std::cout << "File" << file << " being writen." << std::endl; + f->WriteObject(&vect, "ccdb_object"); + f->Close(); + } + } else { + std::cout << "No file created" << std::endl; + } + return 0; +} From a3542ea03f009b6fb9910185731957ed97dbc03d Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Fri, 9 Feb 2024 23:38:23 +0100 Subject: [PATCH 15/50] DPL Analysis: support both 17 and 20 c++std for type_name() (#12674) --- .../Foundation/include/Framework/TypeIdHelpers.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Framework/Foundation/include/Framework/TypeIdHelpers.h b/Framework/Foundation/include/Framework/TypeIdHelpers.h index 82203fad66d7b..d4f72b8f3f7ff 100644 --- a/Framework/Foundation/include/Framework/TypeIdHelpers.h +++ b/Framework/Foundation/include/Framework/TypeIdHelpers.h @@ -14,12 +14,14 @@ #include #include +#if __cplusplus >= 202002L #include +#endif #include "Framework/StringHelpers.h" namespace o2::framework { -#ifdef __CLING__ +#if defined(__CLING__) || __cplusplus < 202002L template struct unique_type_id { static constexpr auto get() noexcept @@ -35,7 +37,7 @@ template inline constexpr auto unique_type_id_v = unique_type_id::value; #endif -#ifndef __CLING__ +#if !defined(__CLING__) && __cplusplus >= 202002L /// Workaround GCC optimizing out unused template parameter template consteval static std::string_view type_name_impl(T*) @@ -49,17 +51,18 @@ consteval static std::string_view type_name_impl(T*) template constexpr static std::string_view type_name() { -#ifdef __CLING__ +#if defined(__CLING__) || __cplusplus < 202002L constexpr std::string_view wrapped_name{unique_type_id_v}; #else constexpr std::string_view wrapped_name = type_name_impl(nullptr); #endif const std::string_view left_marker{"T = "}; -#ifdef __clang__ - const std::string_view right_marker{"]"}; -#else +#if !defined(__clang__) && __cplusplus >= 202002L const std::string_view right_marker{";"}; +#else + const std::string_view right_marker{"]"}; #endif + const auto left_marker_index = wrapped_name.find(left_marker); const auto start_index = left_marker_index + left_marker.size(); const auto end_index = wrapped_name.find(right_marker, left_marker_index); From 4486909abcad78e6742a228ed53751942d89333d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 10 Feb 2024 09:25:41 +0100 Subject: [PATCH 16/50] DPL: keep code checker happy --- Framework/DataInspector/src/DataInspector.cxx | 4 ++-- Framework/DataInspector/src/DataInspector.h | 4 ++-- Framework/DataInspector/src/DataInspectorService.cxx | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Framework/DataInspector/src/DataInspector.cxx b/Framework/DataInspector/src/DataInspector.cxx index a38b173cdd22b..b948d969f4d10 100644 --- a/Framework/DataInspector/src/DataInspector.cxx +++ b/Framework/DataInspector/src/DataInspector.cxx @@ -44,7 +44,7 @@ using namespace rapidjson; -namespace o2::framework::DataInspector +namespace o2::framework::data_inspector { #if BOOST_ENDIAN_BIG_BYTE static const auto endianness = "BIG"; @@ -147,4 +147,4 @@ std::vector serializeO2Messages(const std::vector& refs, con return messages; } -} // namespace o2::framework::DataInspector +} // namespace o2::framework::data_inspector diff --git a/Framework/DataInspector/src/DataInspector.h b/Framework/DataInspector/src/DataInspector.h index 27c9987a45081..5e28f6bb3853b 100644 --- a/Framework/DataInspector/src/DataInspector.h +++ b/Framework/DataInspector/src/DataInspector.h @@ -20,7 +20,7 @@ #include -namespace o2::framework::DataInspector +namespace o2::framework::data_inspector { inline bool isNonInternalDevice(const DeviceSpec& spec) { @@ -28,6 +28,6 @@ inline bool isNonInternalDevice(const DeviceSpec& spec) } std::vector serializeO2Messages(const std::vector& refs, const std::string& deviceName); -} // namespace o2::framework::DataInspector +} // namespace o2::framework::data_inspector #endif // O2_DATAINSPECTOR_H diff --git a/Framework/DataInspector/src/DataInspectorService.cxx b/Framework/DataInspector/src/DataInspectorService.cxx index 40399a366a303..661065da35ff6 100644 --- a/Framework/DataInspector/src/DataInspectorService.cxx +++ b/Framework/DataInspector/src/DataInspectorService.cxx @@ -205,7 +205,7 @@ ServiceSpec* DIServicePlugin::create() std::string runId = std::getenv("O2_DATAINSPECTOR_ID"); const auto& spec = services.get(); - if (DataInspector::isNonInternalDevice(spec)) { + if (data_inspector::isNonInternalDevice(spec)) { auto* diService = new DataInspectorProxyService(services, spec, proxyAddress, proxyPort, runId); return ServiceHandle{TypeIdHelpers::uniqueId(), diService}; } else { @@ -238,11 +238,11 @@ ServiceSpec* DIServicePlugin::create() } // Send copy to proxy - auto proxyMessages = DataInspector::serializeO2Messages(refs, registry.get < DeviceSpec const>().name); + auto proxyMessages = data_inspector::serializeO2Messages(refs, registry.get().name); for (auto &proxyMessage: proxyMessages) { diService.send(std::move(proxyMessage)); } } }, .kind = ServiceKind::Global}; }; -} // namespace o2::framework \ No newline at end of file +} // namespace o2::framework From ed1abe3ceabc64bc07249db062094906ef23cf4e Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 9 Feb 2024 19:03:21 +0100 Subject: [PATCH 17/50] In W-FLOW=print mode dump sources to help with MC configuration --- prodtests/full-system-test/dpl-workflow.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 70b2dcf306f6e..3c26916bece47 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -93,7 +93,7 @@ INTERACTION_TAG_CONFIG_KEY= : ${ITSEXTRAERR:=} : ${TRACKTUNETPCINNER:=} : ${ITSTPC_CONFIG_KEY:=} -: ${AOD_INPUT:=$TRACK_SOURCES} +: ${AOD_SOURCES:=$TRACK_SOURCES} : ${AODPROD_OPT:=} [[ "0$DISABLE_ROOT_OUTPUT" == "00" ]] && DISABLE_ROOT_OUTPUT= @@ -599,7 +599,7 @@ workflow_has_parameter GPU_DISPLAY && [[ $NUMAID == 0 ]] && add_W o2-gpu-display # AOD [[ ${SECTVTX_ON:-} != "1" ]] && AODPROD_OPT+=" --disable-secondary-vertices " AODPROD_OPT+=" $STRTRACKING " -workflow_has_parameter AOD && [[ ! -z "$AOD_INPUT" ]] && add_W o2-aod-producer-workflow "$AODPROD_OPT --info-sources $AOD_INPUT $DISABLE_ROOT_INPUT --aod-writer-keep dangling --aod-writer-resfile \"AO2D\" --aod-writer-resmode UPDATE $DISABLE_MC --pipeline $(get_N aod-producer-workflow AOD REST 1 AODPROD)" +workflow_has_parameter AOD && [[ ! -z "$AOD_SOURCES" ]] && add_W o2-aod-producer-workflow "$AODPROD_OPT --info-sources $AOD_SOURCES $DISABLE_ROOT_INPUT --aod-writer-keep dangling --aod-writer-resfile \"AO2D\" --aod-writer-resmode UPDATE $DISABLE_MC --pipeline $(get_N aod-producer-workflow AOD REST 1 AODPROD)" # extra workflows in case we want to extra ITS/MFT info for dead channel maps to then go to CCDB for MC : ${ALIEN_JDL_PROCESSITSDEADMAP:=} @@ -650,7 +650,19 @@ if [[ "${FST_BENCHMARK_STARTUP:-}" == "1" ]]; then eval $WORKFLOW2 else [[ $WORKFLOWMODE != "print" ]] && WORKFLOW+=" --${WORKFLOWMODE} ${WORKFLOWMODE_FILE:-}" - [[ $WORKFLOWMODE == "print" || ${PRINT_WORKFLOW:-} == "1" ]] && echo "#Workflow command:\n\n${WORKFLOW}\n" | sed -e "s/\\\\n/\n/g" -e"s/| */| \\\\\n/g" | eval cat $( [[ $WORKFLOWMODE == "dds" ]] && echo '1>&2') + if [[ $WORKFLOWMODE == "print" || ${PRINT_WORKFLOW:-} == "1" ]] ; then + echo "# defined detectors and sources: " + echo "#export WORKFLOW_DETECTORS=$WORKFLOW_DETECTORS" + echo "#export TRD_SOURCES=$TRD_SOURCES" + echo "#export TOF_SOURCES=$TOF_SOURCES" + echo "#export HMP_SOURCES=$HMP_SOURCES" + echo "#export TRACK_SOURCES=$TRACK_SOURCES" + echo "#export VERTEXING_SOURCES=$VERTEXING_SOURCES" + echo "#export VERTEX_TRACK_MATCHING_SOURCES=$VERTEX_TRACK_MATCHING_SOURCES" + echo "#export SVERTEXING_SOURCES=$SVERTEXING_SOURCES" + echo "#export AOD_SOURCES=$AOD_SOURCES" + echo "\n\n#Workflow command:\n\n${WORKFLOW}\n" | sed -e "s/\\\\n/\n/g" -e"s/| */| \\\\\n/g" | eval cat $( [[ $WORKFLOWMODE == "dds" ]] && echo '1>&2') + fi if [[ $WORKFLOWMODE != "print" ]]; then eval $WORKFLOW; else true; fi fi From ba1b788decb1726e4b68c18fe8cbf83bb49a57b8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 10 Feb 2024 01:17:29 +0100 Subject: [PATCH 18/50] DPL: use the SendingPolicy for every kind of message sending --- .../Core/include/Framework/ChannelInfo.h | 4 + .../include/Framework/DataProcessingHelpers.h | 22 +++--- Framework/Core/include/Framework/DriverInfo.h | 3 + .../Core/include/Framework/ForwardRoute.h | 9 ++- .../Core/include/Framework/SendingPolicy.h | 9 +++ Framework/Core/src/CommonServices.cxx | 10 +-- Framework/Core/src/DataProcessingDevice.cxx | 24 +++--- Framework/Core/src/DataProcessingHelpers.cxx | 41 +++++----- Framework/Core/src/DeviceSpecHelpers.cxx | 35 ++++++--- Framework/Core/src/DeviceSpecHelpers.h | 5 +- .../Core/src/ExternalFairMQDeviceProxy.cxx | 17 +++- Framework/Core/src/FairMQDeviceProxy.cxx | 3 +- Framework/Core/src/SendingPolicy.cxx | 77 +++++++++++++++++++ Framework/Core/src/runDataProcessing.cxx | 3 + Framework/Core/test/test_DeviceSpec.cxx | 6 +- Utilities/DataSampling/src/Dispatcher.cxx | 3 +- 16 files changed, 194 insertions(+), 77 deletions(-) diff --git a/Framework/Core/include/Framework/ChannelInfo.h b/Framework/Core/include/Framework/ChannelInfo.h index 0ebc4a8506301..1f4bd8bc9e90e 100644 --- a/Framework/Core/include/Framework/ChannelInfo.h +++ b/Framework/Core/include/Framework/ChannelInfo.h @@ -67,6 +67,7 @@ struct InputChannelInfo { }; struct SendingPolicy; +struct ForwardingPolicy; /// Output channel information struct OutputChannelInfo { @@ -74,6 +75,7 @@ struct OutputChannelInfo { ChannelAccountingType channelType = ChannelAccountingType::DPL; fair::mq::Channel& channel; SendingPolicy const* policy; + ChannelIndex index = {-1}; }; struct OutputChannelState { @@ -89,6 +91,8 @@ struct ForwardChannelInfo { /// Wether or not it's a DPL internal channel. ChannelAccountingType channelType = ChannelAccountingType::DPL; fair::mq::Channel& channel; + ForwardingPolicy const* policy; + ChannelIndex index = {-1}; }; struct ForwardChannelState { diff --git a/Framework/Core/include/Framework/DataProcessingHelpers.h b/Framework/Core/include/Framework/DataProcessingHelpers.h index 35f78f12cc405..7a05ddf25c46c 100644 --- a/Framework/Core/include/Framework/DataProcessingHelpers.h +++ b/Framework/Core/include/Framework/DataProcessingHelpers.h @@ -11,14 +11,16 @@ #ifndef O2_FRAMEWORK_DATAPROCESSINGHELPERS_H_ #define O2_FRAMEWORK_DATAPROCESSINGHELPERS_H_ -#include "Framework/TimesliceIndex.h" -#include +#include namespace o2::framework { - +struct ServiceRegistryRef; +struct ForwardChannelInfo; +struct ForwardChannelState; +struct OutputChannelInfo; struct OutputChannelSpec; -class FairMQDeviceProxy; +struct OutputChannelState; /// Generic helpers for DataProcessing releated functions. struct DataProcessingHelpers { @@ -26,15 +28,13 @@ struct DataProcessingHelpers { /// @param device the fair::mq::Device which needs to send the EndOfStream message /// @param channel the OutputChannelSpec of the channel which needs to be signaled /// for EndOfStream - static void sendEndOfStream(fair::mq::Device& device, OutputChannelSpec const& channel); + static void sendEndOfStream(ServiceRegistryRef const& ref, OutputChannelSpec const& channel); /// @returns true if we did send the oldest possible timeslice message, false otherwise. - static bool sendOldestPossibleTimeframe(ForwardChannelInfo const& info, ForwardChannelState& state, size_t timeslice); + static bool sendOldestPossibleTimeframe(ServiceRegistryRef const& ref, ForwardChannelInfo const& info, ForwardChannelState& state, size_t timeslice); /// @returns true if we did send the oldest possible timeslice message, false otherwise. - static bool sendOldestPossibleTimeframe(OutputChannelInfo const& info, OutputChannelState& state, size_t timeslice); - static void broadcastOldestPossibleTimeslice(FairMQDeviceProxy& proxy, size_t timeslice); - - private: - static void sendOldestPossibleTimeframe(fair::mq::Channel& channel, size_t timeslice); + static bool sendOldestPossibleTimeframe(ServiceRegistryRef const& ref, OutputChannelInfo const& info, OutputChannelState& state, size_t timeslice); + /// Broadcast the oldest possible timeslice to all channels in output + static void broadcastOldestPossibleTimeslice(ServiceRegistryRef const& ref, size_t timeslice); }; } // namespace o2::framework diff --git a/Framework/Core/include/Framework/DriverInfo.h b/Framework/Core/include/Framework/DriverInfo.h index 043a689087325..45c4c85a32d01 100644 --- a/Framework/Core/include/Framework/DriverInfo.h +++ b/Framework/Core/include/Framework/DriverInfo.h @@ -111,6 +111,9 @@ struct DriverInfo { /// These are the policies which can be applied to decide how /// we send data. std::vector sendingPolicies; + /// These are the policies which can be applied to decide how + /// we forward data. + std::vector forwardingPolicies; /// The argc with which the driver was started. int argc; /// The argv with which the driver was started. diff --git a/Framework/Core/include/Framework/ForwardRoute.h b/Framework/Core/include/Framework/ForwardRoute.h index bae2eaacf1a44..0e3d4d12da24a 100644 --- a/Framework/Core/include/Framework/ForwardRoute.h +++ b/Framework/Core/include/Framework/ForwardRoute.h @@ -15,11 +15,11 @@ #include #include -namespace o2 -{ -namespace framework +namespace o2::framework { +struct ForwardingPolicy; + /// This uniquely identifies a route to be forwarded by the device if /// the InputSpec @a matcher matches an input which should also go to /// @a channel @@ -28,8 +28,9 @@ struct ForwardRoute { size_t maxTimeslices; InputSpec matcher; std::string channel; + // The policy to use to send to on this route. + ForwardingPolicy const* policy; }; -} // namespace framework } // namespace o2 #endif // FRAMEWORK_FORWARDROUTE_H diff --git a/Framework/Core/include/Framework/SendingPolicy.h b/Framework/Core/include/Framework/SendingPolicy.h index 1d68412d46db8..7cc5c16e2c923 100644 --- a/Framework/Core/include/Framework/SendingPolicy.h +++ b/Framework/Core/include/Framework/SendingPolicy.h @@ -32,6 +32,15 @@ struct SendingPolicy { static std::vector createDefaultPolicies(); }; +struct ForwardingPolicy { + using ForwardingCallback = std::function; + std::string name = "invalid"; + EdgeMatcher matcher = nullptr; + ForwardingCallback forward = nullptr; + static std::vector createDefaultPolicies(); + static ForwardingPolicy createDefaultForwardingPolicy(); +}; + } // namespace o2::framework #endif // O2_FRAMEWORK_SENDINGPOLICY_H_ diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index b7fc3410a1931..a0f7fcdc88201 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -588,7 +588,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() timesliceIndex.rescan(); } } - DataProcessingHelpers::broadcastOldestPossibleTimeslice(proxy, oldestPossibleOutput.timeslice.value); + DataProcessingHelpers::broadcastOldestPossibleTimeslice(ctx.services(), oldestPossibleOutput.timeslice.value); for (int fi = 0; fi < proxy.getNumForwardChannels(); fi++) { auto& info = proxy.getForwardChannelInfo(ChannelIndex{fi}); @@ -598,7 +598,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Skipping channel %{public}s", info.name.c_str()); continue; } - if (DataProcessingHelpers::sendOldestPossibleTimeframe(info, state, oldestPossibleOutput.timeslice.value)) { + if (DataProcessingHelpers::sendOldestPossibleTimeframe(ctx.services(), info, state, oldestPossibleOutput.timeslice.value)) { O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Forwarding to channel %{public}s oldest possible timeslice %" PRIu64 ", priority %d", info.name.c_str(), (uint64_t)oldestPossibleOutput.timeslice.value, 20); @@ -646,7 +646,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Queueing oldest possible timeslice %" PRIu64 " propagation for execution.", (uint64_t)oldestPossibleOutput.timeslice.value); AsyncQueueHelpers::post( - queue, decongestion.oldestPossibleTimesliceTask, [oldestPossibleOutput, &decongestion, &proxy, &spec, device, ×liceIndex]() { + queue, decongestion.oldestPossibleTimesliceTask, [ref = services, oldestPossibleOutput, &decongestion, &proxy, &spec, device, ×liceIndex]() { O2_SIGNPOST_ID_FROM_POINTER(cid, data_processor_context, &decongestion); if (decongestion.lastTimeslice >= oldestPossibleOutput.timeslice.value) { O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Not sending already sent value: %" PRIu64 "> %" PRIu64, @@ -655,7 +655,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() } O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Running oldest possible timeslice %" PRIu64 " propagation.", (uint64_t)oldestPossibleOutput.timeslice.value); - DataProcessingHelpers::broadcastOldestPossibleTimeslice(proxy, oldestPossibleOutput.timeslice.value); + DataProcessingHelpers::broadcastOldestPossibleTimeslice(ref, oldestPossibleOutput.timeslice.value); for (int fi = 0; fi < proxy.getNumForwardChannels(); fi++) { auto& info = proxy.getForwardChannelInfo(ChannelIndex{fi}); @@ -665,7 +665,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Skipping channel %{public}s", info.name.c_str()); continue; } - if (DataProcessingHelpers::sendOldestPossibleTimeframe(info, state, oldestPossibleOutput.timeslice.value)) { + if (DataProcessingHelpers::sendOldestPossibleTimeframe(ref, info, state, oldestPossibleOutput.timeslice.value)) { O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Forwarding to channel %{public}s oldest possible timeslice %" PRIu64 ", priority %d", info.name.c_str(), (uint64_t)oldestPossibleOutput.timeslice.value, 20); diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 8c914e201a479..50934bd59a729 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -680,19 +680,15 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, if (forwardedParts[fi].Size() == 0) { continue; } - auto channel = proxy.getForwardChannel(ChannelIndex{fi}); - LOG(debug) << "Forwarding to " << channel->GetName() << " " << fi; + ForwardChannelInfo info = proxy.getForwardChannelInfo(ChannelIndex{fi}); + LOG(debug) << "Forwarding to " << info.name << " " << fi; // in DPL we are using subchannel 0 only auto& parts = forwardedParts[fi]; - int timeout = 30000; - auto res = channel->Send(parts, timeout); - if (res == (size_t)fair::mq::TransferCode::timeout) { - LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on {}.", timeout / 1000, channel->GetName()); - channel->Send(parts); - LOGP(info, "Downstream backpressure on {} recovered.", channel->GetName()); - } else if (res == (size_t)fair::mq::TransferCode::error) { - LOGP(fatal, "Error while sending on channel {}", channel->GetName()); + if (info.policy == nullptr) { + LOG(error) << "Forwarding to " << info.name << " " << fi << " has no policy"; + continue; } + info.policy->forward(parts, ChannelIndex{fi}, registry); } auto& asyncQueue = registry.get(); @@ -713,7 +709,7 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, LOG(debug) << "Skipping channel"; continue; } - if (DataProcessingHelpers::sendOldestPossibleTimeframe(info, state, oldestTimeslice.timeslice.value)) { + if (DataProcessingHelpers::sendOldestPossibleTimeframe(registry, info, state, oldestTimeslice.timeslice.value)) { LOGP(debug, "Forwarding to channel {} oldest possible timeslice {}, prio 20", info.name, oldestTimeslice.timeslice.value); } } @@ -1678,8 +1674,7 @@ void DataProcessingDevice::doRun(ServiceRegistryRef ref) for (auto& channel : spec.outputChannels) { LOGP(detail, "Sending end of stream to {}", channel.name); - auto& rawDevice = ref.get(); - DataProcessingHelpers::sendEndOfStream(*rawDevice.device(), channel); + DataProcessingHelpers::sendEndOfStream(ref, channel); } // This is needed because the transport is deleted before the device. relayer.clear(); @@ -2460,8 +2455,7 @@ bool DataProcessingDevice::tryDispatchComputation(ServiceRegistryRef ref, std::v if (state.streaming == StreamingState::EndOfStreaming) { LOGP(detail, "Broadcasting end of stream"); for (auto& channel : spec.outputChannels) { - auto& rawDevice = ref.get(); - DataProcessingHelpers::sendEndOfStream(*rawDevice.device(), channel); + DataProcessingHelpers::sendEndOfStream(ref, channel); } switchState(StreamingState::Idle); } diff --git a/Framework/Core/src/DataProcessingHelpers.cxx b/Framework/Core/src/DataProcessingHelpers.cxx index d424a53a52bd9..58fda5a13bae9 100644 --- a/Framework/Core/src/DataProcessingHelpers.cxx +++ b/Framework/Core/src/DataProcessingHelpers.cxx @@ -18,79 +18,74 @@ #include "Headers/DataHeader.h" #include "Headers/Stack.h" #include "Framework/Logger.h" +#include "Framework/SendingPolicy.h" +#include "Framework/RawDeviceService.h" #include #include namespace o2::framework { -void DataProcessingHelpers::sendEndOfStream(fair::mq::Device& device, OutputChannelSpec const& channel) +void DataProcessingHelpers::sendEndOfStream(ServiceRegistryRef const& ref, OutputChannelSpec const& channel) { + fair::mq::Device* device = ref.get().device(); fair::mq::Parts parts; - fair::mq::MessagePtr payload(device.NewMessage()); + fair::mq::MessagePtr payload(device->NewMessage()); SourceInfoHeader sih; sih.state = InputChannelState::Completed; - auto channelAlloc = o2::pmr::getTransportAllocator(device.GetChannel(channel.name, 0).Transport()); + auto channelAlloc = o2::pmr::getTransportAllocator(device->GetChannel(channel.name, 0).Transport()); auto header = o2::pmr::getMessage(o2::header::Stack{channelAlloc, sih}); // sigh... See if we can avoid having it const by not // exposing it to the user in the first place. parts.AddPart(std::move(header)); parts.AddPart(std::move(payload)); - device.Send(parts, channel.name, 0); + device->Send(parts, channel.name, 0); LOGP(info, "Sending end-of-stream message to channel {}", channel.name); } -void DataProcessingHelpers::sendOldestPossibleTimeframe(fair::mq::Channel& channel, size_t timeslice) +void doSendOldestPossibleTimeframe(ServiceRegistryRef ref, fair::mq::TransportFactory* transport, ChannelIndex index, SendingPolicy::SendingCallback const& callback, size_t timeslice) { fair::mq::Parts parts; - fair::mq::MessagePtr payload(channel.Transport()->CreateMessage()); + fair::mq::MessagePtr payload(transport->CreateMessage()); o2::framework::DomainInfoHeader dih; dih.oldestPossibleTimeslice = timeslice; - auto channelAlloc = o2::pmr::getTransportAllocator(channel.Transport()); + auto channelAlloc = o2::pmr::getTransportAllocator(transport); auto header = o2::pmr::getMessage(o2::header::Stack{channelAlloc, dih}); // sigh... See if we can avoid having it const by not // exposing it to the user in the first place. parts.AddPart(std::move(header)); parts.AddPart(std::move(payload)); - auto timeout = 1000; - auto res = channel.Send(parts, timeout); - if (res == (size_t)fair::mq::TransferCode::timeout) { - LOGP(warning, "Timed out sending oldest possible timeslice after {}s. Downstream backpressure detected on {}.", timeout / 1000, channel.GetName()); - channel.Send(parts); - LOGP(info, "Downstream backpressure on {} recovered.", channel.GetName()); - } - if (res < (size_t)fair::mq::TransferCode::success) { - LOGP(fatal, "Error sending oldest possible timeframe {} on channel {} (code {})", timeslice, channel.GetName(), res); - } + callback(parts, index, ref); } -bool DataProcessingHelpers::sendOldestPossibleTimeframe(ForwardChannelInfo const& info, ForwardChannelState& state, size_t timeslice) +bool DataProcessingHelpers::sendOldestPossibleTimeframe(ServiceRegistryRef const& ref, ForwardChannelInfo const& info, ForwardChannelState& state, size_t timeslice) { if (state.oldestForChannel.value >= timeslice) { return false; } - sendOldestPossibleTimeframe(info.channel, timeslice); + doSendOldestPossibleTimeframe(ref, info.channel.Transport(), info.index, info.policy->forward, timeslice); state.oldestForChannel = {timeslice}; return true; } -bool DataProcessingHelpers::sendOldestPossibleTimeframe(OutputChannelInfo const& info, OutputChannelState& state, size_t timeslice) +bool DataProcessingHelpers::sendOldestPossibleTimeframe(ServiceRegistryRef const& ref, OutputChannelInfo const& info, OutputChannelState& state, size_t timeslice) { if (state.oldestForChannel.value >= timeslice) { return false; } - sendOldestPossibleTimeframe(info.channel, timeslice); + doSendOldestPossibleTimeframe(ref, info.channel.Transport(), info.index, info.policy->send, timeslice); state.oldestForChannel = {timeslice}; return true; } -void DataProcessingHelpers::broadcastOldestPossibleTimeslice(FairMQDeviceProxy& proxy, size_t timeslice) +void DataProcessingHelpers::broadcastOldestPossibleTimeslice(ServiceRegistryRef const& ref, size_t timeslice) { + auto& proxy = ref.get(); for (int ci = 0; ci < proxy.getNumOutputChannels(); ++ci) { auto& info = proxy.getOutputChannelInfo({ci}); auto& state = proxy.getOutputChannelState({ci}); - sendOldestPossibleTimeframe(info, state, timeslice); + sendOldestPossibleTimeframe(ref, info, state, timeslice); } } diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index b1681a4779ceb..e9df320fe8b95 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -493,6 +493,7 @@ void DeviceSpecHelpers::processOutEdgeActions(ConfigContext const& configContext const std::vector& outputsMatchers, const std::vector& channelPolicies, const std::vector& sendingPolicies, + const std::vector& forwardingPolicies, std::string const& channelPrefix, ComputingOffer const& defaultOffer, OverrideServiceSpecs const& overrideServices) @@ -656,7 +657,7 @@ void DeviceSpecHelpers::processOutEdgeActions(ConfigContext const& configContext // whether this is a real OutputRoute or if it's a forward from // a previous consumer device. // FIXME: where do I find the InputSpec for the forward? - auto appendOutputRouteToSourceDeviceChannel = [&outputsMatchers, &workflow, &devices, &logicalEdges, &sendingPolicies, &configContext]( + auto appendOutputRouteToSourceDeviceChannel = [&outputsMatchers, &workflow, &devices, &logicalEdges, &sendingPolicies, &forwardingPolicies, &configContext]( size_t ei, size_t di, size_t ci) { assert(ei < logicalEdges.size()); assert(di < devices.size()); @@ -670,29 +671,40 @@ void DeviceSpecHelpers::processOutEdgeActions(ConfigContext const& configContext assert(edge.outputGlobalIndex < outputsMatchers.size()); // Iterate over all the policies and apply the first one that matches. SendingPolicy const* policyPtr = nullptr; + ForwardingPolicy const* forwardPolicyPtr = nullptr; for (auto& policy : sendingPolicies) { if (policy.matcher(producer, consumer, configContext)) { policyPtr = &policy; break; } } + assert(forwardingPolicies.empty() == false); + for (auto& policy : forwardingPolicies) { + if (policy.matcher(producer, consumer, configContext)) { + forwardPolicyPtr = &policy; + break; + } + } assert(policyPtr != nullptr); + assert(forwardPolicyPtr != nullptr); if (edge.isForward == false) { OutputRoute route{ - edge.timeIndex, - consumer.maxInputTimeslices, - outputsMatchers[edge.outputGlobalIndex], - channel.name, - policyPtr, + .timeslice = edge.timeIndex, + .maxTimeslices = consumer.maxInputTimeslices, + .matcher = outputsMatchers[edge.outputGlobalIndex], + .channel = channel.name, + .policy = policyPtr, }; device.outputs.emplace_back(route); } else { ForwardRoute route{ - edge.timeIndex, - consumer.maxInputTimeslices, - workflow[edge.consumer].inputs[edge.consumerInputIndex], - channel.name}; + .timeslice = edge.timeIndex, + .maxTimeslices = consumer.maxInputTimeslices, + .matcher = workflow[edge.consumer].inputs[edge.consumerInputIndex], + .channel = channel.name, + .policy = forwardPolicyPtr, + }; device.forwards.emplace_back(route); } }; @@ -1051,6 +1063,7 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf std::vector const& resourcePolicies, std::vector const& callbacksPolicies, std::vector const& sendingPolicies, + std::vector const& forwardingPolicies, std::vector& devices, ResourceManager& resourceManager, std::string const& uniqueWorkflowId, @@ -1111,7 +1124,7 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf defaultOffer.memory /= deviceCount + 1; processOutEdgeActions(configContext, devices, deviceIndex, connections, resourceManager, outEdgeIndex, logicalEdges, - outActions, workflow, outputs, channelPolicies, sendingPolicies, channelPrefix, defaultOffer, overrideServices); + outActions, workflow, outputs, channelPolicies, sendingPolicies, forwardingPolicies, channelPrefix, defaultOffer, overrideServices); // FIXME: is this not the case??? std::sort(connections.begin(), connections.end()); diff --git a/Framework/Core/src/DeviceSpecHelpers.h b/Framework/Core/src/DeviceSpecHelpers.h index 1fb1866ae2dc3..17601c81342c1 100644 --- a/Framework/Core/src/DeviceSpecHelpers.h +++ b/Framework/Core/src/DeviceSpecHelpers.h @@ -53,6 +53,7 @@ struct DeviceSpecHelpers { std::vector const& resourcePolicies, std::vector const& callbacksPolicies, std::vector const& sendingPolicy, + std::vector const& forwardingPolicies, std::vector& devices, ResourceManager& resourceManager, std::string const& uniqueWorkflowId, @@ -80,9 +81,10 @@ struct DeviceSpecHelpers { std::vector dispatchPolicies = DispatchPolicy::createDefaultPolicies(); std::vector resourcePolicies = ResourcePolicy::createDefaultPolicies(); std::vector sendingPolicies = SendingPolicy::createDefaultPolicies(); + std::vector forwardingPolicies = ForwardingPolicy::createDefaultPolicies(); dataProcessorSpecs2DeviceSpecs(workflow, channelPolicies, completionPolicies, dispatchPolicies, resourcePolicies, callbacksPolicies, - sendingPolicies, devices, + sendingPolicies, forwardingPolicies, devices, resourceManager, uniqueWorkflowId, configContext, optimizeTopology, resourcesMonitoringInterval, channelPrefix, overrideServices); } @@ -150,6 +152,7 @@ struct DeviceSpecHelpers { const std::vector& outputs, std::vector const& channelPolicies, std::vector const& sendingPolicies, + std::vector const& forwardingPolicies, std::string const& channelPrefix, ComputingOffer const& defaultOffer, OverrideServiceSpecs const& overrideServices = {}); diff --git a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx index 0f769ae2dc850..4846363efd93b 100644 --- a/Framework/Core/src/ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/src/ExternalFairMQDeviceProxy.cxx @@ -29,6 +29,7 @@ #include "Framework/TimingInfo.h" #include "Framework/DeviceState.h" #include "Framework/Monitoring.h" +#include "Framework/SendingPolicy.h" #include "Headers/DataHeader.h" #include "Headers/Stack.h" #include "DecongestionService.h" @@ -923,10 +924,16 @@ DataProcessorSpec specifyFairMQDeviceOutputProxy(char const* name, auto lastDataProcessingHeader = std::make_shared(0, 0); auto& spec = const_cast(deviceSpec); + static auto policy = ForwardingPolicy::createDefaultForwardingPolicy(); for (auto const& inputSpec : inputSpecs) { // this is a prototype, in principle we want to have all spec objects const // and so only the const object can be retrieved from service registry - ForwardRoute route{0, 1, inputSpec, outputChannelName}; + ForwardRoute route{ + .timeslice = 0, + .maxTimeslices = 1, + .matcher = inputSpec, + .channel = outputChannelName, + .policy = &policy}; spec.forwards.emplace_back(route); } @@ -1010,7 +1017,13 @@ DataProcessorSpec specifyFairMQDeviceMultiOutputProxy(char const* name, if (device->GetChannels().count(channel) == 0) { throw std::runtime_error("no corresponding output channel found for input '" + channel + "'"); } - ForwardRoute route{0, 1, spec, channel}; + static auto policy = ForwardingPolicy::createDefaultForwardingPolicy(); + ForwardRoute route{ + .timeslice = 0, + .maxTimeslices = 1, + .matcher = spec, + .channel = channel, + .policy = &policy}; // this we will try to fix on the framework level, there will be an API to // set external routes. Basically, this has to be added while setting up the // workflow. After that, the actual spec provided by the service is supposed diff --git a/Framework/Core/src/FairMQDeviceProxy.cxx b/Framework/Core/src/FairMQDeviceProxy.cxx index c25a58e47ef2d..bdffddd5a4d1a 100644 --- a/Framework/Core/src/FairMQDeviceProxy.cxx +++ b/Framework/Core/src/FairMQDeviceProxy.cxx @@ -267,6 +267,7 @@ void FairMQDeviceProxy::bind(std::vector const& outputs, std::vecto .channelType = dplChannel, .channel = channel->second.at(0), .policy = route.policy, + .index = channelIndex, }; mOutputChannelInfos.push_back(info); mOutputChannelStates.push_back({0}); @@ -345,7 +346,7 @@ void FairMQDeviceProxy::bind(std::vector const& outputs, std::vecto LOGP(fatal, "Expected channel {} not configured.", route.channel); } ChannelAccountingType dplChannel = (route.channel.rfind("from_", 0) == 0) ? ChannelAccountingType::DPL : ChannelAccountingType::RAWFMQ; - mForwardChannelInfos.push_back(ForwardChannelInfo{route.channel, dplChannel, channel->second.at(0)}); + mForwardChannelInfos.push_back(ForwardChannelInfo{.name = route.channel, .channelType = dplChannel, .channel = channel->second.at(0), .policy = route.policy, .index = channelIndex}); mForwardChannelStates.push_back(ForwardChannelState{0}); channelNameToChannel[route.channel] = channelIndex; LOGP(detail, "Binding forward channel {} to channel index {}", route.channel, channelIndex.value); diff --git a/Framework/Core/src/SendingPolicy.cxx b/Framework/Core/src/SendingPolicy.cxx index 17faef6dbd3d0..3d65975919676 100644 --- a/Framework/Core/src/SendingPolicy.cxx +++ b/Framework/Core/src/SendingPolicy.cxx @@ -119,4 +119,81 @@ std::vector SendingPolicy::createDefaultPolicies() LOGP(fatal, "Error while sending on channel {}", channel->GetName()); } }}}; } + +ForwardingPolicy ForwardingPolicy::createDefaultForwardingPolicy() +{ + return ForwardingPolicy{ + .name = "default", + .matcher = [](DataProcessorSpec const&, DataProcessorSpec const&, ConfigContext const&) { return true; }, + .forward = [](fair::mq::Parts& parts, ChannelIndex channelIndex, ServiceRegistryRef registry) { + auto &proxy = registry.get(); + auto *channel = proxy.getForwardChannel(channelIndex); + auto timeout = 1000; + auto res = channel->Send(parts, timeout); + if (res == (size_t)fair::mq::TransferCode::timeout) { + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on {}.", timeout/1000, channel->GetName()); + channel->Send(parts); + LOGP(info, "Downstream backpressure on {} recovered.", channel->GetName()); + } else if (res == (size_t) fair::mq::TransferCode::error) { + LOGP(fatal, "Error while sending on channel {}", channel->GetName()); + } }}; +} + +std::vector ForwardingPolicy::createDefaultPolicies() +{ + return {ForwardingPolicy{ + .name = "profiling", + .matcher = [](DataProcessorSpec const&, DataProcessorSpec const&, ConfigContext const&) { return getenv("DPL_DEBUG_MESSAGE_SIZE"); }, + .forward = [](fair::mq::Parts& parts, ChannelIndex channelIndex, ServiceRegistryRef registry) { + auto &proxy = registry.get(); + auto *channel = proxy.getForwardChannel(channelIndex); + auto timeout = 1000; + int count = 0; + auto& relayer = registry.get(); + for (auto& part : parts) { + auto* dh = o2::header::get(part->GetData()); + if (dh == nullptr) { + // This is a payload. + continue; + } + LOGP(info, "Sent {}/{}/{} for a total of {} bytes", dh->dataOrigin, dh->dataDescription, dh->subSpecification, dh->payloadSize); + count+= dh->payloadSize; + auto* dph = o2::header::get(part->GetData()); + if (dph == nullptr) { + // This is a payload. + continue; + } + auto oldestPossibleOutput = relayer.getOldestPossibleOutput(); + if ((size_t)dph->startTime < oldestPossibleOutput.timeslice.value) { + LOGP(error, "Sent startTime {} while oldestPossibleOutput is {}. This should not be possible.", dph->startTime, oldestPossibleOutput.timeslice.value); + } + } + LOGP(info, "Sent {} parts for a total of {} bytes", parts.Size(), count); + auto res = channel->Send(parts, timeout); + if (res == (size_t)fair::mq::TransferCode::timeout) { + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on {}.", timeout/1000, channel->GetName()); + channel->Send(parts); + LOGP(info, "Downstream backpressure on {} recovered.", channel->GetName()); + } else if (res == (size_t) fair::mq::TransferCode::error) { + LOGP(fatal, "Error while sending on channel {}", channel->GetName()); + } }}, + ForwardingPolicy{ + .name = "expendable", + .matcher = [](DataProcessorSpec const& source, DataProcessorSpec const& dest, ConfigContext const&) { + auto has_label = [](DataProcessorLabel const& label) { + return label.value == "expendable"; + }; + return std::find_if(dest.labels.begin(), dest.labels.end(), has_label) != dest.labels.end(); }, + .forward = [](fair::mq::Parts& parts, ChannelIndex channelIndex, ServiceRegistryRef registry) { + auto &proxy = registry.get(); + auto *channel = proxy.getForwardChannel(channelIndex); + auto timeout = 1000; + auto res = channel->Send(parts, timeout); + if (res == (size_t)fair::mq::TransferCode::timeout) { + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on expendable channel {}.", timeout/1000, channel->GetName()); + } else if (res == (size_t) fair::mq::TransferCode::error) { + LOGP(info, "Error while sending on channel {}", channel->GetName()); + } }}, + createDefaultForwardingPolicy()}; +} } // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 9ca46e060b1a2..cfbb616b0d0a5 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1650,6 +1650,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, driverInfo.resourcePolicies, driverInfo.callbacksPolicies, driverInfo.sendingPolicies, + driverInfo.forwardingPolicies, runningWorkflow.devices, *resourceManager, driverInfo.uniqueWorkflowId, @@ -2644,6 +2645,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, { std::vector currentArgs; std::vector plugins; + std::vector forwardingPolicies = ForwardingPolicy::createDefaultPolicies(); for (int ai = 1; ai < argc; ++ai) { currentArgs.emplace_back(argv[ai]); @@ -3001,6 +3003,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, }; DriverInfo driverInfo{ .sendingPolicies = sendingPolicies, + .forwardingPolicies = forwardingPolicies, .callbacksPolicies = callbacksPolicies}; driverInfo.states.reserve(10); driverInfo.sigintRequested = false; diff --git a/Framework/Core/test/test_DeviceSpec.cxx b/Framework/Core/test/test_DeviceSpec.cxx index 99494d5f8ea4f..72b19da542a76 100644 --- a/Framework/Core/test/test_DeviceSpec.cxx +++ b/Framework/Core/test/test_DeviceSpec.cxx @@ -421,6 +421,7 @@ TEST_CASE("TestOutEdgeProcessingHelpers") auto configContext = makeEmptyConfigContext(); auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto sendingPolicies = SendingPolicy::createDefaultPolicies(); + auto forwardingPolicies = ForwardingPolicy::createDefaultPolicies(); std::vector resources{ComputingResourceHelpers::getLocalhostResource()}; SimpleResourceManager rm(resources); @@ -429,7 +430,7 @@ TEST_CASE("TestOutEdgeProcessingHelpers") defaultOffer.memory = 0.01; DeviceSpecHelpers::processOutEdgeActions(*configContext, devices, deviceIndex, connections, rm, edgeOutIndex, logicalEdges, - actions, workflow, globalOutputs, channelPolicies, sendingPolicies, "", defaultOffer); + actions, workflow, globalOutputs, channelPolicies, sendingPolicies, forwardingPolicies, "", defaultOffer); std::vector expectedDeviceIndex = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 1}, {1, 0, 1}, {1, 1, 2}, {1, 1, 2}, {1, 2, 3}, {1, 2, 3}}; REQUIRE(devices.size() == 4); @@ -713,6 +714,7 @@ TEST_CASE("TestSimpleWildcard") auto configContext = makeEmptyConfigContext(); auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); auto sendingPolicies = SendingPolicy::createDefaultPolicies(); + auto forwardingPolicies = ForwardingPolicy::createDefaultPolicies(); std::vector devices; std::vector deviceIndex; @@ -751,7 +753,7 @@ TEST_CASE("TestSimpleWildcard") defaultOffer.memory = 0.01; DeviceSpecHelpers::processOutEdgeActions(*configContext, devices, deviceIndex, connections, rm, edgeOutIndex, logicalEdges, - outActions, workflow, globalOutputs, channelPolicies, sendingPolicies, "", defaultOffer); + outActions, workflow, globalOutputs, channelPolicies, sendingPolicies, forwardingPolicies, "", defaultOffer); REQUIRE(devices.size() == 2); ; // Two devices have outputs: A and Timer diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index de78993ff083e..28ff4d5568da9 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -125,10 +125,9 @@ void Dispatcher::run(ProcessingContext& ctx) if (ctx.inputs().isValid("timer-stats")) { reportStats(ctx.services().get()); } - auto& proxy = ctx.services().get(); auto& relayer = ctx.services().get(); auto timeslice = relayer.getOldestPossibleOutput().timeslice.value; - DataProcessingHelpers::broadcastOldestPossibleTimeslice(proxy, timeslice); + DataProcessingHelpers::broadcastOldestPossibleTimeslice(ctx.services(), timeslice); } void Dispatcher::reportStats(Monitoring& monitoring) const From 976e46008822c619e15f4b47a6701dc0fcaa6eef Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 10 Feb 2024 01:17:29 +0100 Subject: [PATCH 19/50] DPL: add SendingPolicy for the case destination is expendable --- Framework/Core/src/SendingPolicy.cxx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/SendingPolicy.cxx b/Framework/Core/src/SendingPolicy.cxx index 3d65975919676..3aeccb680c150 100644 --- a/Framework/Core/src/SendingPolicy.cxx +++ b/Framework/Core/src/SendingPolicy.cxx @@ -29,7 +29,7 @@ std::vector SendingPolicy::createDefaultPolicies() { return {SendingPolicy{ .name = "dispatcher", - .matcher = [](DataProcessorSpec const& source, DataProcessorSpec const& dest, ConfigContext const&) { + .matcher = [](DataProcessorSpec const& source, DataProcessorSpec const& dest, ConfigContext const&) { if (source.name == "Dispatcher") { return true; } @@ -103,6 +103,23 @@ std::vector SendingPolicy::createDefaultPolicies() } else if (res == (size_t) fair::mq::TransferCode::error) { LOGP(fatal, "Error while sending on channel {}", channel->GetName()); } }}, + SendingPolicy{ + .name = "expendable", + .matcher = [](DataProcessorSpec const& source, DataProcessorSpec const& dest, ConfigContext const&) { + auto has_label = [](DataProcessorLabel const& label) { + return label.value == "expendable"; + }; + return std::find_if(dest.labels.begin(), dest.labels.end(), has_label) != dest.labels.end(); }, + .send = [](fair::mq::Parts& parts, ChannelIndex channelIndex, ServiceRegistryRef registry) { + auto &proxy = registry.get(); + auto *channel = proxy.getOutputChannel(channelIndex); + auto timeout = 1000; + auto res = channel->Send(parts, timeout); + if (res == (size_t)fair::mq::TransferCode::timeout) { + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on expendable channel {}.", timeout/1000, channel->GetName()); + } else if (res == (size_t) fair::mq::TransferCode::error) { + LOGP(info, "Error while sending on channel {}", channel->GetName()); + } }}, SendingPolicy{ .name = "default", .matcher = [](DataProcessorSpec const&, DataProcessorSpec const&, ConfigContext const&) { return true; }, From f309be5f57e0d65d46521c7f1fbd970edd054485 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli Date: Wed, 7 Feb 2024 13:08:41 +0100 Subject: [PATCH 20/50] Fixes to make the split wf work again --- .../helpers/src/InputHelper.cxx | 2 +- prodtests/full-system-test/calib-workflow.sh | 34 ++++++++++++++++--- prodtests/full-system-test/dpl-workflow.sh | 11 +++--- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx b/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx index 7197b302b953d..c6c163f4b8911 100644 --- a/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx +++ b/Detectors/GlobalTrackingWorkflow/helpers/src/InputHelper.cxx @@ -176,7 +176,7 @@ int InputHelper::addInputSpecs(const ConfigContext& configcontext, WorkflowSpec& } if (maskClusters[GID::MCH]) { - specs.emplace_back(o2::mch::getClusterReaderSpec(maskClustersMC[GID::MCH], "mch-cluster-reader", true, false)); + specs.emplace_back(o2::mch::getClusterReaderSpec(maskClustersMC[GID::MCH], "mch-cluster-reader", true, true)); } return 0; diff --git a/prodtests/full-system-test/calib-workflow.sh b/prodtests/full-system-test/calib-workflow.sh index b6192e62a809a..e098625b9a48b 100755 --- a/prodtests/full-system-test/calib-workflow.sh +++ b/prodtests/full-system-test/calib-workflow.sh @@ -37,13 +37,39 @@ if [[ $CALIB_ZDC_TDC == 1 ]]; then add_W o2-zdc-tdccalib-epn-workflow "" "" 0; f if [[ $CALIB_FT0_TIMEOFFSET == 1 ]]; then add_W o2-calibration-ft0-time-spectra-processor; fi # current integration -if [[ $CALIB_FT0_INTEGRATEDCURR == 1 ]]; then add_W o2-ft0-integrate-cluster-workflow "$DISABLE_ROOT_OUTPUT --nSlicesTF $TPC_IDCCALIB_NSLICESPERTF"; fi -if [[ $CALIB_FV0_INTEGRATEDCURR == 1 ]]; then add_W o2-fv0-integrate-cluster-workflow "$DISABLE_ROOT_OUTPUT --nSlicesTF $TPC_IDCCALIB_NSLICESPERTF"; fi -if [[ $CALIB_FDD_INTEGRATEDCURR == 1 ]]; then add_W o2-fdd-integrate-cluster-workflow "$DISABLE_ROOT_OUTPUT --nSlicesTF $TPC_IDCCALIB_NSLICESPERTF"; fi -if [[ $CALIB_TOF_INTEGRATEDCURR == 1 ]]; then add_W o2-tof-integrate-cluster-workflow "$DISABLE_ROOT_OUTPUT --nSlicesTF $TPC_IDCCALIB_NSLICESPERTF"; fi +: ${INTEGRATED_CURR_OPTIONS:=""} +if [[ $SYNCMODE == 1 ]]; then INTEGRATED_CURR_OPTIONS="$DISABLE_ROOT_OUTPUT --nSlicesTF $TPC_IDCCALIB_NSLICESPERTF"; fi +if [[ $CALIB_FT0_INTEGRATEDCURR == 1 ]]; then add_W o2-ft0-integrate-cluster-workflow "$INTEGRATED_CURR_OPTIONS"; fi +if [[ $CALIB_FV0_INTEGRATEDCURR == 1 ]]; then add_W o2-fv0-integrate-cluster-workflow "$INTEGRATED_CURR_OPTIONS"; fi +if [[ $CALIB_FDD_INTEGRATEDCURR == 1 ]]; then add_W o2-fdd-integrate-cluster-workflow "$INTEGRATED_CURR_OPTIONS"; fi +if [[ $CALIB_TOF_INTEGRATEDCURR == 1 ]]; then add_W o2-tof-integrate-cluster-workflow "$INTEGRATED_CURR_OPTIONS"; fi # for async calibrations if [[ $CALIB_EMC_ASYNC_RECALIB == 1 ]]; then add_W o2-emcal-emc-offline-calib-workflow "--input-subspec 1 --applyGainCalib"; fi +: ${ARGS_EXTRA_PROCESS_o2_tpc_integrate_cluster_workflow:=""} +if [[ $CALIB_ASYNC_EXTRACTTPCCURRENTS == 1 ]]; then + add_comma_separated ADD_EXTRA_WORKFLOW "o2-tpc-integrate-cluster-workflow" + if [[ $CALIB_ASYNC_DISABLE3DCURRENTS != 1 ]]; then + export ARGS_EXTRA_PROCESS_o2_tpc_integrate_cluster_workflow="$ARGS_EXTRA_PROCESS_o2_tpc_integrate_cluster_workflow--process-3D-currents --nSlicesTF 1" + fi +fi +if [[ $CALIB_ASYNC_EXTRACTTIMESERIES == 1 ]] ; then + : ${ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow:=""} + : ${CALIB_ASYNC_SAMPLINGFACTORTIMESERIES:=0.001} + add_comma_separated ADD_EXTRA_WORKFLOW "o2-tpc-time-series-workflow" + if [[ ! -z "$CALIB_ASYNC_ENABLEUNBINNEDTIMESERIES" ]]; then + export ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow="$ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow --enable-unbinned-root-output --sample-unbinned-tsallis --threads 1" + fi + if [[ $ON_SKIMMED_DATA == 1 ]] || [[ ! -z "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then + if [[ $ON_SKIMMED_DATA == 1 ]]; then + SAMPLINGFACTORTIMESERIES=0.1 + fi + if [[ ! -z "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then # this takes priority, even if we were on skimmed data + SAMPLINGFACTORTIMESERIES=${CALIB_ASYNC_SAMPLINGFACTORTIMESERIES} + fi + export ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow="$ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow --sampling-factor ${SAMPLINGFACTORTIMESERIES}" + fi +fi # output-proxy for aggregator if workflow_has_parameter CALIB_PROXIES; then diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 3c26916bece47..7bb6748f0797d 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -347,13 +347,16 @@ WORKFLOW= # Make sure we start with an empty workflow # --------------------------------------------------------------------------------------------------------------------- # Input workflow INPUT_DETECTOR_LIST=$WORKFLOW_DETECTORS -if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER} ]]; then - for i in ${WORKFLOW_DETECTORS_USE_GLOBAL_READER//,/ }; do +if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS} ]]; then + for i in ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS//,/ }; do + export INPUT_DETECTOR_LIST=$(echo $INPUT_DETECTOR_LIST | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") + done + for i in ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS//,/ }; do export INPUT_DETECTOR_LIST=$(echo $INPUT_DETECTOR_LIST | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") done GLOBAL_READER_OPTIONS= has_detector ITS && SYNCMODE==1 && GLOBAL_READER_OPTIONS+=" --ir-frames-its" - add_W o2-global-track-cluster-reader "--cluster-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER --track-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER $GLOBAL_READER_OPTIONS $DISABLE_MC --hbfutils-config o2_tfidinfo.root" + add_W o2-global-track-cluster-reader "--cluster-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS --track-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS $GLOBAL_READER_OPTIONS $DISABLE_MC --hbfutils-config o2_tfidinfo.root" has_detector FV0 && has_detector_from_global_reader FV0 && add_W o2-fv0-digit-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --fv0-digit-infile o2_fv0digits.root" has_detector MID && has_detector_from_global_reader MID && add_W o2-mid-digits-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --mid-digit-infile mid-digits-decoded.root" has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --infile mchdigits.root" @@ -503,7 +506,7 @@ has_detector FDD && ! has_detector_from_global_reader FDD && has_processing_step has_detector FV0 && ! has_detector_from_global_reader FV0 && has_processing_step FV0_RECO && add_W o2-fv0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector ZDC && ! has_detector_from_global_reader ZDC && has_processing_step ZDC_RECO && add_W o2-zdc-digits-reco "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector HMP && ! has_detector_from_global_reader HMP && has_processing_step HMP_RECO && add_W o2-hmpid-digits-to-clusters-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT --pipeline $(get_N HMP-Clusterization HMP REST 1 HMPCLUS)" -has_detector HMP && ! has_detector_from_global_reader HMP && has_processing_step HMP_RECO && add_W o2-hmpid-matcher-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --track-sources ${HMP_SOURCES:-all} --pipeline $(get_N hmp-matcher HMP REST 1 HMPMATCH)" +has_detector HMP && has_detector_matching HMP && ! has_detector_from_global_reader_tracks HMP && has_processing_step HMP_RECO && add_W o2-hmpid-matcher-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --track-sources ${HMP_SOURCES:-all} --pipeline $(get_N hmp-matcher HMP REST 1 HMPMATCH)" has_detectors_reco MCH MID && has_detector_matching MCHMID && add_W o2-muon-tracks-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N muon-track-matcher MATCH REST 1)" has_detectors_reco MFT MCH && has_detector_matching MFTMCH && add_W o2-globalfwd-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N globalfwd-track-matcher MATCH REST 1 FWDMATCH)" "$MFTMCHConf" From 29de135e0547ea78fc4f463c7f1bba2ddfd6f175 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sat, 10 Feb 2024 02:40:28 +0100 Subject: [PATCH 21/50] Add reader-driver workflow to allow TF throttling with readers The workflows driven by the input from the root files produced by detectors (e.g. by the o2-global-track-cluster-reader), can be preceded by the o2-reader-driver-workflow workflow to have TFs throttling via usual --timeframes-rate-limit --timeframes-rate-limit-ipcid options. The o2-reader-driver-workflow as well as all reader workflows must be provided with the --hbfutils-config ,upstream option, with being the file produced by the o2-tfidinfo-writer-workflow: usually o2_tfidinfo.root file. If this file is in the working directory, then the --hbfutils-config option can be shortened to upstream only. The o2-reader-driver-workflow is not supported for o2simdigitizerworkflow_configuration.ini version of --hbfutils-config, since it is used only for MC, where by construction there is only 1 TF, hence the throttling is meaningless. Option --max-tf of the o2-reader-driver-workflow allows to inject only 1st TFs by the dowsntream readers. --- .../GlobalTrackingWorkflow/CMakeLists.txt | 5 + Detectors/GlobalTrackingWorkflow/README.md | 19 ++++ .../GlobalTrackingWorkflow/ReaderDriverSpec.h | 32 +++++++ .../src/ReaderDriverSpec.cxx | 95 +++++++++++++++++++ .../src/reader-driver-workflow.cxx | 64 +++++++++++++ .../DetectorsRaw/HBFUtilsInitializer.h | 4 + Detectors/Raw/src/HBFUtilsInitializer.cxx | 64 +++++++++---- 7 files changed, 266 insertions(+), 17 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/ReaderDriverSpec.h create mode 100644 Detectors/GlobalTrackingWorkflow/src/ReaderDriverSpec.cxx create mode 100644 Detectors/GlobalTrackingWorkflow/src/reader-driver-workflow.cxx diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index a01ffa4b770c7..6b0c5a7285c15 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -33,6 +33,7 @@ o2_add_library(GlobalTrackingWorkflow src/GlobalFwdTrackWriterSpec.cxx src/GlobalFwdMatchingAssessmentSpec.cxx src/MatchedMFTMCHWriterSpec.cxx + src/ReaderDriverSpec.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::GlobalTrackingWorkflowReaders O2::GlobalTrackingWorkflowHelpers @@ -48,6 +49,10 @@ o2_add_library(GlobalTrackingWorkflow O2::SimulationDataFormat O2::DetectorsVertexing O2::StrangenessTracking) +o2_add_executable(driver-workflow + COMPONENT_NAME reader + SOURCES src/reader-driver-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflow ) o2_add_executable(match-workflow COMPONENT_NAME tpcits diff --git a/Detectors/GlobalTrackingWorkflow/README.md b/Detectors/GlobalTrackingWorkflow/README.md index 2042f89a582ed..95693115d932d 100644 --- a/Detectors/GlobalTrackingWorkflow/README.md +++ b/Detectors/GlobalTrackingWorkflow/README.md @@ -28,4 +28,23 @@ o2-cosmics-match-workflow --shm-segment-size 10000000000 --run | tee cosmics.log One can account contributions of a limited set of track sources (currently by default: ITS, TPC, ITS-TPC, TPC-TOF, ITS-TPC-TOF) by providing optiont `--track-sources`. +## Using TF throttling when reading root files from detectors processing (tracks, clusters etc.) +The workflows driven by the input from the root files produced by detectors (e.g. by the `o2-global-track-cluster-reader`), can be preceded by the +`o2-reader-driver-workflow` which will allow to have TF throttling via usual `--timeframes-rate-limit ` and `--timeframes-rate-limit-ipcid ` +options. +The `o2-reader-driver-workflow` as well as all reader workflows must be provided with the `--hbfutils-config ,upstream` option, with being the file produced by the +`o2-tfidinfo-writer-workflow` (usually o2_tfidinfo.root file). If this file is in the working directory, then the `--hbfutils-config` option can be shortened to `upstream` only. + +The `o2-reader-driver-workflow` is not supported for `o2simdigitizerworkflow_configuration.ini` version of the `--hbfutils-config`, since it is used only for MC, +where by construction there is only 1 TF, hence the throttling is meaningless. + +Option `--max-tf ` of the `o2-reader-driver-workflow` allows to inject only 1st TFs by the dowsntream readers. + +A typical invocation of the throttled workflow is: + +``` +GLOSET=" --shm-segment-size 24000000000 --timeframes-rate-limit 2 --timeframes-rate-limit-ipcid 0" +HBFSET=" --hbfutils-config upstream,o2_tfidinfo.root " +o2-reader-driver-workflow $GLOSET $HBFSET --max-tf 3 | o2-global-track-cluster-reader $GLOSET $HBFSET --disable-mc --track-types <...> --cluster-types <...> | [ $GLOSET $HBFSET ] | $GLOSET --run +``` diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/ReaderDriverSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/ReaderDriverSpec.h new file mode 100644 index 0000000000000..3cbf7e5d8f4fe --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/ReaderDriverSpec.h @@ -0,0 +1,32 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file ReaderDriverSpec.h + +#ifndef O2_READER_DRIVER_ +#define O2_READER_DRIVER_ + +#include "Framework/DataProcessorSpec.h" +#include + +namespace o2 +{ +namespace globaltracking +{ + +/// create a processor spec +/// pushes an empty output to provide timing to downstream devices +framework::DataProcessorSpec getReaderDriverSpec(const std::string& metricChannel = "", size_t minSHM = 0); + +} // namespace globaltracking +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/src/ReaderDriverSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/ReaderDriverSpec.cxx new file mode 100644 index 0000000000000..0ab7a69dc5363 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/ReaderDriverSpec.cxx @@ -0,0 +1,95 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file ReaderDriverSpec.cxx + +#include +#include +#include +#include "Framework/ControlService.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Task.h" +#include "Framework/Logger.h" +#include "Framework/RateLimiter.h" +#include "Framework/RawDeviceService.h" +#include "GlobalTrackingWorkflow/ReaderDriverSpec.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" +#include "CommonUtils/StringUtils.h" +#include "TFile.h" +#include "TTree.h" + +using namespace o2::framework; + +namespace o2 +{ +namespace globaltracking +{ + +class ReadeDriverSpec : public o2::framework::Task +{ + public: + ReadeDriverSpec(size_t minSHM) : mMinSHM(minSHM) {} + ~ReadeDriverSpec() override = default; + void init(o2::framework::InitContext& ic) final; + void run(o2::framework::ProcessingContext& pc) final; + + protected: + int mTFRateLimit = -999; + int mNTF = 0; + size_t mMinSHM = 0; +}; + +void ReadeDriverSpec::init(InitContext& ic) +{ + mNTF = ic.options().get("max-tf"); +} + +void ReadeDriverSpec::run(ProcessingContext& pc) +{ + if (mTFRateLimit == -999) { + mTFRateLimit = std::stoi(pc.services().get().device()->fConfig->GetValue("timeframes-rate-limit")); + } + static RateLimiter limiter; + static int count = 0; + if (!count) { + if (o2::raw::HBFUtilsInitializer::NTFs < 0) { + LOGP(fatal, "Number of TFs to process was not initizalized in the HBFUtilsInitializer"); + } + mNTF = (mNTF > 0 && mNTF < o2::raw::HBFUtilsInitializer::NTFs) ? mNTF : o2::raw::HBFUtilsInitializer::NTFs; + } else { // check only for count > 0 + limiter.check(pc, mTFRateLimit, mMinSHM); + } + std::vector v{}; + pc.outputs().snapshot(Output{"GLO", "READER_DRIVER", 0}, v); + if (++count >= mNTF) { + pc.services().get().endOfStream(); + pc.services().get().readyToQuit(QuitRequest::Me); + } +} + +DataProcessorSpec getReaderDriverSpec(const std::string& metricChannel, size_t minSHM) +{ + std::vector outputSpec; + std::vector options; + options.emplace_back(ConfigParamSpec{"max-tf", o2::framework::VariantType::Int, -1, {"max TFs to process (<1 : no limits)"}}); + if (!metricChannel.empty()) { + options.emplace_back(ConfigParamSpec{"channel-config", VariantType::String, metricChannel, {"Out-of-band channel config for TF throttling"}}); + } + return DataProcessorSpec{ + o2::raw::HBFUtilsInitializer::ReaderDriverDevice, + Inputs{}, + Outputs{{"GLO", "READER_DRIVER", 0, Lifetime::Timeframe}}, + AlgorithmSpec{adaptFromTask(minSHM)}, + options}; +} + +} // namespace globaltracking +} // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/reader-driver-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/reader-driver-workflow.cxx new file mode 100644 index 0000000000000..5deabc8e70344 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/src/reader-driver-workflow.cxx @@ -0,0 +1,64 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/ChannelSpecHelpers.h" +#include "GlobalTrackingWorkflow/ReaderDriverSpec.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" +#include "Framework/CallbacksPolicy.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector& workflowOptions) +{ + // option allowing to set parameters + std::vector options{ + {"timeframes-shm-limit", VariantType::String, "0", {"Minimum amount of SHM required in order to publish data"}}, + {"metric-feedback-channel-format", VariantType::String, "name=metric-feedback,type=pull,method=connect,address=ipc://{}metric-feedback-{},transport=shmem,rateLogging=0", {"format for the metric-feedback channel for TF rate limiting"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::raw::HBFUtilsInitializer::addConfigOption(options, "o2_tfidinfo.root,upstream"); + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); + + int rateLimitingIPCID = std::stoi(configcontext.options().get("timeframes-rate-limit-ipcid")); + std::string chanFmt = configcontext.options().get("metric-feedback-channel-format"); + std::string metricChannel{}; + if (rateLimitingIPCID > -1 && !chanFmt.empty()) { + metricChannel = fmt::format(fmt::runtime(chanFmt), o2::framework::ChannelSpecHelpers::defaultIPCFolder(), rateLimitingIPCID); + } + size_t minSHM = std::stoul(configcontext.options().get("timeframes-shm-limit")); + + WorkflowSpec specs; + specs.emplace_back(o2::globaltracking::getReaderDriverSpec(metricChannel, minSHM)); + + // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit + o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); + + return std::move(specs); +} diff --git a/Detectors/Raw/include/DetectorsRaw/HBFUtilsInitializer.h b/Detectors/Raw/include/DetectorsRaw/HBFUtilsInitializer.h index 47216f912660d..439b53371b336 100644 --- a/Detectors/Raw/include/DetectorsRaw/HBFUtilsInitializer.h +++ b/Detectors/Raw/include/DetectorsRaw/HBFUtilsInitializer.h @@ -51,6 +51,10 @@ struct HBFUtilsInitializer { static constexpr char HBFConfOpt[] = "hbfutils-config"; static constexpr char HBFTFInfoOpt[] = "tf-info-source"; static constexpr char HBFUSrc[] = "hbfutils"; + static constexpr char ReaderDriverDevice[] = "reader-driver"; + static constexpr char UpstreamOpt[] = "upstream"; + + static int NTFs; HBFUtilsInitializer(const o2::framework::ConfigContext& configcontext, o2::framework::WorkflowSpec& wf); static HBFOpt getOptType(const std::string& optString); diff --git a/Detectors/Raw/src/HBFUtilsInitializer.cxx b/Detectors/Raw/src/HBFUtilsInitializer.cxx index cb492812c3634..967cb843eb9ff 100644 --- a/Detectors/Raw/src/HBFUtilsInitializer.cxx +++ b/Detectors/Raw/src/HBFUtilsInitializer.cxx @@ -38,31 +38,57 @@ namespace o2f = o2::framework; /// In case the configcontext has relevant option, the HBFUtils will be beforehand updated from the file indicated by this option. /// (only those fields of HBFUtils which were not modified before, e.g. by ConfigurableParam::updateFromString) +int HBFUtilsInitializer::NTFs = 0; + //_________________________________________________________ HBFUtilsInitializer::HBFUtilsInitializer(const o2f::ConfigContext& configcontext, o2f::WorkflowSpec& wf) { - auto updateHBFUtils = [&configcontext]() -> std::string { + bool upstream = false; // timing info will be provided from upstream readers-driver, just subscribe to it + + auto updateHBFUtils = [&configcontext, &upstream]() -> std::string { static bool done = false; static std::string confTFInfo{}; if (!done) { bool helpasked = configcontext.helpOnCommandLine(); // if help is asked, don't take for granted that the ini file is there, don't produce an error if it is not! auto conf = configcontext.options().isSet(HBFConfOpt) ? configcontext.options().get(HBFConfOpt) : ""; + HBFOpt opt = HBFOpt::NONE; + upstream = false; if (!conf.empty()) { - auto opt = getOptType(conf); - if ((opt == HBFOpt::INI || opt == HBFOpt::JSON) && (!(helpasked && !o2::conf::ConfigurableParam::configFileExists(conf)))) { - o2::conf::ConfigurableParam::updateFromFile(conf, "HBFUtils", true); // update only those values which were not touched yet (provenance == kCODE) - const auto& hbfu = o2::raw::HBFUtils::Instance(); - hbfu.checkConsistency(); - confTFInfo = HBFUSrc; - } else if (opt == HBFOpt::HBFUTILS) { - const auto& hbfu = o2::raw::HBFUtils::Instance(); - hbfu.checkConsistency(); - confTFInfo = HBFUSrc; - } else if (opt == HBFOpt::ROOT) { - confTFInfo = conf; + auto vopts = o2::utils::Str::tokenize(conf, ','); + for (const auto& optStr : vopts) { + if (optStr == UpstreamOpt) { + upstream = true; + continue; + } + if (!confTFInfo.empty()) { + throw std::runtime_error(fmt::format("too many options in {} {}", HBFConfOpt, conf)); + } + opt = getOptType(optStr); + if ((opt == HBFOpt::INI || opt == HBFOpt::JSON) && (!(helpasked && !o2::conf::ConfigurableParam::configFileExists(confTFInfo)))) { + o2::conf::ConfigurableParam::updateFromFile(optStr, "HBFUtils", true); // update only those values which were not touched yet (provenance == kCODE) + const auto& hbfu = o2::raw::HBFUtils::Instance(); + hbfu.checkConsistency(); + confTFInfo = HBFUSrc; + } else if (opt == HBFOpt::HBFUTILS) { + const auto& hbfu = o2::raw::HBFUtils::Instance(); + hbfu.checkConsistency(); + confTFInfo = HBFUSrc; + } else if (opt == HBFOpt::ROOT) { + confTFInfo = optStr; + } } } done = true; + if (opt != HBFOpt::NONE) { + if (upstream) { + if (opt != HBFOpt::ROOT) { + throw std::runtime_error(fmt::format("invalid option {}: upstream can be used only with root file providing TFIDInfo", conf)); + } + } + } else if (upstream) { + confTFInfo = "o2_tfidinfo.root"; + LOGP(debug, "--hbfutils-config input type is not provided but upstream keyword is found: assume {}", confTFInfo); + } } return confTFInfo; }; @@ -70,13 +96,16 @@ HBFUtilsInitializer::HBFUtilsInitializer(const o2f::ConfigContext& configcontext if (configcontext.options().hasOption("disable-root-input") && configcontext.options().get("disable-root-input")) { return; // we apply HBFUtilsInitializer only in case of root readers } - const auto& hbfu = o2::raw::HBFUtils::Instance(); for (auto& spec : wf) { if (spec.inputs.empty()) { auto conf = updateHBFUtils(); - o2f::ConfigParamsHelper::addOptionIfMissing(spec.options, o2f::ConfigParamSpec{HBFTFInfoOpt, o2f::VariantType::String, conf, {"root file with per-TF info"}}); - o2f::ConfigParamsHelper::addOptionIfMissing(spec.options, o2f::ConfigParamSpec{DelayOpt, o2f::VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); + if (!upstream || spec.name == ReaderDriverDevice) { + o2f::ConfigParamsHelper::addOptionIfMissing(spec.options, o2f::ConfigParamSpec{HBFTFInfoOpt, o2f::VariantType::String, conf, {"root file with per-TF info"}}); + o2f::ConfigParamsHelper::addOptionIfMissing(spec.options, o2f::ConfigParamSpec{DelayOpt, o2f::VariantType::Float, 0.f, {"delay in seconds between consecutive TFs sending"}}); + } else { // subsribe to upstream timing info from readers-driver + spec.inputs.emplace_back(o2f::InputSpec{"driverInfo", "GLO", "READER_DRIVER", 0, o2f::Lifetime::Timeframe}); + } } } } @@ -114,6 +143,7 @@ std::vector HBFUtilsInitializer::readTFIDInfoVector(c throw std::runtime_error(fmt::format("Failed to read tfidinfo vector from {}", fname)); } std::vector v(*vptr); + NTFs = v.size(); return v; } @@ -174,5 +204,5 @@ void HBFUtilsInitializer::addNewTimeSliceCallback(std::vector& opts, const std::string& defOpt) { - o2f::ConfigParamsHelper::addOptionIfMissing(opts, o2f::ConfigParamSpec{HBFConfOpt, o2f::VariantType::String, defOpt, {R"(ConfigurableParam ini file or "hbfutils" for HBFUtils, root file with per-TF info or "none")"}}); + o2f::ConfigParamsHelper::addOptionIfMissing(opts, o2f::ConfigParamSpec{HBFConfOpt, o2f::VariantType::String, defOpt, {R"(ConfigurableParam ini file or "hbfutils" for HBFUtils, root file with per-TF info (augmented with ,upstream if reader-driver is used) or "none")"}}); } From dfbb4f038bdb2027b302099828f77fc03b651c0e Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 11 Feb 2024 21:13:26 +0100 Subject: [PATCH 22/50] Use o2-reader-driver in dpl-workflow with readers if throttling is asked --- prodtests/full-system-test/dpl-workflow.sh | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 7bb6748f0797d..88eabad09bcb1 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -354,18 +354,26 @@ if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFL for i in ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS//,/ }; do export INPUT_DETECTOR_LIST=$(echo $INPUT_DETECTOR_LIST | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") done + GLOBAL_READER_OPTIONS= has_detector ITS && SYNCMODE==1 && GLOBAL_READER_OPTIONS+=" --ir-frames-its" - add_W o2-global-track-cluster-reader "--cluster-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS --track-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS $GLOBAL_READER_OPTIONS $DISABLE_MC --hbfutils-config o2_tfidinfo.root" - has_detector FV0 && has_detector_from_global_reader FV0 && add_W o2-fv0-digit-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --fv0-digit-infile o2_fv0digits.root" - has_detector MID && has_detector_from_global_reader MID && add_W o2-mid-digits-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --mid-digit-infile mid-digits-decoded.root" - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --infile mchdigits.root" - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC --hbfutils-config o2_tfidinfo.root --infile mchfdigits.root --mch-output-digits-data-description F-DIGITS --mch-output-digitrofs-data-description TC-F-DIGITROFS" - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-errors-reader-workflow "--hbfutils-config o2_tfidinfo.root" "" 0 - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-clusters-reader-workflow "--hbfutils-config o2_tfidinfo.root" "" 0 - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-preclusters-reader-workflow "--hbfutils-config o2_tfidinfo.root" "" 0 - has_detector TRD && has_detector_from_global_reader TRD && add_W o2-trd-digit-reader-workflow "$DISABLE_MC --digit-subspec 0 --disable-trigrec --hbfutils-config o2_tfidinfo.root" - has_detector TOF && has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$DISABLE_MC --input-type digits --output-type NONE --hbfutils-config o2_tfidinfo.root" + + if [[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]]; then + HBFINI_OPTIONS=" --hbfutils-config o2_tfidinfo.root,upstream " + add_W o2-reader-driver-workflow "$HBFINI_OPTIONS" + else + HBFINI_OPTIONS=" --hbfutils-config o2_tfidinfo.root " + fi + add_W o2-global-track-cluster-reader "--cluster-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS --track-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS $GLOBAL_READER_OPTIONS $DISABLE_MC $HBFINI_OPTIONS" + has_detector FV0 && has_detector_from_global_reader FV0 && add_W o2-fv0-digit-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --fv0-digit-infile o2_fv0digits.root" + has_detector MID && has_detector_from_global_reader MID && add_W o2-mid-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --mid-digit-infile mid-digits-decoded.root" + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --infile mchdigits.root" + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --infile mchfdigits.root --mch-output-digits-data-description F-DIGITS --mch-output-digitrofs-data-description TC-F-DIGITROFS" + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-errors-reader-workflow "$HBFINI_OPTIONS" "" 0 + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-clusters-reader-workflow "$HBFINI_OPTIONS" "" 0 + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-preclusters-reader-workflow "$HBFINI_OPTIONS" "" 0 + has_detector TRD && has_detector_from_global_reader TRD && add_W o2-trd-digit-reader-workflow "$DISABLE_MC --digit-subspec 0 --disable-trigrec $HBFINI_OPTIONS" + has_detector TOF && has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$DISABLE_MC --input-type digits --output-type NONE $HBFINI_OPTIONS" fi if [[ ! -z $INPUT_DETECTOR_LIST ]]; then From 314755cd1de74b3d736cf15ad26ada56e9f2ff08 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Mon, 12 Feb 2024 10:50:10 +0100 Subject: [PATCH 23/50] [EMCAL-688] Add protection for MCClusterLabel access in case of nullptr (#12684) - Bug introduced in https://github.com/AliceO2Group/AliceO2/pull/12660 - If MC labels not there (e.g. in data) the object was still accessed and orderLabels() was called - Protection added to check that clusterLabel is actually present Co-authored-by: jokonig --- Detectors/EMCAL/base/src/ClusterFactory.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Detectors/EMCAL/base/src/ClusterFactory.cxx b/Detectors/EMCAL/base/src/ClusterFactory.cxx index 734ed2a5d2eab..9386f42b4e8e5 100644 --- a/Detectors/EMCAL/base/src/ClusterFactory.cxx +++ b/Detectors/EMCAL/base/src/ClusterFactory.cxx @@ -90,9 +90,10 @@ o2::emcal::AnalysisCluster ClusterFactory::buildCluster(int clusterIn std::vector cellsIdices; size_t iCell = 0; + bool addClusterLabels = ((clusterLabel != nullptr) && (mCellLabelContainer.size() > 0)); for (auto cellIndex : inputsIndices) { cellsIdices.push_back(cellIndex); - if ((clusterLabel != nullptr) && (mCellLabelContainer.size() > 0)) { + if (addClusterLabels) { for (size_t iLabel = 0; iLabel < mCellLabelContainer[iCell].GetLabelSize(); iLabel++) { clusterLabel->addValue(mCellLabelContainer[iCell].GetLabel(iLabel), mCellLabelContainer[iCell].GetAmplitudeFraction(iLabel) * mInputsContainer[iCell].getEnergy()); @@ -100,8 +101,10 @@ o2::emcal::AnalysisCluster ClusterFactory::buildCluster(int clusterIn iCell++; } } - clusterLabel->orderLabels(); - clusterLabel->normalize(cellAmp); + if (addClusterLabels) { + clusterLabel->orderLabels(); + clusterLabel->normalize(cellAmp); + } clusterAnalysis.setCellsIndices(cellsIdices); From 8c58cb56c5acd58ee42429c8f2c6c85831681f20 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:44:18 +0100 Subject: [PATCH 24/50] DPL: hide exception handling from header --- .../include/Framework/runDataProcessing.h | 43 ++----------------- Framework/Core/src/runDataProcessing.cxx | 39 +++++++++++++++++ 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index bfda47d07971c..186d76499c1d6 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -25,7 +25,6 @@ #include "Framework/CustomWorkflowTerminationHook.h" #include "Framework/CommonServices.h" #include "Framework/WorkflowCustomizationHelpers.h" -#include "Framework/RuntimeError.h" #include "Framework/ResourcePolicyHelpers.h" #include "Framework/Logger.h" #include "Framework/CheckTypes.h" @@ -33,12 +32,6 @@ #include #include -#include - -namespace boost -{ -class exception; -} namespace o2::framework { @@ -147,9 +140,6 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& specs, std::vector const& workflowOptions, o2::framework::ConfigContext& configContext); -void doBoostException(boost::exception& e, const char*); -void doDPLException(o2::framework::RuntimeErrorRef& ref, char const*); -void doUnknownException(std::string const& s, char const*); void doDefaultWorkflowTerminationHook(); template @@ -220,41 +210,14 @@ int mainNoCatch(int argc, char** argv) resourcePolicies, callbacksPolicies, sendingPolicies, workflowOptions, configContext); } +int callMain(int argc, char** argv, int (*)(int, char**)); + int main(int argc, char** argv) { using namespace o2::framework; using namespace boost::program_options; - static bool noCatch = getenv("O2_NO_CATCHALL_EXCEPTIONS") && strcmp(getenv("O2_NO_CATCHALL_EXCEPTIONS"), "0"); - int result = 1; - if (noCatch) { - try { - result = mainNoCatch(argc, argv); - } catch (o2::framework::RuntimeErrorRef& ref) { - doDPLException(ref, argv[0]); - throw; - } - } else { - try { - // The 0 here is an int, therefore having the template matching in the - // SFINAE expression above fit better the version which invokes user code over - // the default one. - // The default policy is a catch all pub/sub setup to be consistent with the past. - result = mainNoCatch(argc, argv); - } catch (boost::exception& e) { - doBoostException(e, argv[0]); - throw; - } catch (std::exception const& error) { - doUnknownException(error.what(), argv[0]); - throw; - } catch (o2::framework::RuntimeErrorRef& ref) { - doDPLException(ref, argv[0]); - throw; - } catch (...) { - doUnknownException("", argv[0]); - throw; - } - } + int result = callMain(argc, argv, mainNoCatch); char* idstring = nullptr; for (int argi = 0; argi < argc; argi++) { diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index cfbb616b0d0a5..64c034ebb8533 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -177,6 +177,45 @@ bpo::options_description gHiddenDeviceOptions("Hidden child options"); O2_DECLARE_DYNAMIC_LOG(driver); +void doBoostException(boost::exception& e, const char*); +void doDPLException(o2::framework::RuntimeErrorRef& ref, char const*); +void doUnknownException(std::string const& s, char const*); + +int callMain(int argc, char** argv, int (*mainNoCatch)(int, char**)) +{ + static bool noCatch = getenv("O2_NO_CATCHALL_EXCEPTIONS") && strcmp(getenv("O2_NO_CATCHALL_EXCEPTIONS"), "0"); + int result = 1; + if (noCatch) { + try { + result = mainNoCatch(argc, argv); + } catch (o2::framework::RuntimeErrorRef& ref) { + doDPLException(ref, argv[0]); + throw; + } + } else { + try { + // The 0 here is an int, therefore having the template matching in the + // SFINAE expression above fit better the version which invokes user code over + // the default one. + // The default policy is a catch all pub/sub setup to be consistent with the past. + result = mainNoCatch(argc, argv); + } catch (boost::exception& e) { + doBoostException(e, argv[0]); + throw; + } catch (std::exception const& error) { + doUnknownException(error.what(), argv[0]); + throw; + } catch (o2::framework::RuntimeErrorRef& ref) { + doDPLException(ref, argv[0]); + throw; + } catch (...) { + doUnknownException("", argv[0]); + throw; + } + } + return result; +} + // Read from a given fd and print it. // return true if we can still read from it, // return false if we need to close the input pipe. From 66de30958153cd7badf522150e8554f9fcf975ff Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 12 Feb 2024 13:58:57 +0100 Subject: [PATCH 25/50] Fix usage of TPC_CORR_OPT and TPC_CORR_KEY in calib-workflow.sh --- prodtests/full-system-test/calib-workflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full-system-test/calib-workflow.sh b/prodtests/full-system-test/calib-workflow.sh index e098625b9a48b..e37f5e248aa88 100755 --- a/prodtests/full-system-test/calib-workflow.sh +++ b/prodtests/full-system-test/calib-workflow.sh @@ -31,7 +31,7 @@ if [[ $CALIB_TPC_TIMEGAIN == 1 ]]; then fi if [[ $CALIB_TPC_RESPADGAIN == 1 ]]; then : ${SCALEEVENTS_TPC_RESPADGAIN:=40} - add_W o2-tpc-calib-gainmap-tracks "--publish-after-tfs 30 --useEveryNthTF $SCALEEVENTS_TPC_RESPADGAIN $TPC_CORR_SCALING" + add_W o2-tpc-calib-gainmap-tracks "--publish-after-tfs 30 --useEveryNthTF $SCALEEVENTS_TPC_RESPADGAIN $TPC_CORR_OPT" "$TPC_CORR_KEY" fi if [[ $CALIB_ZDC_TDC == 1 ]]; then add_W o2-zdc-tdccalib-epn-workflow "" "" 0; fi if [[ $CALIB_FT0_TIMEOFFSET == 1 ]]; then add_W o2-calibration-ft0-time-spectra-processor; fi From 1300dd35422153bcaa6e0e0a1bac6107c8db255a Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 1 Feb 2024 09:01:37 +0100 Subject: [PATCH 26/50] GPU: Use dumpMask for merger and clusterizer debug dump --- .../Global/GPUChainTrackingClusterizer.cxx | 16 ++++++++-------- .../Global/GPUChainTrackingMerger.cxx | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 6d11d0e8534d7..726c8c642b779 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -711,7 +711,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (fragment.index == 0) { runKernel(GetGridAutoStep(lane, RecoStep::TPCClusterFinding), krnlRunRangeNone, {}, clustererShadow.mPpadIsNoisy, TPC_PADS_IN_SECTOR * sizeof(*clustererShadow.mPpadIsNoisy)); } - DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Zeroed Charges", doGPU); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Zeroed Charges", doGPU); if (doGPU) { if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice] && mCFContext->zsVersion != -1) { @@ -799,7 +799,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (!mIOPtrs.tpcZS) { runKernel(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); } - if (DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpDigits, *mDebugFile)) { + if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpDigits, *mDebugFile)) { clusterer.DumpChargeMap(*mDebugFile, "Charges", doGPU); } @@ -818,11 +818,11 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); - DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpPeaks, *mDebugFile); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpPeaks, *mDebugFile); RunTPCClusterizer_compactPeaks(clusterer, clustererShadow, 0, doGPU, lane); TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); - DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpPeaksCompacted, *mDebugFile); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpPeaksCompacted, *mDebugFile); } GPUCA_OPENMP(parallel for if(!doGPU && GetProcessingSettings().ompKernels != 1) num_threads(mRec->SetAndGetNestedLoopOmpFactor(!doGPU, GetProcessingSettings().nTPCClustererLanes))) for (int lane = 0; lane < maxLane; lane++) { @@ -837,11 +837,11 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel(GetGrid(clusterer.mPmemory->counters.nPeaks, lane), {iSlice}, {}); runKernel(GetGrid(clusterer.mPmemory->counters.nPeaks, lane), {iSlice}, {}); - DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaks, *mDebugFile); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaks, *mDebugFile); RunTPCClusterizer_compactPeaks(clusterer, clustererShadow, 1, doGPU, lane); TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); - DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaksCompacted, *mDebugFile); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaksCompacted, *mDebugFile); } GPUCA_OPENMP(parallel for if(!doGPU && GetProcessingSettings().ompKernels != 1) num_threads(mRec->SetAndGetNestedLoopOmpFactor(!doGPU, GetProcessingSettings().nTPCClustererLanes))) for (int lane = 0; lane < maxLane; lane++) { @@ -862,7 +862,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel(GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}, {}); - DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges", doGPU); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges", doGPU); runKernel(GetGrid(clusterer.mPmemory->counters.nClusters, lane), {iSlice}, {}, 0); if (doGPU && propagateMCLabels) { @@ -878,7 +878,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) TransferMemoryResourcesToHost(RecoStep::TPCClusterFinding, &clusterer, lane); laneHasData[lane] = true; - if (DoDebugAndDump(RecoStep::TPCClusterFinding, 0, clusterer, &GPUTPCClusterFinder::DumpCountedPeaks, *mDebugFile)) { + if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpCountedPeaks, *mDebugFile)) { clusterer.DumpClusters(*mDebugFile); } } diff --git a/GPU/GPUTracking/Global/GPUChainTrackingMerger.cxx b/GPU/GPUTracking/Global/GPUChainTrackingMerger.cxx index 23e37e5bcf382..4b9bfbde6990a 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingMerger.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingMerger.cxx @@ -136,14 +136,14 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone, i); } runKernel({1, -WarpSize(), 0, deviceType}, krnlRunRangeNone, krnlEventNone, 2 * NSLICES); - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpSliceTracks, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpSliceTracks, *mDebugFile); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone, 0); runKernel({1, -WarpSize(), 0, deviceType, RecoStep::TPCMerging}, krnlRunRangeNone, {}, MergerShadowAll.TmpCounter(), NSLICES * sizeof(*MergerShadowAll.TmpCounter())); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); RunTPCTrackingMerger_MergeBorderTracks(1, 0, deviceType); RunTPCTrackingMerger_Resolve(0, 1, deviceType); - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpMergedWithinSlices, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpMergedWithinSlices, *mDebugFile); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone, 0); runKernel({1, -WarpSize(), 0, deviceType, RecoStep::TPCMerging}, krnlRunRangeNone, {}, MergerShadowAll.TmpCounter(), 2 * NSLICES * sizeof(*MergerShadowAll.TmpCounter())); @@ -158,20 +158,20 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) runKernel(GetGridBlk(std::max(2u, numBlocks), 0, deviceType), krnlRunRangeNone, krnlEventNone, 0, 1, 1); RunTPCTrackingMerger_MergeBorderTracks(0, -1, deviceType); RunTPCTrackingMerger_Resolve(0, 1, deviceType); - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpMergedBetweenSlices, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpMergedBetweenSlices, *mDebugFile); runKernel({1, -WarpSize(), 0, deviceType, RecoStep::TPCMerging}, krnlRunRangeNone, {}, MergerShadowAll.TmpCounter(), 2 * NSLICES * sizeof(*MergerShadowAll.TmpCounter())); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpCollected, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpCollected, *mDebugFile); if (param().rec.tpc.mergeCE) { runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone, 1); RunTPCTrackingMerger_MergeBorderTracks(-1, 1, deviceType); RunTPCTrackingMerger_MergeBorderTracks(-1, 2, deviceType); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpMergeCE, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpMergeCE, *mDebugFile); } int waitForTransfer = 0; if (doGPUall) { @@ -199,7 +199,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); } - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpFitPrepare, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpFitPrepare, *mDebugFile); if (doGPUall) { CondWaitEvent(waitForTransfer, &mEvents->single); @@ -229,7 +229,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) SynchronizeStream(0); } - DoDebugAndDump(RecoStep::TPCMerging, 0, Merger, &GPUTPCGMMerger::DumpRefit, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, Merger, &GPUTPCGMMerger::DumpRefit, *mDebugFile); runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); if (!param().rec.nonConsecutiveIDs) { runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); @@ -244,7 +244,7 @@ int GPUChainTracking::RunTPCTrackingMerger(bool synchronizeOutput) runKernel(GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); runKernel(doGPUall ? GetGrid(Merger.Memory()->nLooperMatchCandidates, 0, deviceType) : GetGridAuto(0, deviceType), krnlRunRangeNone, krnlEventNone); } - DoDebugAndDump(RecoStep::TPCMerging, 0, doGPUall, Merger, &GPUTPCGMMerger::DumpFinal, *mDebugFile); + DoDebugAndDump(RecoStep::TPCMerging, 2048, doGPUall, Merger, &GPUTPCGMMerger::DumpFinal, *mDebugFile); if (doGPUall) { RecordMarker(&mEvents->single, 0); From 758ab9d410a9755c6d3018d0d399e559b06123e4 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 6 Feb 2024 13:25:59 +0100 Subject: [PATCH 27/50] GPU: Remove obsolete settings --- GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h | 1 - GPU/GPUTracking/SliceTracker/GPUTPCDef.h | 7 ------- 2 files changed, 8 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h index 2688b416e9ecd..2ae729b19ad53 100644 --- a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h +++ b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h @@ -68,7 +68,6 @@ //#define GPUCA_FULL_CLUSTERDATA // Store all cluster information in the cluster data, also those not needed for tracking. //#define GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME // Propagate Pad, Row, Time cluster information to GM //#define GPUCA_GM_USE_FULL_FIELD // Use offline magnetic field during GMPropagator prolongation -//#define GPUCA_TPC_USE_STAT_ERROR // Use statistical errors from offline in track fit // clang-format on diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCDef.h b/GPU/GPUTracking/SliceTracker/GPUTPCDef.h index eb56b02126b7d..12548078dc5f5 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCDef.h +++ b/GPU/GPUTracking/SliceTracker/GPUTPCDef.h @@ -36,10 +36,6 @@ struct cahit2 { cahit x, y; }; } } // GPUCA_NAMESPACE::GPU -#ifdef GPUCA_TPC_USE_STAT_ERROR - #define GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME -#endif - #ifdef GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME // Needs full clusterdata #define GPUCA_FULL_CLUSTERDATA #endif @@ -48,9 +44,6 @@ struct cahit2 { cahit x, y; }; #ifdef GPUCA_GM_USE_FULL_FIELD #undef GPUCA_GM_USE_FULL_FIELD #endif - #ifdef GPUCA_TPC_USE_STAT_ERROR - #undef GPUCA_TPC_USE_STAT_ERROR - #endif #endif #endif //GPUDTPCEF_H From afc110f526ca1ffbfa5ad575d79d3023da63d0a9 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 6 Feb 2024 13:30:54 +0100 Subject: [PATCH 28/50] GPU: Fix maxTime in track model decoding of triggered data + cleanup --- GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx | 2 +- GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h | 2 ++ GPU/GPUTracking/Definitions/clusterFinderDefs.h | 1 - GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx index b8f491a6f5767..a5b84369a46e2 100644 --- a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx +++ b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx @@ -52,7 +52,7 @@ int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompres (&locks[0][0])[i].clear(); } unsigned int offset = 0, lasti = 0; - const unsigned int maxTime = (param.par.continuousMaxTimeBin + 1) * ClusterNative::scaleTimePacked - 1; + const unsigned int maxTime = param.par.continuousMaxTimeBin > 0 ? ((param.par.continuousMaxTimeBin + 1) * ClusterNative::scaleTimePacked - 1) : TPC_MAX_TIME_BIN_TRIGGERED; GPUCA_OPENMP(parallel for firstprivate(offset, lasti)) for (unsigned int i = 0; i < clustersCompressed->nTracks; i++) { if (i < lasti) { diff --git a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h index 2ae729b19ad53..fd9a8163dc38a 100644 --- a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h +++ b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h @@ -46,6 +46,8 @@ #define GPUCA_TPC_COMP_CHUNK_SIZE 1024 // Chunk size of sorted unattached TPC cluster in compression +#define TPC_MAX_TIME_BIN_TRIGGERED 600 + #if defined(GPUCA_HAVE_O2HEADERS) && (!defined(__OPENCL__) || defined(__OPENCLCPP__)) && !(defined(ROOT_VERSION_CODE) && ROOT_VERSION_CODE < 393216) && defined(__has_include) #if __has_include("DataFormatsTPC/Constants.h") //Use definitions from the O2 headers if available for nicer code and type safety diff --git a/GPU/GPUTracking/Definitions/clusterFinderDefs.h b/GPU/GPUTracking/Definitions/clusterFinderDefs.h index 2aa81d5953e84..fb5cd7a1fc0c7 100644 --- a/GPU/GPUTracking/Definitions/clusterFinderDefs.h +++ b/GPU/GPUTracking/Definitions/clusterFinderDefs.h @@ -52,7 +52,6 @@ using ulong = unsigned long; #define TPC_MAX_FRAGMENT_LEN_GPU 4000 #define TPC_MAX_FRAGMENT_LEN_HOST 1000 #define TPC_MAX_FRAGMENT_LEN_PADDED(size) ((size) + 2 * GPUCF_PADDING_TIME) -#define TPC_MAX_TIME_BIN_TRIGGERED 600 #if 0 #define DBG_PRINT(msg, ...) printf(msg "\n", __VA_ARGS__) diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx index 48d88272d42a1..a5fa2aa1b31a2 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCSliceData.cxx @@ -112,7 +112,7 @@ void* GPUTPCSliceData::SetPointersRows(void* mem) GPUd() void GPUTPCSliceData::GetMaxNBins(GPUconstantref() const MEM_CONSTANT(GPUConstantMem) * mem, GPUTPCRow* GPUrestrict() row, int& maxY, int& maxZ) { maxY = row->mMaxY * 2.f / GPUCA_MIN_BIN_SIZE + 1; - maxZ = mem->param.par.continuousMaxTimeBin > 0 ? mem->calibObjects.fastTransformHelper->getCorrMap()->convTimeToZinTimeFrame(0, 0, mem->param.par.continuousMaxTimeBin) + 50 : 300; + maxZ = (mem->param.par.continuousMaxTimeBin > 0 ? (mem->calibObjects.fastTransformHelper->getCorrMap()->convTimeToZinTimeFrame(0, 0, mem->param.par.continuousMaxTimeBin)) : mem->param.tpcGeometry.TPCLength()) + 50; maxZ = maxZ / GPUCA_MIN_BIN_SIZE + 1; } From 8e59becdfc476000f7b1ea3d2dd0023a1e0fce45 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 5 Feb 2024 20:06:50 +0100 Subject: [PATCH 29/50] GPU TPC: Create and distribute TPC Cluster Occupancy Map --- GPU/GPUTracking/Base/GPUParam.inc | 4 +- GPU/GPUTracking/Base/GPUReconstructionCPU.h | 1 + .../Base/GPUReconstructionIncludesDevice.h | 3 + GPU/GPUTracking/CMakeLists.txt | 2 + GPU/GPUTracking/DataTypes/GPUOutputControl.h | 1 + .../DataTypes/GPUTPCClusterOccupancyMap.cxx | 29 +++++++++ .../DataTypes/GPUTPCClusterOccupancyMap.h | 33 ++++++++++ .../Definitions/GPUDefGPUParameters.h | 6 ++ GPU/GPUTracking/Definitions/GPUSettingsList.h | 1 + GPU/GPUTracking/Global/GPUChain.h | 4 ++ .../Global/GPUChainTrackingSliceTracker.cxx | 17 +++++- .../Global/GPUTrackingInputProvider.cxx | 13 +++- .../Global/GPUTrackingInputProvider.h | 6 ++ .../SliceTracker/GPUTPCCreateOccupancyMap.cxx | 60 +++++++++++++++++++ .../SliceTracker/GPUTPCCreateOccupancyMap.h | 39 ++++++++++++ GPU/GPUTracking/kernels.cmake | 2 + GPU/Workflow/src/GPUWorkflowSpec.cxx | 6 ++ 17 files changed, 223 insertions(+), 4 deletions(-) create mode 100644 GPU/GPUTracking/DataTypes/GPUTPCClusterOccupancyMap.cxx create mode 100644 GPU/GPUTracking/DataTypes/GPUTPCClusterOccupancyMap.h create mode 100644 GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.cxx create mode 100644 GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.h diff --git a/GPU/GPUTracking/Base/GPUParam.inc b/GPU/GPUTracking/Base/GPUParam.inc index 2cb5f2275b13d..bfbedb374d098 100644 --- a/GPU/GPUTracking/Base/GPUParam.inc +++ b/GPU/GPUTracking/Base/GPUParam.inc @@ -77,9 +77,9 @@ GPUdi() float MEM_LG(GPUParam)::GetSystematicClusterErrorIFC2(float x, float z, } else if (rec.tpc.sysClusErrorZRegion > kEpsZBoundary && sideC) { return 0; // don't apply to C-side clusters if the Z-boundary is for A-region } - const float dz = CAMath::Abs((rec.tpc.sysClusErrorZRegion-z)*rec.tpc.sysClusErrorZRegionSigInv); + const float dz = CAMath::Abs((rec.tpc.sysClusErrorZRegion - z) * rec.tpc.sysClusErrorZRegionSigInv); if (dz < kMaxExpArgZ) { // is it small enough to call exp? - argExp += 0.5f * dz*dz; + argExp += 0.5f * dz * dz; if (argExpgetTimer(name, num); } + // Get GRID with NBLOCKS minimal such that nThreads * NBLOCS >= totalItems krnlExec GetGrid(unsigned int totalItems, unsigned int nThreads, int stream, GPUReconstruction::krnlDeviceType d = GPUReconstruction::krnlDeviceType::Auto, GPUCA_RECO_STEP st = GPUCA_RECO_STEP::NoRecoStep); + // Get GRID with NBLOCKS minimal such that ideal number of threads * NBLOCKS >= totalItems krnlExec GetGrid(unsigned int totalItems, int stream, GPUReconstruction::krnlDeviceType d = GPUReconstruction::krnlDeviceType::Auto, GPUCA_RECO_STEP st = GPUCA_RECO_STEP::NoRecoStep); + // Get GRID with specified number of blocks, each block with ideal number of threads krnlExec GetGridBlk(unsigned int nBlocks, int stream, GPUReconstruction::krnlDeviceType d = GPUReconstruction::krnlDeviceType::Auto, GPUCA_RECO_STEP st = GPUCA_RECO_STEP::NoRecoStep); krnlExec GetGridBlkStep(unsigned int nBlocks, int stream, GPUCA_RECO_STEP st = GPUCA_RECO_STEP::NoRecoStep); + // Get GRID with ideal number of threads / blocks for GPU krnlExec GetGridAuto(int stream, GPUReconstruction::krnlDeviceType d = GPUReconstruction::krnlDeviceType::Auto, GPUCA_RECO_STEP st = GPUCA_RECO_STEP::NoRecoStep); krnlExec GetGridAutoStep(int stream, GPUCA_RECO_STEP st = GPUCA_RECO_STEP::NoRecoStep); diff --git a/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx b/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx index 4d023cc8bca22..379c302159ef5 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx @@ -17,6 +17,8 @@ #include "GPUO2DataTypes.h" #include "GPUMemorySizeScalers.h" #include "GPUTPCClusterData.h" +#include "GPUTrackingInputProvider.h" +#include "GPUTPCClusterOccupancyMap.h" #include "utils/strtag.h" #include @@ -143,6 +145,20 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() return (2); } + if (param().rec.tpc.occupancyMapTimeBins) { + AllocateRegisteredMemory(mInputsHost->mResourceOccupancyMap, mSubOutputControls[GPUTrackingOutputs::getIndex(&GPUTrackingOutputs::tpcOccupancyMap)]); + ReleaseEvent(mEvents->init); + auto* ptr = doGPU ? mInputsShadow->mTPCClusterOccupancyMap : mInputsHost->mTPCClusterOccupancyMap; + runKernel(GetGridAutoStep(mRec->NStreams() - 1, RecoStep::TPCSliceTracking), krnlRunRangeNone, {}, ptr, GPUTPCClusterOccupancyMapBin::getTotalSize(param())); + runKernel(GetGridBlk(GPUCA_NSLICES * GPUCA_ROW_COUNT, mRec->NStreams() - 1), krnlRunRangeNone, krnlEventNone, ptr); + runKernel(GetGridBlk(GPUCA_NSLICES * GPUCA_ROW_COUNT, mRec->NStreams() - 1), krnlRunRangeNone, {&mEvents->init}, ptr); + if (doGPU) { + TransferMemoryResourceLinkToHost(RecoStep::TPCSliceTracking, mInputsHost->mResourceOccupancyMap); + } else { + TransferMemoryResourceLinkToGPU(RecoStep::TPCSliceTracking, mInputsHost->mResourceOccupancyMap); + } + } + int streamMap[NSLICES]; bool error = false; @@ -170,7 +186,6 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() GPUInfo("Waiting for helper thread %d", iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) - 1); } while (HelperDone(iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) - 1) < (int)iSlice) { - ; } if (HelperError(iSlice % (GetProcessingSettings().nDeviceHelperThreads + 1) - 1)) { error = 1; diff --git a/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx b/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx index 2d9f7aea723d4..f541b4a6be8d1 100644 --- a/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx +++ b/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx @@ -16,6 +16,7 @@ #include "GPUDataTypes.h" #include "GPUTRDTrackletWord.h" #include "GPUReconstruction.h" +#include "GPUTPCClusterOccupancyMap.h" #include "GPUErrors.h" using namespace GPUCA_NAMESPACE::gpu; @@ -75,10 +76,19 @@ void* GPUTrackingInputProvider::SetPointersInputTRD(void* mem) return mem; } +void* GPUTrackingInputProvider::SetPointersTPCOccupancyMap(void* mem) +{ + if (mHoldTPCOccupancyMap) { + computePointerWithAlignment(mem, mTPCClusterOccupancyMap, GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam())); + } + return mem; +} + void GPUTrackingInputProvider::RegisterMemoryAllocation() { mResourceErrorCodes = mRec->RegisterMemoryAllocation(this, &GPUTrackingInputProvider::SetPointersErrorCodes, GPUMemoryResource::MEMORY_PERMANENT, "ErrorCodes"); mResourceZS = mRec->RegisterMemoryAllocation(this, &GPUTrackingInputProvider::SetPointersInputZS, GPUMemoryResource::MEMORY_INPUT | GPUMemoryResource::MEMORY_PERMANENT, "InputZS"); + mResourceOccupancyMap = mRec->RegisterMemoryAllocation(this, &GPUTrackingInputProvider::SetPointersTPCOccupancyMap, GPUMemoryResource::MEMORY_INOUT | GPUMemoryResource::MEMORY_CUSTOM, "OccupancyMap"); mResourceClusterNativeAccess = mRec->RegisterMemoryAllocation(this, &GPUTrackingInputProvider::SetPointersInputClusterNativeAccess, GPUMemoryResource::MEMORY_INPUT, "ClusterNativeAccess"); mResourceClusterNativeBuffer = mRec->RegisterMemoryAllocation(this, &GPUTrackingInputProvider::SetPointersInputClusterNativeBuffer, GPUMemoryResource::MEMORY_INPUT_FLAG | GPUMemoryResource::MEMORY_GPU | GPUMemoryResource::MEMORY_EXTERNAL | GPUMemoryResource::MEMORY_CUSTOM, "ClusterNativeBuffer"); mResourceClusterNativeOutput = mRec->RegisterMemoryAllocation(this, &GPUTrackingInputProvider::SetPointersInputClusterNativeOutput, GPUMemoryResource::MEMORY_OUTPUT_FLAG | GPUMemoryResource::MEMORY_HOST | GPUMemoryResource::MEMORY_CUSTOM, "ClusterNativeOutput"); @@ -89,5 +99,6 @@ void GPUTrackingInputProvider::SetMaxData(const GPUTrackingInOutPointers& io) { mHoldTPCZS = io.tpcZS && (mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding); mHoldTPCClusterNative = (io.tpcZS || io.tpcPackedDigits || io.clustersNative || io.tpcCompressedClusters) && mRec->IsGPU(); - mHoldTPCClusterNativeOutput = (io.tpcZS || io.tpcPackedDigits || io.tpcCompressedClusters); + mHoldTPCOccupancyMap = (io.tpcZS || io.tpcPackedDigits || io.clustersNative || io.tpcCompressedClusters) && mRec->GetParam().rec.tpc.occupancyMapTimeBins; + mHoldTPCClusterNativeOutput = io.tpcZS || io.tpcPackedDigits || io.tpcCompressedClusters; } diff --git a/GPU/GPUTracking/Global/GPUTrackingInputProvider.h b/GPU/GPUTracking/Global/GPUTrackingInputProvider.h index a14dcdebc39de..0f958353fa464 100644 --- a/GPU/GPUTracking/Global/GPUTrackingInputProvider.h +++ b/GPU/GPUTracking/Global/GPUTrackingInputProvider.h @@ -33,6 +33,7 @@ namespace gpu { struct GPUTrackingInOutZS; +struct GPUTPCClusterOccupancyMapBin; class GPUTRDTrackletWord; class GPUTRDSpacePoint; @@ -44,6 +45,7 @@ class GPUTrackingInputProvider : public GPUProcessor void RegisterMemoryAllocation(); void SetMaxData(const GPUTrackingInOutPointers& io); + void* SetPointersTPCOccupancyMap(void* mem); void* SetPointersInputZS(void* mem); void* SetPointersInputClusterNativeAccess(void* mem); void* SetPointersInputClusterNativeBuffer(void* mem); @@ -58,10 +60,12 @@ class GPUTrackingInputProvider : public GPUProcessor unsigned short mResourceClusterNativeOutput = -1; unsigned short mResourceErrorCodes = -1; unsigned short mResourceTRD = -1; + unsigned short mResourceOccupancyMap = -1; bool mHoldTPCZS = false; bool mHoldTPCClusterNative = false; bool mHoldTPCClusterNativeOutput = false; + bool mHoldTPCOccupancyMap = false; unsigned int mNClusterNative = 0; GPUTrackingInOutZS* mPzsMeta = nullptr; @@ -81,6 +85,8 @@ class GPUTrackingInputProvider : public GPUProcessor o2::tpc::ClusterNative* mPclusterNativeBuffer = nullptr; o2::tpc::ClusterNative* mPclusterNativeOutput = nullptr; + GPUTPCClusterOccupancyMapBin* mTPCClusterOccupancyMap = nullptr; + unsigned int* mErrorCodes = nullptr; }; diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.cxx new file mode 100644 index 0000000000000..749ea81dd528b --- /dev/null +++ b/GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.cxx @@ -0,0 +1,60 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file GPUTPCCreateOccupancyMap.cxx +/// \author David Rohr + +#include "GPUTPCCreateOccupancyMap.h" +#include "GPUTPCClusterOccupancyMap.h" + +using namespace GPUCA_NAMESPACE::gpu; + +template <> +GPUdii() void GPUTPCCreateOccupancyMap::Thread<0>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() processors, GPUTPCClusterOccupancyMapBin* GPUrestrict() map) +{ + const GPUTrackingInOutPointers& GPUrestrict() ioPtrs = processors.ioPtrs; + const o2::tpc::ClusterNativeAccess* GPUrestrict() clusters = ioPtrs.clustersNative; + GPUParam& GPUrestrict() param = processors.param; + const int iSliceRow = iBlock * nThreads + iThread; + if (iSliceRow >= GPUCA_ROW_COUNT * GPUCA_NSLICES) { + return; + } + const unsigned int iSlice = iSliceRow / GPUCA_ROW_COUNT; + const unsigned int iRow = iSliceRow % GPUCA_ROW_COUNT; + for (unsigned int i = 0; i < clusters->nClusters[iSlice][iRow]; i++) { + const unsigned int bin = clusters->clusters[iSlice][iRow][i].getTime() / param.rec.tpc.occupancyMapTimeBins; + map[bin].bin[iSlice][iRow]++; + } +} + +template <> +GPUdii() void GPUTPCCreateOccupancyMap::Thread<1>(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() processors, GPUTPCClusterOccupancyMapBin* GPUrestrict() map) +{ + GPUParam& GPUrestrict() param = processors.param; + const int iSliceRow = iBlock * nThreads + iThread; + if (iSliceRow > GPUCA_ROW_COUNT * GPUCA_NSLICES) { + return; + } + const unsigned int iSlice = iSliceRow / GPUCA_ROW_COUNT; + const unsigned int iRow = iSliceRow % GPUCA_ROW_COUNT; + const unsigned int nBins = GPUTPCClusterOccupancyMapBin::getNBins(param); + const unsigned int nFoldBins = CAMath::Min(5u, nBins); + unsigned int sum = 0; + for (unsigned int i = 0; i < nFoldBins; i++) { + sum += map[i].bin[iSlice][iRow]; + } + unsigned short lastVal; + for (unsigned int i = 0; i < nBins; i++) { + lastVal = map[i].bin[iSlice][iRow]; + map[i].bin[iSlice][iRow] = sum / nFoldBins; + sum += map[CAMath::Min(i + nFoldBins, nBins - 1)].bin[iSlice][iRow] - lastVal; + } +} diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.h b/GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.h new file mode 100644 index 0000000000000..33a0d18b92a30 --- /dev/null +++ b/GPU/GPUTracking/SliceTracker/GPUTPCCreateOccupancyMap.h @@ -0,0 +1,39 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file GPUTPCCreateOccupancyMap.h +/// \author David Rohr + +#ifndef GPUTPCCREATEOCCUPANCYMAP_H +#define GPUTPCCREATEOCCUPANCYMAP_H + +#include "GPUTPCDef.h" +#include "GPUGeneralKernels.h" +#include "GPUConstantMem.h" + +namespace GPUCA_NAMESPACE::gpu +{ +struct GPUTPCClusterOccupancyMapBin; + +class GPUTPCCreateOccupancyMap : public GPUKernelTemplate +{ + public: + enum K { defaultKernel = 0, + fill = 0, + fold = 1 }; + GPUhdi() CONSTEXPR static GPUDataTypes::RecoStep GetRecoStep() { return GPUDataTypes::RecoStep::TPCSliceTracking; } + template + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors, GPUTPCClusterOccupancyMapBin* map); +}; + +} // namespace GPUCA_NAMESPACE::gpu + +#endif diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index b06749010d2d9..ff35e7e0e02cc 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -23,6 +23,8 @@ o2_gpu_add_kernel("GPUMemClean16" NO_OCL1 "simple o2_gpu_add_kernel("GPUTPCGlobalTrackingCopyNumbers" NO_OCL1 single int n) o2_gpu_add_kernel("GPUTPCCreateSliceData" LB single) o2_gpu_add_kernel("GPUTPCGlobalTracking" LB single) +o2_gpu_add_kernel("GPUTPCCreateOccupancyMap, fill" LB simple GPUTPCClusterOccupancyMapBin* map) +o2_gpu_add_kernel("GPUTPCCreateOccupancyMap, fold" LB simple GPUTPCClusterOccupancyMapBin* map) o2_gpu_add_kernel("GPUTPCGMMergerTrackFit" LB simple int mode) o2_gpu_add_kernel("GPUTPCGMMergerFollowLoopers" LB simple) o2_gpu_add_kernel("GPUTPCGMMergerUnpackResetIds" LB simple int iSlice) diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index b1f4b00d3240f..3e024c595b97c 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -737,6 +737,7 @@ void GPURecoWorkflowSpec::run(ProcessingContext& pc) setOutputAllocator("COMPCLUSTERSFLAT", mSpecConfig.outputCompClustersFlat, outputRegions.compressedClusters, std::make_tuple(gDataOriginTPC, (DataDescription) "COMPCLUSTERSFLAT", 0)); setOutputAllocator("CLUSTERNATIVE", mClusterOutputIds.size() > 0, outputRegions.clustersNative, std::make_tuple(gDataOriginTPC, mSpecConfig.sendClustersPerSector ? (DataDescription) "CLUSTERNATIVETMP" : (DataDescription) "CLUSTERNATIVE", NSectors, clusterOutputSectorHeader), sizeof(o2::tpc::ClusterCountIndex)); setOutputAllocator("CLSHAREDMAP", mSpecConfig.outputSharedClusterMap, outputRegions.sharedClusterMap, std::make_tuple(gDataOriginTPC, (DataDescription) "CLSHAREDMAP", 0)); + setOutputAllocator("TPCOCCUPANCYMAP", mSpecConfig.outputSharedClusterMap, outputRegions.tpcOccupancyMap, std::make_tuple(gDataOriginTPC, (DataDescription) "TPCOCCUPANCYMAP", 0)); setOutputAllocator("TRACKS", mSpecConfig.outputTracks, outputRegions.tpcTracksO2, std::make_tuple(gDataOriginTPC, (DataDescription) "TRACKS", 0)); setOutputAllocator("CLUSREFS", mSpecConfig.outputTracks, outputRegions.tpcTracksO2ClusRefs, std::make_tuple(gDataOriginTPC, (DataDescription) "CLUSREFS", 0)); setOutputAllocator("TRACKSMCLBL", mSpecConfig.outputTracks && mSpecConfig.processMC, outputRegions.tpcTracksO2Labels, std::make_tuple(gDataOriginTPC, (DataDescription) "TRACKSMCLBL", 0)); @@ -837,6 +838,10 @@ void GPURecoWorkflowSpec::run(ProcessingContext& pc) } } + if (mConfig->configReconstruction.tpc.occupancyMapTimeBins == 0) { + pc.outputs().make>({gDataOriginTPC, "TPCOCCUPANCYMAP", 0}, 0u); + } + std::unique_ptr tmpEmptyClNative; if (createEmptyOutput) { memset(&ptrs, 0, sizeof(ptrs)); @@ -1201,6 +1206,7 @@ Outputs GPURecoWorkflowSpec::outputs() } if (mSpecConfig.outputSharedClusterMap) { outputSpecs.emplace_back(gDataOriginTPC, "CLSHAREDMAP", 0, Lifetime::Timeframe); + outputSpecs.emplace_back(gDataOriginTPC, "TPCOCCUPANCYMAP", 0, Lifetime::Timeframe); } if (mSpecConfig.tpcTriggerHandling) { outputSpecs.emplace_back(gDataOriginTPC, "TRIGGERWORDS", 0, Lifetime::Timeframe); From 63a5bb6bb57ac478ba7d47e18690a3321326b799 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 13 Feb 2024 00:45:58 +0100 Subject: [PATCH 30/50] Add matches info tree to track-mc-study --- .../study/src/TrackMCStudy.cxx | 97 +++++++++++++------ 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx index cb9cadec23776..810a8a0d5de9e 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx @@ -24,6 +24,7 @@ #include "CommonDataFormat/BunchFilling.h" #include "CommonUtils/NameConf.h" #include "DataFormatsFT0/RecPoints.h" +#include "DataFormatsITSMFT/TrkClusRef.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "FT0Reconstruction/InteractionTag.h" @@ -268,7 +269,7 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) LOGP(info, "[{}] Lbl:{} PDG:{:+5d} (par: {:+5d}) | MC: {}", vgids.size(), lbl.asString(), pdg, pdgParent, mctrO2.asString()); } bool itstpcMatch = false; - int entITS = -1, entTPC = -1; + int entITS = -1, entTPC = -1, entITSTPC = -1; for (size_t i = 0; i < vgids.size(); i++) { auto vid = vgids[i].second; auto lbl = recoData.getTrackMCLabel(vid); @@ -287,6 +288,7 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) } if (msk[DetID::ITS] && msk[DetID::TPC]) { itstpcMatch = true; + entITSTPC = i; } else { if (vid.getSource() == VTIndex::ITS) { entITS = i; @@ -314,36 +316,71 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) << "\n"; // special ITS-TPC matching failure output - while (mCheckMatching && !itstpcMatch && entITS > -1 && entTPC > -1) { // ITS and TPC were found but matching failed - auto vidITS = vgids[entITS].second; - auto vidTPC = recoData.getTPCContributorGID(vgids[entTPC].second); // might be TPC match to outer detector, extract TPC - auto trcTPC = recoData.getTrackParam(vidTPC); - auto trcITS = recoData.getTrackParam(vidITS); - if (!propagateToRefX(trcTPC, trcITS)) { - break; + while (mCheckMatching) { + if (!itstpcMatch && entITS > -1 && entTPC > -1) { // ITS and TPC were found but matching failed + auto vidITS = vgids[entITS].second; + auto vidTPC = recoData.getTPCContributorGID(vgids[entTPC].second); // might be TPC match to outer detector, extract TPC + auto trcTPC = recoData.getTrackParam(vidTPC); + auto trcITS = recoData.getTrackParam(vidITS); + if (!propagateToRefX(trcTPC, trcITS)) { + break; + } + const auto& trcTPCOrig = recoData.getTPCTrack(vidTPC); + const auto& trcITSOrig = recoData.getITSTrack(vidITS); + int lowestTPCRow = lowestPadrows[entTPC]; + float tpcT0 = trcTPCOrig.getTime0(), tF = trcTPCOrig.getDeltaTFwd(), tB = trcTPCOrig.getDeltaTBwd(); + TBracket tpcBr((tpcT0 - tB) * mTPCTBinMUS, (tpcT0 + tF) * mTPCTBinMUS); + + (*mDBGOut) << "failMatch" + << "mcTr=" << mctrO2 + << "pdg=" << pdg + << "pdgPar=" << pdgParent + << "labelITS=" << recoData.getTrackMCLabel(vidITS) + << "labelTPC=" << recoData.getTrackMCLabel(vidTPC) + << "gidITS=" << vidITS + << "gidTPC=" << vidTPC + << "itsBracket=" << mITSROFBracket[mITSROF[vidITS.getIndex()]] + << "tpcBracket=" << tpcBr + << "itsRef=" << trcITS + << "tpcRef=" << trcTPC + << "itsOrig=" << trcITSOrig + << "tpcOrig=" << trcTPCOrig + << "tpcLowestRow=" << lowestTPCRow + << "\n"; + } else if (itstpcMatch) { // match was found + auto contribIDs = recoData.getSingleDetectorRefs(vgids[entITSTPC].second); + auto vidMatch = contribIDs[VTIndex::ITSTPC]; + auto vidTPC = contribIDs[VTIndex::TPC]; + auto vidITS = contribIDs[VTIndex::ITSAB].isSourceSet() ? contribIDs[VTIndex::ITSAB] : contribIDs[VTIndex::ITS]; + const auto& trcTPCOrig = recoData.getTPCTrack(vidTPC); + o2::MCCompLabel itsLb; + int nITScl = 0; + if (vidITS.getSource() == VTIndex::ITS) { + itsLb = recoData.getTrackMCLabel(vidITS); + nITScl = recoData.getITSTrack(vidITS).getNClusters(); + } else { + itsLb = recoData.getITSABMCLabels()[vidITS]; + nITScl = recoData.getITSABRefs()[vidITS].getNClusters(); + } + int lowestTPCRow = lowestPadrows[entITSTPC]; + const auto& trackITSTPC = recoData.getTPCITSTrack(vidMatch); + float timeTB = trackITSTPC.getTimeMUS().getTimeStamp() / o2::constants::lhc::LHCBunchSpacingMUS / 8; // ITS-TPC time in TPC timebins + + (*mDBGOut) << "match" + << "mcTr=" << mctrO2 + << "pdg=" << pdg + << "pdgPar=" << pdgParent + << "labelMatch=" << recoData.getTrackMCLabel(vidMatch) + << "labelTPC=" << recoData.getTrackMCLabel(vidTPC) + << "labelITS=" << itsLb + << "gidTPC=" << vidTPC + << "gidITS=" << vidITS + << "tpcOrig=" << trcTPCOrig + << "itstpc=" << ((o2::track::TrackParCov&)trackITSTPC) + << "timeTB=" << timeTB + << "tpcLowestRow=" << lowestTPCRow + << "\n"; } - const auto& trcTPCOrig = recoData.getTPCTrack(vidTPC); - const auto& trcITSOrig = recoData.getITSTrack(vidITS); - int lowestTPCRow = lowestPadrows[entTPC]; - float tpcT0 = trcTPCOrig.getTime0(), tF = trcTPCOrig.getDeltaTFwd(), tB = trcTPCOrig.getDeltaTBwd(); - TBracket tpcBr((tpcT0 - tB) * mTPCTBinMUS, (tpcT0 + tF) * mTPCTBinMUS); - - (*mDBGOut) << "failMatch" - << "mcTr=" << mctrO2 - << "pdg=" << pdg - << "pdgPar=" << pdgParent - << "fakeITS=" << recoData.getTrackMCLabel(vidITS) - << "fakeTPC=" << recoData.getTrackMCLabel(vidTPC) - << "gidITS=" << vidITS - << "gidTPC=" << vidTPC - << "itsBracket=" << mITSROFBracket[mITSROF[vidITS.getIndex()]] - << "tpcBracket=" << tpcBr - << "itsRef=" << trcITS - << "tpcRef=" << trcTPC - << "itsOrig=" << trcITSOrig - << "tpcOrig=" << trcTPCOrig - << "tpcLowestRow=" << lowestTPCRow - << "\n"; break; } } From f572f2c2e4f9d5accd48c7dc6569b56b4c0beede Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 12 Feb 2024 16:11:27 +0100 Subject: [PATCH 31/50] DPL Analysis: make sure additional AOD origins are not skipped --- Framework/Core/src/CommonDataProcessors.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 3c86f921c01b8..48a3eb1da95b9 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -41,6 +41,7 @@ #include "Framework/RateLimiter.h" #include "Framework/Plugins.h" #include "Framework/DeviceSpec.h" +#include "WorkflowHelpers.h" #include #include "TFile.h" @@ -370,8 +371,7 @@ DataProcessorSpec } // skip non-AOD refs - if (!DataSpecUtils::partialMatch(*ref.spec, header::DataOrigin("AOD")) && - !DataSpecUtils::partialMatch(*ref.spec, header::DataOrigin("DYN"))) { + if (!DataSpecUtils::partialMatch(*ref.spec, writableAODOrigins)) { continue; } startTime = DataRefUtils::getHeader(ref)->startTime; From 55997f8c036017f8387faeb05698fe94cfa167a7 Mon Sep 17 00:00:00 2001 From: benedikt-voelkel Date: Tue, 13 Feb 2024 11:29:51 +0100 Subject: [PATCH 32/50] Make hmp-matcher-workflow respect selected sources (#12691) --- Detectors/GlobalTrackingWorkflow/src/hmp-matcher-workflow.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/GlobalTrackingWorkflow/src/hmp-matcher-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/hmp-matcher-workflow.cxx index 2784b48161f80..2d748ae3cffb3 100644 --- a/Detectors/GlobalTrackingWorkflow/src/hmp-matcher-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/hmp-matcher-workflow.cxx @@ -94,7 +94,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) GID::mask_t alowedSources = GID::getSourcesMask("ITS-TPC,TPC-TRD,TPC-TOF,ITS-TPC-TRD,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF"); - GID::mask_t src = alowedSources; + GID::mask_t src = alowedSources & GID::getSourcesMask(configcontext.options().get("track-sources")); GID::mask_t mcmaskcl; GID::mask_t nonemask = GID::getSourcesMask(GID::NONE); From 511a4d3eb34964712c21dce06c55420f46defa61 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Tue, 13 Feb 2024 13:43:30 +0100 Subject: [PATCH 33/50] O2sim: DPL: restore mctracks-to-aod task name as topology adaptation relies on it --- run/o2sim_mctracks_to_aod.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run/o2sim_mctracks_to_aod.cxx b/run/o2sim_mctracks_to_aod.cxx index c63063a721d43..e2293338e8058 100644 --- a/run/o2sim_mctracks_to_aod.cxx +++ b/run/o2sim_mctracks_to_aod.cxx @@ -18,7 +18,7 @@ template using Configurable = o2::framework::Configurable; -struct Task { +struct MctracksToAod { /** @{ @name Types used */ using Collisions = o2::aod::McCollisions; @@ -142,7 +142,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { using o2::framework::adaptAnalysisTask; - auto spec = adaptAnalysisTask(cfgc); + auto spec = adaptAnalysisTask(cfgc); spec.inputs.emplace_back("mctracks", "MC", "MCTRACKS", 0., Lifetime::Timeframe); spec.inputs.emplace_back("mcheader", "MC", "MCHEADER", 0., From 5ed529c3cdb3dd4e08d12055273e65b2af2881e1 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Tue, 13 Feb 2024 15:02:04 +0100 Subject: [PATCH 34/50] GPU: Add prototype for SMatrixGPU testing (#12693) * Add HIPIFIED tests * Finalise inversion test --- .../MathUtils/include/MathUtils/SMatrixGPU.h | 8 +- GPU/Common/CMakeLists.txt | 20 ++- GPU/Common/test/.gitignore | 1 + GPU/Common/test/testSMatrixImp.cu | 131 ++++++++++++++++++ cmake/O2AddHipifiedExecutable.cmake | 5 +- cmake/O2AddTest.cmake | 22 ++- 6 files changed, 172 insertions(+), 15 deletions(-) create mode 100644 GPU/Common/test/.gitignore create mode 100644 GPU/Common/test/testSMatrixImp.cu diff --git a/Common/MathUtils/include/MathUtils/SMatrixGPU.h b/Common/MathUtils/include/MathUtils/SMatrixGPU.h index 2faaf118d1daa..d0820778550dd 100644 --- a/Common/MathUtils/include/MathUtils/SMatrixGPU.h +++ b/Common/MathUtils/include/MathUtils/SMatrixGPU.h @@ -140,7 +140,7 @@ template GPUd() SVectorGPU::SVectorGPU() { for (unsigned int i = 0; i < N; ++i) { - mArray[i] = 7; + mArray[i] = 0; } } @@ -1067,10 +1067,10 @@ GPUdi() void Inverter::InvertBunchKaufman(MatRepSymGPU& rhs, int& if } *mjj -= static_cast(temp2); } - } else //2x2 pivot, compute columns j and j-1 of the inverse + } else // 2x2 pivot, compute columns j and j-1 of the inverse { if (piv[j - 1] != 0) { - printf("error in piv %lf \n", piv[j - 1]); + printf("error in piv %lf \n", static_cast(piv[j - 1])); } s = 2; if (j < nrow) { @@ -1344,7 +1344,7 @@ GPUdi() int Inverter::DfinvMatrix(MatRepStdGPU& rhs, unsigned int for (unsigned int i = 1; i < n; i++) { unsigned int ni = n - i; mIter mij = mi; - //int j; + // int j; for (unsigned j = 1; j <= i; j++) { s33 = *mij; mIter mikj = mi + n + j - 1; diff --git a/GPU/Common/CMakeLists.txt b/GPU/Common/CMakeLists.txt index d22366b406a16..c37ec3f5f5a13 100644 --- a/GPU/Common/CMakeLists.txt +++ b/GPU/Common/CMakeLists.txt @@ -38,7 +38,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") target_compile_definitions(${targetName} PRIVATE GPUCA_O2_LIB GPUCA_TPC_GEOMETRY_O2 GPUCA_HAVE_O2HEADERS) - + # cuda test, only compile if CUDA if(CUDA_ENABLED) o2_add_test(GPUsortCUDA NAME test_GPUsortCUDA @@ -46,8 +46,24 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") PUBLIC_LINK_LIBRARIES O2::${MODULE} COMPONENT_NAME GPU LABELS gpu) + o2_add_test(SMatrixImpCUDA NAME test_SMatrixImpCUDA + SOURCES test/testSMatrixImp.cu + PUBLIC_LINK_LIBRARIES O2::${MODULE} + O2::MathUtils + ROOT::Core + COMPONENT_NAME GPU + LABELS gpu) + endif() + if (HIP_ENABLED) + o2_add_test(SMatrixImpHIP NAME test_SMatrixImpHIP + SOURCES test/testSMatrixImp.cu + HIPIFIED test + PUBLIC_LINK_LIBRARIES O2::${MODULE} + O2::MathUtils + ROOT::Core + COMPONENT_NAME GPU + LABELS gpu) endif() - install(FILES ${HDRS_INSTALL} DESTINATION include/GPU) endif() diff --git a/GPU/Common/test/.gitignore b/GPU/Common/test/.gitignore new file mode 100644 index 0000000000000..43fd5862f17c1 --- /dev/null +++ b/GPU/Common/test/.gitignore @@ -0,0 +1 @@ +*.hip \ No newline at end of file diff --git a/GPU/Common/test/testSMatrixImp.cu b/GPU/Common/test/testSMatrixImp.cu new file mode 100644 index 0000000000000..08ca0b823488d --- /dev/null +++ b/GPU/Common/test/testSMatrixImp.cu @@ -0,0 +1,131 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file testGPUSMatrixImp.cu +/// \author Matteo Concas + +#define BOOST_TEST_MODULE Test GPUSMatrixImpl +#ifdef __HIPCC__ +#define GPUPLATFORM "HIP" +#include "hip/hip_runtime.h" +#else +#define GPUPLATFORM "CUDA" +#include +#endif + +#include +#include + +#include +#include + +template +void discardResult(const T&) +{ +} + +void prologue() +{ + int deviceCount; + discardResult(cudaGetDeviceCount(&deviceCount)); + if (!deviceCount) { + std::cerr << "No " << GPUPLATFORM << " devices found" << std::endl; + } + for (int iDevice = 0; iDevice < deviceCount; ++iDevice) { + cudaDeviceProp deviceProp; + discardResult(cudaGetDeviceProperties(&deviceProp, iDevice)); + std::cout << GPUPLATFORM << " Device " << iDevice << ": " << deviceProp.name << std::endl; + } +} + +using MatSym3DGPU = o2::math_utils::SMatrixGPU>; +using MatSym3D = ROOT::Math::SMatrix>; + +template +__global__ void invertSymMatrixKernel(o2::math_utils::SMatrixGPU>* matrix) +{ + MatSym3DGPU smat2 = *matrix; + + printf("A(0,0) = %f, A(0,1) = %f, A(0,2) = %f\n", (*matrix)(0, 0), (*matrix)(0, 1), (*matrix)(0, 2)); + printf("A(1,0) = %f, A(1,1) = %f, A(1,2) = %f\n", (*matrix)(1, 0), (*matrix)(1, 1), (*matrix)(1, 2)); + printf("A(2,0) = %f, A(2,1) = %f, A(2,2) = %f\n", (*matrix)(2, 0), (*matrix)(2, 1), (*matrix)(2, 2)); + + printf("B(0,0) = %f, B(0,1) = %f, B(0,2) = %f\n", smat2(0, 0), smat2(0, 1), smat2(0, 2)); + printf("B(1,0) = %f, B(1,1) = %f, B(1,2) = %f\n", smat2(1, 0), smat2(1, 1), smat2(1, 2)); + printf("B(2,0) = %f, B(2,1) = %f, B(2,2) = %f\n", smat2(2, 0), smat2(2, 1), smat2(2, 2)); + + printf("\nInverting A...\n"); + matrix->Invert(); + + printf("A(0,0) = %f, A(0,1) = %f, A(0,2) = %f\n", (*matrix)(0, 0), (*matrix)(0, 1), (*matrix)(0, 2)); + printf("A(1,0) = %f, A(1,1) = %f, A(1,2) = %f\n", (*matrix)(1, 0), (*matrix)(1, 1), (*matrix)(1, 2)); + printf("A(2,0) = %f, A(2,1) = %f, A(2,2) = %f\n", (*matrix)(2, 0), (*matrix)(2, 1), (*matrix)(2, 2)); + + printf("\nC = (A^-1) * B...\n"); + auto smat3 = (*matrix) * smat2; + + printf("C(0,0) = %f, C(0,1) = %f, C(0,2) = %f\n", smat3(0, 0), smat3(0, 1), smat3(0, 2)); + printf("C(1,0) = %f, C(1,1) = %f, C(1,2) = %f\n", smat3(1, 0), smat3(1, 1), smat3(1, 2)); + printf("C(2,0) = %f, C(2,1) = %f, C(2,2) = %f\n", smat3(2, 0), smat3(2, 1), smat3(2, 2)); + + printf("\nEvaluating...\n"); + MatSym3DGPU tmp; + o2::math_utils::AssignSym::Evaluate(tmp, smat3); + + printf("A(0,0) = %f, A(0,1) = %f, A(0,2) = %f\n", tmp(0, 0), tmp(0, 1), tmp(0, 2)); + printf("A(1,0) = %f, A(1,1) = %f, A(1,2) = %f\n", tmp(1, 0), tmp(1, 1), tmp(1, 2)); + printf("A(2,0) = %f, A(2,1) = %f, A(2,2) = %f\n", tmp(2, 0), tmp(2, 1), tmp(2, 2)); + (*matrix) = tmp; +} + +struct GPUSMatrixImplFixture { + GPUSMatrixImplFixture() : SMatrix3D_d(nullptr) + { + prologue(); + + SMatrix3D_h(0, 0) = 1; + SMatrix3D_h(1, 1) = 2; + SMatrix3D_h(2, 2) = 3; + SMatrix3D_h(0, 1) = 4; + SMatrix3D_h(0, 2) = 5; + SMatrix3D_h(1, 2) = 6; + + discardResult(cudaMalloc(&SMatrix3D_d, sizeof(MatSym3DGPU))); + discardResult(cudaMemcpy(SMatrix3D_d, &SMatrix3D_h, sizeof(MatSym3DGPU), cudaMemcpyHostToDevice)); + + std::cout << "sizeof(MatSym3DGPU) = " << sizeof(MatSym3DGPU) << std::endl; + std::cout << "sizeof(MatSym3D) = " << sizeof(MatSym3D) << std::endl; + i = 3; + } + + ~GPUSMatrixImplFixture() + { + discardResult(cudaFree(SMatrix3D_d)); + } + + int i; + MatSym3DGPU* SMatrix3D_d; // device ptr + MatSym3D SMatrix3D_h; +}; + +BOOST_FIXTURE_TEST_CASE(DummyFixtureUsage, GPUSMatrixImplFixture) +{ + invertSymMatrixKernel<<<1, 1>>>(SMatrix3D_d); + discardResult(cudaDeviceSynchronize()); + + discardResult(cudaMemcpy(&SMatrix3D_h, SMatrix3D_d, sizeof(MatSym3DGPU), cudaMemcpyDeviceToHost)); + + MatSym3D identity; + identity(0, 0) = 1; + identity(1, 1) = 1; + identity(2, 2) = 1; + BOOST_TEST(SMatrix3D_h == identity); +} \ No newline at end of file diff --git a/cmake/O2AddHipifiedExecutable.cmake b/cmake/O2AddHipifiedExecutable.cmake index 6f25e3b061cf5..1152273b1256f 100644 --- a/cmake/O2AddHipifiedExecutable.cmake +++ b/cmake/O2AddHipifiedExecutable.cmake @@ -15,11 +15,12 @@ include(O2AddExecutable) function(o2_add_hipified_executable baseTargetName) # Parse arguments in the same way o2_add_executable does + # DEST_SRC_REL_PATH is the relative destination path for converted src files cmake_parse_arguments(PARSE_ARGV 1 A "IS_TEST;NO_INSTALL;IS_BENCHMARK" - "COMPONENT_NAME;TARGETVARNAME" + "COMPONENT_NAME;TARGETVARNAME;DEST_SRC_REL_PATH" "SOURCES;PUBLIC_LINK_LIBRARIES;JOB_POOL") # Process each .cu file to generate a .hip file @@ -32,7 +33,7 @@ function(o2_add_hipified_executable baseTargetName) set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${file}) get_filename_component(CUDA_SOURCE ${file} NAME) string(REPLACE ".cu" ".hip" HIP_SOURCE ${CUDA_SOURCE}) - set(OUTPUT_HIP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${HIP_SOURCE}") + set(OUTPUT_HIP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${A_DEST_SRC_REL_PATH}/${HIP_SOURCE}") list(APPEND HIP_SOURCES ${OUTPUT_HIP_FILE}) add_custom_command( diff --git a/cmake/O2AddTest.cmake b/cmake/O2AddTest.cmake index b42c67cfb0821..5687b01724106 100644 --- a/cmake/O2AddTest.cmake +++ b/cmake/O2AddTest.cmake @@ -72,7 +72,7 @@ function(o2_add_test) 1 A "INSTALL;NO_BOOST_TEST" - "COMPONENT_NAME;TIMEOUT;WORKING_DIRECTORY;NAME;TARGETVARNAME" + "COMPONENT_NAME;TIMEOUT;WORKING_DIRECTORY;NAME;TARGETVARNAME;HIPIFIED" "SOURCES;PUBLIC_LINK_LIBRARIES;COMMAND_LINE_ARGS;LABELS;CONFIGURATIONS;ENVIRONMENT" ) @@ -103,12 +103,20 @@ function(o2_add_test) endif() # create the executable - o2_add_executable(${testName} - SOURCES ${A_SOURCES} - PUBLIC_LINK_LIBRARIES ${linkLibraries} - COMPONENT_NAME ${A_COMPONENT_NAME} - IS_TEST ${noInstall} TARGETVARNAME targetName) - + if (NOT A_HIPIFIED) + o2_add_executable(${testName} + SOURCES ${A_SOURCES} + PUBLIC_LINK_LIBRARIES ${linkLibraries} + COMPONENT_NAME ${A_COMPONENT_NAME} + IS_TEST ${noInstall} TARGETVARNAME targetName) + else() + o2_add_hipified_executable(${testName} + SOURCES ${A_SOURCES} + DEST_SRC_REL_PATH ${A_HIPIFIED} + PUBLIC_LINK_LIBRARIES ${linkLibraries} + COMPONENT_NAME ${A_COMPONENT_NAME} + IS_TEST ${noInstall} TARGETVARNAME targetName) + endif() if(A_TARGETVARNAME) set(${A_TARGETVARNAME} ${targetName} PARENT_SCOPE) From 0a5ace519a972b3c9341087f9ea0f01182ab8992 Mon Sep 17 00:00:00 2001 From: Timo Wilken Date: Tue, 13 Feb 2024 15:44:16 +0000 Subject: [PATCH 35/50] Add workflow to reset "Security: approval needed" status on approval (#12702) --- .github/workflows/pr-security-approval.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/pr-security-approval.yml diff --git a/.github/workflows/pr-security-approval.yml b/.github/workflows/pr-security-approval.yml new file mode 100644 index 0000000000000..9ae70fdb9933d --- /dev/null +++ b/.github/workflows/pr-security-approval.yml @@ -0,0 +1,18 @@ +--- +name: Security approval + +'on': + pull_request_review: + types: + - edited + - submitted + +permissions: {} + +jobs: + clean: + name: Security approval + uses: alisw/ali-bot/.github/workflows/pr-security-approval.yml@master + permissions: + pull-requests: read # to get last commit for PR + statuses: write # for set-github-status From aff59d1b35a7d6a63550bc6b248ad714f7c1aa32 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:42:07 +0100 Subject: [PATCH 36/50] DPL: fix lossy sending / forwarding policies --- Framework/Core/src/SendingPolicy.cxx | 53 ++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/Framework/Core/src/SendingPolicy.cxx b/Framework/Core/src/SendingPolicy.cxx index 3aeccb680c150..52123378e1e46 100644 --- a/Framework/Core/src/SendingPolicy.cxx +++ b/Framework/Core/src/SendingPolicy.cxx @@ -56,13 +56,16 @@ std::vector SendingPolicy::createDefaultPolicies() // non-blocking approach. int64_t timeout = 10; if (state.droppedMessages == 10 + 1) { - LOG(warning) << "Failed to send 10 messages with 10ms timeout in a row, switching to completely non-blocking mode"; + LOG(warning) << "Failed to send 10 messages with 10ms timeout in a row, switching to completely non-blocking mode."; + } + if (state.droppedMessages == 0) { + timeout = 10; } if (state.droppedMessages > 10) { timeout = 0; } - size_t result = info.channel.Send(parts, timeout); - if (result > 0) { + int64_t result = info.channel.Send(parts, timeout); + if (result >= 0) { state.droppedMessages = 0; } else if (state.droppedMessages < std::numeric_limits::max()) { state.droppedMessages++; @@ -97,10 +100,10 @@ std::vector SendingPolicy::createDefaultPolicies() LOGP(info, "Sent {} parts for a total of {} bytes", parts.Size(), count); auto res = channel->Send(parts, timeout); if (res == (size_t)fair::mq::TransferCode::timeout) { - LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on {}.", timeout/1000, channel->GetName()); + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on {}.", timeout / 1000, channel->GetName()); channel->Send(parts); LOGP(info, "Downstream backpressure on {} recovered.", channel->GetName()); - } else if (res == (size_t) fair::mq::TransferCode::error) { + } else if (res == (size_t)fair::mq::TransferCode::error) { LOGP(fatal, "Error while sending on channel {}", channel->GetName()); } }}, SendingPolicy{ @@ -113,12 +116,22 @@ std::vector SendingPolicy::createDefaultPolicies() .send = [](fair::mq::Parts& parts, ChannelIndex channelIndex, ServiceRegistryRef registry) { auto &proxy = registry.get(); auto *channel = proxy.getOutputChannel(channelIndex); + OutputChannelState& state = proxy.getOutputChannelState(channelIndex); auto timeout = 1000; - auto res = channel->Send(parts, timeout); - if (res == (size_t)fair::mq::TransferCode::timeout) { - LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on expendable channel {}.", timeout/1000, channel->GetName()); - } else if (res == (size_t) fair::mq::TransferCode::error) { - LOGP(info, "Error while sending on channel {}", channel->GetName()); + if (state.droppedMessages > 0) { + timeout = 0; + } + if (state.droppedMessages == 1) { + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on expendable channel {}. Switching to dropping mode.", timeout / 1000, channel->GetName()); + } + if (state.droppedMessages == 0) { + timeout = 1000; + } + int64_t res = channel->Send(parts, timeout); + if (res >= 0) { + state.droppedMessages = 0; + } else { + state.droppedMessages++; } }}, SendingPolicy{ .name = "default", @@ -204,12 +217,22 @@ std::vector ForwardingPolicy::createDefaultPolicies() .forward = [](fair::mq::Parts& parts, ChannelIndex channelIndex, ServiceRegistryRef registry) { auto &proxy = registry.get(); auto *channel = proxy.getForwardChannel(channelIndex); + OutputChannelState& state = proxy.getOutputChannelState(channelIndex); auto timeout = 1000; - auto res = channel->Send(parts, timeout); - if (res == (size_t)fair::mq::TransferCode::timeout) { - LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on expendable channel {}.", timeout/1000, channel->GetName()); - } else if (res == (size_t) fair::mq::TransferCode::error) { - LOGP(info, "Error while sending on channel {}", channel->GetName()); + if (state.droppedMessages > 0) { + timeout = 0; + } + if (state.droppedMessages == 1) { + LOGP(warning, "Timed out sending after {}s. Downstream backpressure detected on expendable channel {}. Switching to dropping mode.", timeout / 1000, channel->GetName()); + } + if (state.droppedMessages == 0) { + timeout = 1000; + } + int64_t res = channel->Send(parts, timeout); + if (res >= 0) { + state.droppedMessages = 0; + } else { + state.droppedMessages++; } }}, createDefaultForwardingPolicy()}; } From df6af0fa8960a46a124683cfc0ed7eed0e756003 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:42:07 +0100 Subject: [PATCH 37/50] DPL: drop reference to the now obsolete non-critical label --- Framework/Core/src/SendingPolicy.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/SendingPolicy.cxx b/Framework/Core/src/SendingPolicy.cxx index 52123378e1e46..3dbbc451915b0 100644 --- a/Framework/Core/src/SendingPolicy.cxx +++ b/Framework/Core/src/SendingPolicy.cxx @@ -39,9 +39,9 @@ std::vector SendingPolicy::createDefaultPolicies() return true; } } - // Check if any of the destination's labels is "expendable" or "non-critical" + // Check if any of the destination's labels is "expendable" for (auto const& label : dest.labels) { - if (label.value == "expendable" || label.value == "non-critical") { + if (label.value == "expendable") { return true; } } From d1e6ce2fdf889ba4940c45415becf9de12ccf7f9 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Tue, 13 Feb 2024 23:24:15 +0100 Subject: [PATCH 38/50] its-study: add anomaly detection study (#12697) * Skeleton of cluster anomaly study * Add cluster sizes * Add configKeyParam + other fixes * Add ROF base histograms * Add ROF-based * Improve binning and configurability * Add sliced uniform fit along phi * Add Chi2 test on phi uniformity --------- Co-authored-by: fmazzasc --- .../ITS/postprocessing/studies/CMakeLists.txt | 1 + .../studies/include/ITSStudies/AnomalyStudy.h | 29 ++ .../ITSStudies/ITSStudiesConfigParam.h | 12 + .../studies/src/AnomalyStudy.cxx | 288 ++++++++++++++++++ .../studies/src/ITSStudiesConfigParam.cxx | 2 + .../studies/src/ITSStudiesLinkDef.h | 2 + .../standalone-postprocessing-workflow.cxx | 48 ++- 7 files changed, 371 insertions(+), 11 deletions(-) create mode 100644 Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/AnomalyStudy.h create mode 100644 Detectors/ITSMFT/ITS/postprocessing/studies/src/AnomalyStudy.cxx diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/CMakeLists.txt b/Detectors/ITSMFT/ITS/postprocessing/studies/CMakeLists.txt index 6cc53dfa6ea90..fd9074d5b6b6a 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/CMakeLists.txt @@ -14,6 +14,7 @@ o2_add_library(ITSPostprocessing src/AvgClusSize.cxx src/PIDStudy.cxx src/ITSStudiesConfigParam.cxx + src/AnomalyStudy.cxx src/TrackCheck.cxx src/Helpers.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/AnomalyStudy.h b/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/AnomalyStudy.h new file mode 100644 index 0000000000000..946b5ef08fd48 --- /dev/null +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/AnomalyStudy.h @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_ANOMALY_STUDY_H +#define O2_ANOMALY_STUDY_H + +#include "Framework/DataProcessorSpec.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" + +namespace o2::its +{ +namespace study +{ + +using mask_t = o2::dataformats::GlobalTrackID::mask_t; + +o2::framework::DataProcessorSpec getAnomalyStudy(mask_t srcClustersMask, bool useMC); +} // namespace study +} // namespace o2::its + +#endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/ITSStudiesConfigParam.h b/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/ITSStudiesConfigParam.h index 0f8d416bfeb09..5884a0cadd815 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/ITSStudiesConfigParam.h +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/include/ITSStudies/ITSStudiesConfigParam.h @@ -82,6 +82,18 @@ struct PIDStudyParamConfig : public o2::conf::ConfigurableParamHelper { + std::string outFileName = "its_AnomalyStudy.root"; + size_t nLayersToProcess = 3; + size_t nTimeFramesOffset = 500; + size_t nRofTimeFrames = 192; + float nPhiBinsMultiplier = 1.f; + float pValueCut = 0.05; + bool doROFAnalysis = false; + + O2ParamDef(AnomalyStudyParamConfig, "AnomalyStudyParam"); +}; + struct ITSImpactParameterParamConfig : public o2::conf::ConfigurableParamHelper { std::string outFileName = "its_ImpParameter.root"; int minNumberOfContributors = 0; diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/AnomalyStudy.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/AnomalyStudy.cxx new file mode 100644 index 0000000000000..c56c2bff2e0d2 --- /dev/null +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/AnomalyStudy.cxx @@ -0,0 +1,288 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "ITSStudies/AnomalyStudy.h" +#include "ITSStudies/ITSStudiesConfigParam.h" +#include "ITSBase/GeometryTGeo.h" + +#include "Framework/Task.h" +#include "ITStracking/IOUtils.h" +#include "ITSMFTReconstruction/ChipMappingITS.h" +#include "DetectorsBase/GRPGeomHelper.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsGlobalTracking/RecoContainer.h" + +#include +#include +#include +#include + +namespace o2::its::study +{ +using namespace o2::framework; +using namespace o2::globaltracking; +using GTrackID = o2::dataformats::GlobalTrackID; +using ITSCluster = o2::BaseCluster; +class AnomalyStudy : public Task +{ + static constexpr int nChipStavesIB{9}; + + public: + AnomalyStudy(std::shared_ptr dr, + std::shared_ptr gr, + bool isMC) : mDataRequest{dr}, mGGCCDBRequest(gr), mUseMC(isMC) {} + void init(InitContext& ic) final; + void run(ProcessingContext&) final; + void endOfStream(EndOfStreamContext&) final; + void finaliseCCDB(ConcreteDataMatcher&, void*) final; + + // custom + void prepareOutput(); + void updateTimeDependentParams(ProcessingContext& pc); + void process(o2::globaltracking::RecoContainer& recoData); + void setClusterDictionary(const o2::itsmft::TopologyDictionary* d) { mDict = d; } + + private: + bool mUseMC; + int mTFCount{0}; + TStopwatch mStopwatch; + const int mNumberOfStaves[7] = {12, 16, 20, 24, 30, 42, 48}; + std::shared_ptr mGGCCDBRequest; + std::shared_ptr mDataRequest; + const o2::itsmft::TopologyDictionary* mDict = nullptr; + + // utils + void getClusterPatterns(gsl::span&, gsl::span&, const o2::itsmft::TopologyDictionary&); + std::vector mPatterns; + o2::its::GeometryTGeo* mGeom; + o2::itsmft::ChipMappingITS mChipMapping; + + // Histos + std::vector> mTFvsPhiHist; + std::vector> mTFvsPhiClusSizeHist; + std::vector> mROFvsPhiHist; + std::vector> mROFvsPhiClusSizeHist; +}; + +void AnomalyStudy::updateTimeDependentParams(ProcessingContext& pc) +{ + o2::base::GRPGeomHelper::instance().checkUpdates(pc); + static bool initOnceDone = false; + if (!initOnceDone) { // this param need to be queried only once + initOnceDone = true; + mGeom = o2::its::GeometryTGeo::Instance(); + mGeom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); + } +} + +void AnomalyStudy::init(InitContext& ic) +{ + o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); + prepareOutput(); + + auto nLayProc = o2::its::study::AnomalyStudyParamConfig::Instance().nLayersToProcess; + auto nTF = o2::its::study::AnomalyStudyParamConfig::Instance().nTimeFramesOffset; + auto nROF = o2::its::study::AnomalyStudyParamConfig::Instance().nRofTimeFrames; + auto doROFAnalysis = o2::its::study::AnomalyStudyParamConfig::Instance().doROFAnalysis; + + mTFvsPhiHist.resize(nLayProc); + mTFvsPhiClusSizeHist.resize(nLayProc); + if (doROFAnalysis) { + mROFvsPhiHist.resize(nLayProc); + mROFvsPhiClusSizeHist.resize(nLayProc); + } + for (unsigned int i = 0; i < nLayProc; i++) { + int phiBins = o2::its::study::AnomalyStudyParamConfig::Instance().nPhiBinsMultiplier * mNumberOfStaves[i]; + mTFvsPhiHist[i].reset(new TH2F(Form("tf_phi_occup_layer_%d", i), Form("Occupancy layer %d ; #phi ; # TF; Counts", i), phiBins, -TMath::Pi(), TMath::Pi(), nTF, 0.5, nTF + 0.5)); + mTFvsPhiClusSizeHist[i].reset(new TH2F(Form("tf_phi_clsize_layer_%d", i), Form("Cluster size layer %d ; #phi; # TF ; #lt Cluster Size #gt", i), phiBins, -TMath::Pi(), TMath::Pi(), nTF, 0.5, nTF + 0.5)); + if (doROFAnalysis) { + mROFvsPhiHist[i].reset(new TH2F(Form("rof_phi_occup_layer_%d", i), Form("Occupancy layer %d ; #phi; # ROF; Counts", i), phiBins, -TMath::Pi(), TMath::Pi(), nROF * nTF, 0.5, nROF * nTF + 0.5)); + mROFvsPhiClusSizeHist[i].reset(new TH2F(Form("rof_phi_clsize_layer_%d", i), Form("Cluster size layer %d; #phi; # ROF; #lt Cluster Size #gt", i), phiBins, -TMath::Pi(), TMath::Pi(), nROF * nTF, 0.5, nROF * nTF + 0.5)); + } + } +} + +void AnomalyStudy::run(ProcessingContext& pc) +{ + o2::globaltracking::RecoContainer recoData; + recoData.collectData(pc, *mDataRequest.get()); + updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions + process(recoData); +} + +void AnomalyStudy::endOfStream(EndOfStreamContext&) +{ + TFile* f = TFile::Open(o2::its::study::AnomalyStudyParamConfig::Instance().outFileName.c_str(), "recreate"); + auto nLayProc = o2::its::study::AnomalyStudyParamConfig::Instance().nLayersToProcess; + auto doROFAnalysis = o2::its::study::AnomalyStudyParamConfig::Instance().doROFAnalysis; + + // Iterate over all the histograms and compute the averages + for (unsigned int i = 0; i < nLayProc; i++) { + mTFvsPhiClusSizeHist[i]->Divide(mTFvsPhiHist[i].get()); + if (doROFAnalysis) { + mROFvsPhiClusSizeHist[i]->Divide(mROFvsPhiHist[i].get()); + } + } + + // Fit slices along x of the 2D histograms + for (unsigned int iLayer = 0; iLayer < nLayProc; ++iLayer) { + int phiBins = o2::its::study::AnomalyStudyParamConfig::Instance().nPhiBinsMultiplier * mNumberOfStaves[iLayer]; + TObjArray aSlices; + auto* f1 = new TF1(Form("f1_%d", iLayer), "pol0", -TMath::Pi(), TMath::Pi()); + auto* hPValue = new TH1F(Form("pValue_%d", iLayer), Form("pValue_%d", iLayer), mTFvsPhiClusSizeHist[iLayer]->GetNbinsY(), 0.5, mTFvsPhiClusSizeHist[iLayer]->GetNbinsY() + 0.5); + mTFvsPhiClusSizeHist[iLayer]->FitSlicesX(f1, 0, -1, 0, "QNR", &aSlices); + auto* hChi2 = (TH1D*)aSlices.At(1); + for (auto iTF{0}; iTF < hChi2->GetEntries(); ++iTF) { + auto pValue = TMath::Prob(hChi2->GetBinContent(iTF + 1) * (phiBins - 1), phiBins - 1); + // LOGP(info, "Layer: {} TF: {} Chi2: {} Pvalue: {}", iLayer, iTF, hChi2->GetBinContent(iTF + 1), pValue); + hPValue->SetBinContent(iTF + 1, pValue); + } + hPValue->Write(); + // Save slices to file + for (unsigned int j = 0; j < aSlices.GetEntries(); ++j) { + auto h = (TH1D*)aSlices.At(j); + h->SetMinimum(0); + h->Write(); + } + + // Do the same for ROFs + if (doROFAnalysis) { + TObjArray aSlicesROF; + auto f1ROF = new TF1(Form("f1ROF_%d", iLayer), "pol0", -TMath::Pi(), TMath::Pi()); + mROFvsPhiClusSizeHist[iLayer]->FitSlicesX(f1ROF, 0, -1, 0, "QNR", &aSlicesROF); + // Save slices to file + for (unsigned int j = 0; j < aSlicesROF.GetEntries(); ++j) { + auto h = (TH1D*)aSlicesROF.At(j); + h->SetMinimum(0); + h->Write(); + } + } + } + + for (unsigned int i = 0; i < nLayProc; i++) { + mTFvsPhiHist[i]->Write(); + mTFvsPhiClusSizeHist[i]->Write(); + if (doROFAnalysis) { + mROFvsPhiHist[i]->Write(); + mROFvsPhiClusSizeHist[i]->Write(); + } + } + f->Close(); +} + +void AnomalyStudy::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) +{ + if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { + return; + } + if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) { + setClusterDictionary((const o2::itsmft::TopologyDictionary*)obj); + return; + } +} + +// custom +void AnomalyStudy::process(o2::globaltracking::RecoContainer& recoData) +{ + mStopwatch.Start(); + mTFCount++; + auto nROF = o2::its::study::AnomalyStudyParamConfig::Instance().nRofTimeFrames; + auto nLayProc = o2::its::study::AnomalyStudyParamConfig::Instance().nLayersToProcess; + auto doROFAnalysis = o2::its::study::AnomalyStudyParamConfig::Instance().doROFAnalysis; + int rofCount = 0; + auto clusRofRecords = recoData.getITSClustersROFRecords(); + auto compClus = recoData.getITSClusters(); + auto clusPatt = recoData.getITSClustersPatterns(); + + getClusterPatterns(compClus, clusPatt, *mDict); + + auto pattIt = clusPatt.begin(); + std::vector globalClusters; + o2::its::ioutils::convertCompactClusters(compClus, pattIt, globalClusters, mDict); + + int lay, sta, ssta, mod, chipInMod; + for (auto& rofRecord : clusRofRecords) { + auto clustersInRof = rofRecord.getROFData(compClus); + auto patternsInRof = rofRecord.getROFData(mPatterns); + auto locClustersInRof = rofRecord.getROFData(globalClusters); + for (unsigned int clusInd{0}; clusInd < clustersInRof.size(); clusInd++) { + const auto& compClus = clustersInRof[clusInd]; + auto& locClus = locClustersInRof[clusInd]; + auto& clusPattern = patternsInRof[clusInd]; + auto gloC = locClus.getXYZGlo(*mGeom); + mChipMapping.expandChipInfoHW(compClus.getChipID(), lay, sta, ssta, mod, chipInMod); + if (lay >= nLayProc) { + continue; + } + float phi = TMath::ATan2(gloC.Y(), gloC.X()); + mTFvsPhiHist[lay]->Fill(phi, mTFCount); + mTFvsPhiClusSizeHist[lay]->Fill(phi, mTFCount, clusPattern.getNPixels()); + if (doROFAnalysis) { + mROFvsPhiHist[lay]->Fill(phi, (mTFCount - 1) * nROF + rofCount); + mROFvsPhiClusSizeHist[lay]->Fill(phi, (mTFCount - 1) * nROF + rofCount, clusPattern.getNPixels()); + } + } + ++rofCount; + } + mStopwatch.Stop(); + LOGP(info, "Processed TF: {} in {} s", mTFCount, mStopwatch.RealTime()); +} + +void AnomalyStudy::prepareOutput() +{ +} + +void AnomalyStudy::getClusterPatterns(gsl::span& ITSclus, gsl::span& ITSpatt, const o2::itsmft::TopologyDictionary& mdict) +{ + mPatterns.clear(); + mPatterns.reserve(ITSclus.size()); + auto pattIt = ITSpatt.begin(); + + for (unsigned int iClus{0}; iClus < ITSclus.size(); ++iClus) { + auto& clus = ITSclus[iClus]; + + auto pattID = clus.getPatternID(); + o2::itsmft::ClusterPattern patt; + + if (pattID == o2::itsmft::CompCluster::InvalidPatternID || mdict.isGroup(pattID)) { + patt.acquirePattern(pattIt); + } else { + patt = mdict.getPattern(pattID); + } + + mPatterns.push_back(patt); + } +} + +// getter +DataProcessorSpec getAnomalyStudy(mask_t srcClustersMask, bool useMC) +{ + std::vector outputs; + auto dataRequest = std::make_shared(); + dataRequest->requestClusters(srcClustersMask, useMC); + dataRequest->requestTracks(GTrackID::getSourcesMask(""), useMC); + + auto ggRequest = std::make_shared(false, // orbitResetTime + true, // GRPECS=true + false, // GRPLHCIF + false, // GRPMagField + false, // askMatLUT + o2::base::GRPGeomRequest::Aligned, // geometry + dataRequest->inputs, + true); + return DataProcessorSpec{ + "its-anomaly-study", + dataRequest->inputs, + outputs, + AlgorithmSpec{adaptFromTask(dataRequest, ggRequest, useMC)}, + Options{}}; +} +} // namespace o2::its::study \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesConfigParam.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesConfigParam.cxx index 1ece01a94e456..3f9ea07bf1f51 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesConfigParam.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesConfigParam.cxx @@ -21,11 +21,13 @@ static auto& sAvgClusSizeParamITS = o2::its::study::ITSAvgClusSizeParamConfig::I static auto& sPIDStudyParamITS = o2::its::study::PIDStudyParamConfig::Instance(); static auto& sCheckTracksParamsITS = o2::its::study::ITSCheckTracksParamConfig::Instance(); static auto& sImpactParameterParamsITS = o2::its::study::ITSImpactParameterParamConfig::Instance(); +static auto& sAnomalyStudy = o2::its::study::AnomalyStudyParamConfig::Instance(); O2ParamImpl(o2::its::study::ITSAvgClusSizeParamConfig); O2ParamImpl(o2::its::study::PIDStudyParamConfig); O2ParamImpl(o2::its::study::ITSCheckTracksParamConfig); O2ParamImpl(o2::its::study::ITSImpactParameterParamConfig); +O2ParamImpl(o2::its::study::AnomalyStudyParamConfig); } // namespace study } // namespace its diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesLinkDef.h b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesLinkDef.h index 182bdc9e6c851..2ceae2ea981f6 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesLinkDef.h +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ITSStudiesLinkDef.h @@ -18,10 +18,12 @@ #pragma link C++ class o2::its::study::ITSAvgClusSizeParamConfig + ; #pragma link C++ class o2::its::study::PIDStudyParamConfig + ; #pragma link C++ class o2::its::study::ITSImpactParameterParamConfig + ; +#pragma link C++ class o2::its::study::AnomalyStudyParamConfig + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::its::study::ITSAvgClusSizeParamConfig> + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::its::study::PIDStudyParamConfig> + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::its::study::ITSCheckTracksParamConfig> + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::its::study::ITSImpactParameterParamConfig> + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::its::study::AnomalyStudyParamConfig> + ; #pragma link C++ function o2::its::studies::makeLogBinning + ; #endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx b/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx index d7416f8415bcf..5a6975df35472 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/workflow/standalone-postprocessing-workflow.cxx @@ -21,6 +21,7 @@ #include "ITSStudies/ImpactParameter.h" #include "ITSStudies/AvgClusSize.h" #include "ITSStudies/PIDStudy.h" +#include "ITSStudies/AnomalyStudy.h" #include "ITSStudies/TrackCheck.h" #include "Steer/MCKinematicsReader.h" @@ -38,6 +39,7 @@ void customize(std::vector& workflowOptions) { // option allowing to set parameters std::vector options{ + {"input-from-upstream", VariantType::Bool, false, {"read clusters from the clusterer"}}, {"track-sources", VariantType::String, std::string{"ITS,ITS-TPC-TRD-TOF,ITS-TPC-TOF,ITS-TPC,ITS-TPC-TRD"}, {"comma-separated list of track sources to use"}}, {"cluster-sources", VariantType::String, std::string{"ITS"}, {"comma-separated list of cluster sources to use"}}, {"disable-root-input", VariantType::Bool, false, {"disable root-files input reader"}}, @@ -46,6 +48,7 @@ void customize(std::vector& workflowOptions) {"pid-study", VariantType::Bool, false, {"Perform the PID study"}}, {"track-study", VariantType::Bool, false, {"Perform the track study"}}, {"impact-parameter-study", VariantType::Bool, false, {"Perform the impact parameter study"}}, + {"anomaly-study", VariantType::Bool, false, {"Perform the anomaly study"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; o2::raw::HBFUtilsInitializer::addConfigOption(options, "o2_tfidinfo.root"); std::swap(workflowOptions, options); @@ -56,42 +59,65 @@ void customize(std::vector& workflowOptions) WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { WorkflowSpec specs; - GID::mask_t allowedSourcesTrc = GID::getSourcesMask("ITS,TPC,ITS-TPC-TRD-TOF,ITS-TPC-TOF,ITS-TPC,ITS-TPC-TRD"); - GID::mask_t allowedSourcesClus = GID::getSourcesMask("ITS"); + GID::mask_t srcTrc, srcCls; - // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); auto useMC = !configcontext.options().get("disable-mc"); - GID::mask_t srcTrc = allowedSourcesTrc & GID::getSourcesMask(configcontext.options().get("track-sources")); - srcTrc |= GID::getSourcesMask("ITS"); // guarantee that we will at least use ITS tracks - GID::mask_t srcCls = allowedSourcesClus & GID::getSourcesMask(configcontext.options().get("cluster-sources")); - - o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC, srcCls, srcTrc); - // o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); - // o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); std::shared_ptr mcKinematicsReader; if (useMC) { mcKinematicsReader = std::make_shared("collisioncontext.root"); } - bool anyStudy{false}; // Declare specs related to studies hereafter if (configcontext.options().get("impact-parameter-study")) { anyStudy = true; + srcTrc = GID::getSourcesMask(configcontext.options().get("track-sources")); + srcCls = GID::getSourcesMask(configcontext.options().get("cluster-sources")); + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC, srcCls, srcTrc); + // o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); + // o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); specs.emplace_back(o2::its::study::getImpactParameterStudy(srcTrc, srcCls, useMC)); } if (configcontext.options().get("cluster-size-study")) { anyStudy = true; + srcTrc = GID::getSourcesMask(configcontext.options().get("track-sources")); + srcCls = GID::getSourcesMask(configcontext.options().get("cluster-sources")); + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC, srcCls, srcTrc); + // o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); + // o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); specs.emplace_back(o2::its::study::getAvgClusSizeStudy(srcTrc, srcCls, useMC, mcKinematicsReader)); } if (configcontext.options().get("pid-study")) { anyStudy = true; + srcTrc = GID::getSourcesMask(configcontext.options().get("track-sources")); + srcCls = GID::getSourcesMask(configcontext.options().get("cluster-sources")); + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC, srcCls, srcTrc); + // o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); + // o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); specs.emplace_back(o2::its::study::getPIDStudy(srcTrc, srcCls, useMC, mcKinematicsReader)); } if (configcontext.options().get("track-study")) { anyStudy = true; + srcTrc = GID::getSourcesMask(configcontext.options().get("track-sources")); + srcCls = GID::getSourcesMask(configcontext.options().get("cluster-sources")); + if (!configcontext.options().get("input-from-upstream")) { + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC, srcCls, srcTrc); + } specs.emplace_back(o2::its::study::getTrackCheckStudy(GID::getSourcesMask("ITS"), GID::getSourcesMask("ITS"), useMC, mcKinematicsReader)); + // o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); + // o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); + } + if (configcontext.options().get("anomaly-study")) { + anyStudy = true; + // srcTrc = GID::getSourcesMask(configcontext.options().get("track-sources")); + srcCls = GID::getSourcesMask(configcontext.options().get("cluster-sources")); + if (!configcontext.options().get("input-from-upstream")) { + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC, srcCls, srcTrc); + } + // o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); + // o2::globaltracking::InputHelper::addInputSpecsSVertex(configcontext, specs); + specs.emplace_back(o2::its::study::getAnomalyStudy(srcCls, useMC)); } if (!anyStudy) { LOGP(info, "No study selected, dryrunning"); From 2e1c90520508905195fea0bbf25b76d7801c805c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 14 Feb 2024 08:50:56 +0100 Subject: [PATCH 39/50] DPL: make sure homogeneous_apply_ref complains when we are missing an explicit constructor --- Framework/Foundation/include/Framework/StructToTuple.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Framework/Foundation/include/Framework/StructToTuple.h b/Framework/Foundation/include/Framework/StructToTuple.h index d94c0e3aaae03..6d9a6a2ef305a 100644 --- a/Framework/Foundation/include/Framework/StructToTuple.h +++ b/Framework/Foundation/include/Framework/StructToTuple.h @@ -135,10 +135,12 @@ struct UniversalType { template consteval auto brace_constructible_size(auto... Members) { - if constexpr (requires { T{Members...}; } == false) + if constexpr (requires { T{Members...}; } == false) { + static_assert(sizeof...(Members) != 0, "You need to make sure that you have implicit constructors or that you call the explicit constructor correctly."); return sizeof...(Members) - 1; - else + } else { return brace_constructible_size(Members..., UniversalType{}); + } } #else template From 17048584b01ec22edfd06dd44ed2850fd9dc986d Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Tue, 13 Feb 2024 14:47:50 +0100 Subject: [PATCH 40/50] DPL: Pass the concept of expendable tasks in DPL to templates for ECS --- Framework/Core/src/O2ControlHelpers.cxx | 9 +++++++++ .../Core/test/test_FrameworkDataFlowToO2Control.cxx | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/O2ControlHelpers.cxx b/Framework/Core/src/O2ControlHelpers.cxx index 7618a34cdeb4d..88132572a6210 100644 --- a/Framework/Core/src/O2ControlHelpers.cxx +++ b/Framework/Core/src/O2ControlHelpers.cxx @@ -211,6 +211,14 @@ bool isQcReconfigurable(const DeviceSpec& spec) return std::find(spec.labels.begin(), spec.labels.end(), ecs::qcReconfigurable) != spec.labels.end(); } +bool isCritical(const DeviceSpec& spec) +{ + // DPL's expendable Data Processor corresponds to a non-critical task in ECS + // DPL's resilient Data Processor corresponds to a critical task in ECS + // All tasks are considered critical by default in ECS + return std::find(spec.labels.begin(), spec.labels.end(), DataProcessorLabel{"expendable"}) == spec.labels.end(); +} + void dumpProperties(std::ostream& dumpOut, const DeviceExecution& execution, const DeviceSpec& spec, const std::string& indLevel) { // get the argument `--config` @@ -358,6 +366,7 @@ void dumpRole(std::ostream& dumpOut, const std::string& taskName, const DeviceSp dumpOut << indLevel << indScheme << "task:\n"; dumpOut << indLevel << indScheme << indScheme << "load: " << taskName << "\n"; + dumpOut << indLevel << indScheme << indScheme << "critical: " << (isCritical(spec) ? "true" : "false") << "\n"; } std::string removeO2ControlArg(std::string_view command) diff --git a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx index d15eebd26bdf7..f3a69e44339a4 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx @@ -42,6 +42,7 @@ WorkflowSpec defineDataProcessing() .metadata = {{ecs::cpuKillThreshold, "3.0"}}}, {.name = "C", // first consumer of A1, consumer of B1 .inputs = {InputSpec{"y", "TST", "A1"}, InputSpec{"y", "TST", "B1"}}, + .labels = {{"expendable"}}, .metadata = {{ecs::privateMemoryKillThresholdMB, "5000"}}}, {.name = "D", // second consumer of A1 .inputs = Inputs{InputSpec{"x", "TST", "A1"}}, @@ -50,7 +51,8 @@ WorkflowSpec defineDataProcessing() ConfigParamSpec{"c-param", VariantType::String, "foo;bar", {"another parameter which will be escaped"}}, ConfigParamSpec{"channel-config", VariantType::String, // raw output channel "name=outta_dpl,type=push,method=bind,address=ipc:///tmp/pipe-outta-dpl,transport=shmem,rateLogging=10", - {"Out-of-band channel config"}}}}}; + {"Out-of-band channel config"}}}, + .labels = {{"resilient"}}}}; } char* strdiffchr(const char* s1, const char* s2) @@ -86,10 +88,12 @@ const auto expectedWorkflow = R"EXPECTED(name: testwf rcvBufSize: 789 task: load: testwf-A + critical: true - name: "B" connect: task: load: testwf-B + critical: true - name: "C" connect: - name: from_A_to_C @@ -108,6 +112,7 @@ const auto expectedWorkflow = R"EXPECTED(name: testwf rcvBufSize: 1 task: load: testwf-C + critical: false - name: "D" connect: - name: from_C_to_D @@ -126,6 +131,7 @@ const auto expectedWorkflow = R"EXPECTED(name: testwf global: "outta_dpl-{{ it }}" task: load: testwf-D + critical: true )EXPECTED"; const std::vector expectedTasks{ From 05d2989d594f7c2695174491d62ceaf587bdf9c3 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Thu, 15 Feb 2024 11:08:36 +0000 Subject: [PATCH 41/50] ctpdev: scalers orbit shift (#12706) * fix: cleaning * clang --- DataFormats/Detectors/CTP/src/Scalers.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/DataFormats/Detectors/CTP/src/Scalers.cxx b/DataFormats/Detectors/CTP/src/Scalers.cxx index 6ba75929fdedd..f5e218745b386 100644 --- a/DataFormats/Detectors/CTP/src/Scalers.cxx +++ b/DataFormats/Detectors/CTP/src/Scalers.cxx @@ -780,19 +780,20 @@ std::pair CTPRunScalers::getRateGivenT(double timestamp, int cla // int CTPRunScalers::addOrbitOffset(uint32_t offset) { + int over = 0; LOG(info) << "Subtracting from orbit " << offset; for (auto& screc : mScalerRecordRaw) { uint32_t orbit = screc.intRecord.orbit; uint32_t orbitnew = 0; - if (orbit >= offset) { - orbitnew = orbit - offset; - } else { - orbitnew = 0xffffffff - offset; - orbitnew = orbit + 1 + orbitnew; - LOG(error) << "Orbit overflow - should never happen. Run:" << mRunNumber; + orbitnew = orbit - offset; + if (orbit < offset) { + over++; } screc.intRecord.orbit = orbitnew; } + if (over != 0 && over != mScalerRecordRaw.size()) { + LOG(warning) << "Orbit overflow inside run. Run:" << mRunNumber; + } return 0; } std::vector CTPRunScalers::scalerNames = From 144a9aa1f5ee02ae39476d6150fb3b4a7c9bce06 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Thu, 15 Feb 2024 13:22:30 +0100 Subject: [PATCH 42/50] ALICE 3: Add ECal detector (#12682) * Resize Magnet accoding to SD * Add ECal as Pb Cylinder * Update GeometryTGeo.h --- Common/SimConfig/src/SimConfig.cxx | 8 +- .../DetectorsCommonDataFormats/DetID.h | 9 +- .../Headers/include/Headers/DataHeader.h | 3 +- Detectors/Upgrades/ALICE3/CMakeLists.txt | 1 + Detectors/Upgrades/ALICE3/ECal/CMakeLists.txt | 13 + Detectors/Upgrades/ALICE3/ECal/README.md | 10 + .../Upgrades/ALICE3/ECal/base/CMakeLists.txt | 19 ++ .../base/include/ECalBase/ECalBaseParam.h | 33 +++ .../ECal/base/include/ECalBase/GeometryTGeo.h | 47 ++++ .../ALICE3/ECal/base/src/ECalBaseLinkDef.h | 22 ++ .../ALICE3/ECal/base/src/ECalBaseParam.cxx | 14 ++ .../ALICE3/ECal/base/src/GeometryTGeo.cxx | 66 +++++ .../ALICE3/ECal/simulation/CMakeLists.txt | 18 ++ .../include/ECalSimulation/Detector.h | 105 ++++++++ .../ALICE3/ECal/simulation/src/Detector.cxx | 234 ++++++++++++++++++ .../simulation/src/ECalSimulationLinkDef.h | 21 ++ .../include/Alice3DetectorsPassive/Magnet.h | 6 +- macro/CMakeLists.txt | 2 +- macro/build_geometry.C | 6 + run/CMakeLists.txt | 1 + 20 files changed, 625 insertions(+), 13 deletions(-) create mode 100644 Detectors/Upgrades/ALICE3/ECal/CMakeLists.txt create mode 100644 Detectors/Upgrades/ALICE3/ECal/README.md create mode 100644 Detectors/Upgrades/ALICE3/ECal/base/CMakeLists.txt create mode 100644 Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/ECalBaseParam.h create mode 100644 Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/GeometryTGeo.h create mode 100644 Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseLinkDef.h create mode 100644 Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseParam.cxx create mode 100644 Detectors/Upgrades/ALICE3/ECal/base/src/GeometryTGeo.cxx create mode 100644 Detectors/Upgrades/ALICE3/ECal/simulation/CMakeLists.txt create mode 100644 Detectors/Upgrades/ALICE3/ECal/simulation/include/ECalSimulation/Detector.h create mode 100644 Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx create mode 100644 Detectors/Upgrades/ALICE3/ECal/simulation/src/ECalSimulationLinkDef.h diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 8a19217ad629d..9460b429b38d5 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -74,14 +74,14 @@ void SimConfig::determineActiveModules(std::vector const& inputargs if (activeModules[0] != "all") { if (isUpgrade) { for (int i = 0; i < activeModules.size(); ++i) { - if (activeModules[i] != "IT3" && activeModules[i] != "TRK" && activeModules[i] != "FT3" && activeModules[i] != "FCT" && activeModules[i] != "A3IP" && activeModules[i] != "TF3" && activeModules[i] != "RCH" && activeModules[i] != "MI3") { + if (activeModules[i] != "IT3" && activeModules[i] != "TRK" && activeModules[i] != "FT3" && activeModules[i] != "FCT" && activeModules[i] != "A3IP" && activeModules[i] != "TF3" && activeModules[i] != "RCH" && activeModules[i] != "MI3" && activeModules[i] != "ECL") { LOGP(fatal, "List of active modules contains {}, which is not a module from the upgrades.", activeModules[i]); } } } if (!isUpgrade) { for (int i = 0; i < activeModules.size(); ++i) { - if (activeModules[i] == "TRK" || activeModules[i] == "FT3" || activeModules[i] == "FCT" || activeModules[i] == "A3IP" && activeModules[i] == "TF3" && activeModules[i] == "RCH" && activeModules[i] == "MI3") { + if (activeModules[i] == "TRK" || activeModules[i] == "FT3" || activeModules[i] == "FCT" || activeModules[i] == "A3IP" && activeModules[i] == "TF3" && activeModules[i] == "RCH" && activeModules[i] == "MI3" && activeModules[i] == "ECL") { LOGP(fatal, "List of active modules contains {}, which is not a run 3 module", activeModules[i]); } } @@ -93,7 +93,7 @@ void SimConfig::determineActiveModules(std::vector const& inputargs #ifdef ENABLE_UPGRADES if (isUpgrade) { for (int d = DetID::First; d <= DetID::Last; ++d) { - if (d == DetID::TRK || d == DetID::FT3 || d == DetID::FCT || d == DetID::TF3 || d == DetID::RCH) { + if (d == DetID::TRK || d == DetID::FT3 || d == DetID::FCT || d == DetID::TF3 || d == DetID::RCH || d == DetID::ECL) { activeModules.emplace_back(DetID::getName(d)); } } @@ -112,7 +112,7 @@ void SimConfig::determineActiveModules(std::vector const& inputargs activeModules.emplace_back("SHIL"); for (int d = DetID::First; d <= DetID::Last; ++d) { #ifdef ENABLE_UPGRADES - if (d != DetID::IT3 && d != DetID::TRK && d != DetID::FT3 && d != DetID::FCT && d != DetID::TF3 && d != DetID::RCH && d != DetID::MI3) { + if (d != DetID::IT3 && d != DetID::TRK && d != DetID::FT3 && d != DetID::FCT && d != DetID::TF3 && d != DetID::RCH && d != DetID::ECL && d != DetID::MI3) { activeModules.emplace_back(DetID::getName(d)); } } diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h index f796f1f815ece..a2767c7620cdd 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/DetID.h @@ -86,7 +86,8 @@ class DetID static constexpr ID TF3 = 22; static constexpr ID RCH = 23; static constexpr ID MI3 = 24; - static constexpr ID Last = MI3; + static constexpr ID ECL = 25; + static constexpr ID Last = ECL; #else static constexpr ID Last = FOC; ///< if extra detectors added, update this !!! #endif @@ -180,7 +181,7 @@ class DetID // detector names, will be defined in DataSources static constexpr const char* sDetNames[nDetectors + 1] = ///< defined detector names #ifdef ENABLE_UPGRADES - {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "TST", "CTP", "FOC", "IT3", "TRK", "FT3", "FCT", "TF3", "RCH", "MI3", nullptr}; + {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "TST", "CTP", "FOC", "IT3", "TRK", "FT3", "FCT", "TF3", "RCH", "MI3", "ECL", nullptr}; #else {"ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "TST", "CTP", "FOC", nullptr}; #endif @@ -194,7 +195,7 @@ class DetID #ifdef ENABLE_UPGRADES , o2h::gDataOriginIT3, o2h::gDataOriginTRK, o2h::gDataOriginFT3, o2h::gDataOriginFCT, o2h::gDataOriginTF3, - o2h::gDataOriginRCH, o2h::gDataOriginMI3 + o2h::gDataOriginRCH, o2h::gDataOriginMI3, o2h::gDataOriginECL #endif }; #endif // GPUCA_GPUCODE_DEVICE @@ -213,7 +214,7 @@ GPUconstexpr() DetID::mask_t sMasks[DetID::nDetectors] = ///< detectot masks #ifdef ENABLE_UPGRADES , DetID::mask_t(math_utils::bit2Mask(DetID::IT3)), DetID::mask_t(math_utils::bit2Mask(DetID::TRK)), DetID::mask_t(math_utils::bit2Mask(DetID::FT3)), DetID::mask_t(math_utils::bit2Mask(DetID::FCT)), DetID::mask_t(math_utils::bit2Mask(DetID::TF3)), - DetID::mask_t(math_utils::bit2Mask(DetID::RCH)), DetID::mask_t(math_utils::bit2Mask(DetID::MI3)) + DetID::mask_t(math_utils::bit2Mask(DetID::RCH)), DetID::mask_t(math_utils::bit2Mask(DetID::MI3)), DetID::mask_t(math_utils::bit2Mask(DetID::ECL)) #endif }; } // namespace detid_internal diff --git a/DataFormats/Headers/include/Headers/DataHeader.h b/DataFormats/Headers/include/Headers/DataHeader.h index 844823ffed0ed..c37eff9b34f20 100644 --- a/DataFormats/Headers/include/Headers/DataHeader.h +++ b/DataFormats/Headers/include/Headers/DataHeader.h @@ -585,7 +585,8 @@ constexpr o2::header::DataOrigin gDataOriginFT3{"FT3"}; constexpr o2::header::DataOrigin gDataOriginFCT{"FCT"}; constexpr o2::header::DataOrigin gDataOriginTF3{"TF3"}; constexpr o2::header::DataOrigin gDataOriginRCH{"RCH"}; -constexpr o2::header::DataOrigin gDataOriginMI3{"MI3"}; // upgrades +constexpr o2::header::DataOrigin gDataOriginMI3{"MI3"}; +constexpr o2::header::DataOrigin gDataOriginECL{"ECL"}; // upgrades constexpr o2::header::DataOrigin gDataOriginGPU{"GPU"}; diff --git a/Detectors/Upgrades/ALICE3/CMakeLists.txt b/Detectors/Upgrades/ALICE3/CMakeLists.txt index 8330005c3b2e7..0d60f0317dff3 100644 --- a/Detectors/Upgrades/ALICE3/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(Passive) add_subdirectory(TRK) +add_subdirectory(ECal) add_subdirectory(FT3) add_subdirectory(FCT) add_subdirectory(AOD) diff --git a/Detectors/Upgrades/ALICE3/ECal/CMakeLists.txt b/Detectors/Upgrades/ALICE3/ECal/CMakeLists.txt new file mode 100644 index 0000000000000..83838a01d13f1 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +add_subdirectory(base) +add_subdirectory(simulation) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/README.md b/Detectors/Upgrades/ALICE3/ECal/README.md new file mode 100644 index 0000000000000..288040fbd5fd9 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/README.md @@ -0,0 +1,10 @@ + + +# ALICE 3 Electromagnetic Calorimenter + +This is top page for the ECL detector documentation. + + \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/base/CMakeLists.txt b/Detectors/Upgrades/ALICE3/ECal/base/CMakeLists.txt new file mode 100644 index 0000000000000..70017cc051e80 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/base/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2_add_library(ECalBase + SOURCES src/GeometryTGeo.cxx + src/ECalBaseParam.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsBase) + +o2_target_root_dictionary(ECalBase + HEADERS include/ECalBase/GeometryTGeo.h + include/ECalBase/ECalBaseParam.h) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/ECalBaseParam.h b/Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/ECalBaseParam.h new file mode 100644 index 0000000000000..35d25b0050bba --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/ECalBaseParam.h @@ -0,0 +1,33 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_ECAL_BASEPARAM_H +#define O2_ECAL_BASEPARAM_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace ecal +{ +struct ECalBaseParam : public o2::conf::ConfigurableParamHelper { + float rMin = 125.0; // cm + float rMax = 155.0; // cm + float zLength = 350.0; // cm + + O2ParamDef(ECalBaseParam, "ECalBase"); +}; + +} // namespace ecal +} // end namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/GeometryTGeo.h new file mode 100644 index 0000000000000..1cff6dd7d3313 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/base/include/ECalBase/GeometryTGeo.h @@ -0,0 +1,47 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_ECAL_GEOMETRYTGEO_H +#define ALICEO2_ECAL_GEOMETRYTGEO_H + +#include + +namespace o2 +{ +namespace ecal +{ +class GeometryTGeo : public o2::detectors::DetMatrixCache +{ + public: + GeometryTGeo(bool build = false, int loadTrans = 0); + void Build(int loadTrans); + void fillMatrixCache(int mask); + static GeometryTGeo* Instance(); + + static const char* getECalVolPattern() { return sVolumeName.c_str(); } + static const char* getECalSensorPattern() { return sSensorName.c_str(); } + + static const char* composeSymNameECal() + { + return Form("%s_%d", o2::detectors::DetID(o2::detectors::DetID::ECL).getName(), 0); + } + static const char* composeSymNameSensor(); // A single sensor for the moment + + protected: + static std::string sVolumeName; + static std::string sSensorName; + + private: + static std::unique_ptr sInstance; +}; +} // namespace ecal +} // namespace o2 +#endif diff --git a/Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseLinkDef.h b/Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseLinkDef.h new file mode 100644 index 0000000000000..3bf7ccd32460c --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseLinkDef.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::ecal::GeometryTGeo + +#pragma link C++ class o2::ecal::ECalBaseParam + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::ecal::ECalBaseParam> + ; + +#endif \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseParam.cxx b/Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseParam.cxx new file mode 100644 index 0000000000000..54eb2860526b3 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/base/src/ECalBaseParam.cxx @@ -0,0 +1,14 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "ECalBase/ECalBaseParam.h" + +O2ParamImpl(o2::ecal::ECalBaseParam); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/ECal/base/src/GeometryTGeo.cxx new file mode 100644 index 0000000000000..49f57d8a8c5cc --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/base/src/GeometryTGeo.cxx @@ -0,0 +1,66 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +namespace o2 +{ +namespace ecal +{ +std::unique_ptr GeometryTGeo::sInstance; + +std::string GeometryTGeo::sVolumeName = "ECALV"; +std::string GeometryTGeo::sSensorName = "ECALSensor"; + +GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : DetMatrixCache() +{ + if (sInstance) { + LOGP(fatal, "Invalid use of public constructor: o2::ecal::GeometryTGeo instance exists"); + } + if (build) { + Build(loadTrans); + } +} + +void GeometryTGeo::Build(int loadTrans) +{ + if (isBuilt()) { + LOGP(warning, "Already built"); + return; // already initialized + } + + if (!gGeoManager) { + LOGP(fatal, "Geometry is not loaded"); + } + + fillMatrixCache(loadTrans); +} + +void GeometryTGeo::fillMatrixCache(int mask) +{ +} + +GeometryTGeo* GeometryTGeo::Instance() +{ + if (!sInstance) { + sInstance = std::unique_ptr(new GeometryTGeo(true, 0)); + } + return sInstance.get(); +} + +const char* GeometryTGeo::composeSymNameSensor() +{ + return Form("%s/%d", composeSymNameECal(), 0); +} + +} // namespace ecal +} // namespace o2 \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/ECal/simulation/CMakeLists.txt new file mode 100644 index 0000000000000..8c8c5a6bba15f --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/simulation/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2_add_library(ECalSimulation + SOURCES src/Detector.cxx + PUBLIC_LINK_LIBRARIES O2::ECalBase + O2::ITSMFTSimulation) + +o2_target_root_dictionary(ECalSimulation + HEADERS include/ECalSimulation/Detector.h) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/simulation/include/ECalSimulation/Detector.h b/Detectors/Upgrades/ALICE3/ECal/simulation/include/ECalSimulation/Detector.h new file mode 100644 index 0000000000000..54e715224f728 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/simulation/include/ECalSimulation/Detector.h @@ -0,0 +1,105 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Design and equations: Nicola Nicassio nicola.nicassio@cern.ch +// + +#ifndef ALICEO2_ECAL_DETECTOR_H +#define ALICEO2_ECAL_DETECTOR_H + +#include "DetectorsBase/Detector.h" +#include "ITSMFTSimulation/Hit.h" + +#include "ECalBase/GeometryTGeo.h" + +#include +#include + +namespace o2 +{ +namespace ecal +{ + +class Detector : public o2::base::DetImpl +{ + public: + Detector(bool active); + Detector(); + ~Detector(); + + void ConstructGeometry() override; + + o2::itsmft::Hit* addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, + const TVector3& startMom, double startE, double endTime, double eLoss, + unsigned char startStatus, unsigned char endStatus); + + // Mandatory overrides + void BeginPrimary() override { ; } + void FinishPrimary() override { ; } + void InitializeO2Detector() override; + void PostTrack() override { ; } + void PreTrack() override { ; } + bool ProcessHits(FairVolume* v = nullptr) override; + void EndOfEvent() override; + void Register() override; + void Reset() override; + + // Custom memer functions + std::vector* getHits(int iColl) const + { + if (!iColl) { + return mHits; + } + return nullptr; + } + + void createMaterials(); + void createGeometry(); + + private: + // Transient data about track passing the sensor + struct TrackData { + bool mHitStarted; // hit creation started + unsigned char mTrkStatusStart; // track status flag + TLorentzVector mPositionStart; // position at entrance + TLorentzVector mMomentumStart; // momentum + double mEnergyLoss; // energy loss + } mTrackData; //! transient data + + GeometryTGeo* mGeometryTGeo; //! + std::vector* mHits; // ITSMFT ones for the moment + + void defineSensitiveVolumes(); + float mInnerRadius; + float mOuterRadius; + float mLength; + + protected: + template + friend class o2::base::DetImpl; + ClassDefOverride(Detector, 1); +}; +} // namespace ecal +} // namespace o2 + +#ifdef USESHM +namespace o2 +{ +namespace base +{ +template <> +struct UseShm { + static constexpr bool value = true; +}; +} // namespace base +} // namespace o2 +#endif +#endif \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx new file mode 100644 index 0000000000000..587dd4053b777 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx @@ -0,0 +1,234 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include + +#include +#include +#include +#include +#include + +#include "DetectorsBase/Stack.h" +#include "ITSMFTSimulation/Hit.h" +#include "ECalSimulation/Detector.h" +#include "ECalBase/ECalBaseParam.h" + +using o2::itsmft::Hit; + +namespace o2 +{ +namespace ecal +{ + +Detector::Detector() + : o2::base::DetImpl("ECL", true), + mTrackData(), + mHits(o2::utils::createSimVector()) +{ +} + +Detector::Detector(bool active) + : o2::base::DetImpl("ECL", true), + mTrackData(), + mHits(o2::utils::createSimVector()) +{ + auto& ecalPars = ECalBaseParam::Instance(); + mInnerRadius = ecalPars.rMin; + mOuterRadius = ecalPars.rMax; + mLength = ecalPars.zLength; +} + +Detector::~Detector() +{ + if (mHits) { + o2::utils::freeSimVector(mHits); + } +} + +void Detector::ConstructGeometry() +{ + createMaterials(); + createGeometry(); +} + +void Detector::createMaterials() +{ + int ifield = 2; // ? + float fieldm = 10.0; // ? + o2::base::Detector::initFieldTrackingParams(ifield, fieldm); + + float tmaxfdLead = 0.1; // .10000E+01; // Degree + float stemaxLead = .10000E+01; // cm + float deemaxLead = 0.1; // 0.30000E-02; // Fraction of particle's energy 0RegisterAny(addNameTo("Hit").data(), mHits, true); + } +} + +void Detector::createGeometry() +{ + LOGP(info, "Creating ECal geometry"); + + TGeoManager* geoManager = gGeoManager; + TGeoVolume* vALIC = geoManager->GetVolume("barrel"); + if (!vALIC) { + LOGP(fatal, "Could not find barrel volume while constructing ECal geometry"); + } + new TGeoVolumeAssembly(GeometryTGeo::getECalVolPattern()); + TGeoVolume* vECal = geoManager->GetVolume(GeometryTGeo::getECalVolPattern()); + vALIC->AddNode(vECal, 2, new TGeoTranslation(0, 30., 0)); + + char vstrng[100] = "ECalVol"; + vECal->SetTitle(vstrng); + + // Build the ECal cylinder + auto& matmgr = o2::base::MaterialManager::Instance(); + TGeoMedium* medPb = matmgr.getTGeoMedium("ECL_LEAD"); + TGeoTube* ecalShape = new TGeoTube("ECLsh", mInnerRadius, mOuterRadius, mLength); + TGeoVolume* ecalVol = new TGeoVolume("ECL", ecalShape, medPb); + ecalVol->SetLineColor(kCyan + 1); + ecalVol->SetTransparency(50); + vECal->AddNode(ecalVol, 1, nullptr); +} + +void Detector::Reset() +{ + if (!o2::utils::ShmManager::Instance().isOperational()) { + mHits->clear(); + } +} + +bool Detector::ProcessHits(FairVolume* vol) +{ + // This method is called from the MC stepping + if (!(fMC->TrackCharge())) { + return false; + } + + int lay = vol->getVolumeId(); + int volID = vol->getMCid(); + + // Is it needed to keep a track reference when the outer ITS volume is encountered? + auto stack = (o2::data::Stack*)fMC->GetStack(); + if (fMC->IsTrackExiting() && (lay == 0)) { + o2::TrackReference tr(*fMC, GetDetId()); + tr.setTrackID(stack->GetCurrentTrackNumber()); + tr.setUserId(lay); + stack->addTrackReference(tr); + } + bool startHit = false, stopHit = false; + unsigned char status = 0; + if (fMC->IsTrackEntering()) { + status |= Hit::kTrackEntering; + } + if (fMC->IsTrackInside()) { + status |= Hit::kTrackInside; + } + if (fMC->IsTrackExiting()) { + status |= Hit::kTrackExiting; + } + if (fMC->IsTrackOut()) { + status |= Hit::kTrackOut; + } + if (fMC->IsTrackStop()) { + status |= Hit::kTrackStopped; + } + if (fMC->IsTrackAlive()) { + status |= Hit::kTrackAlive; + } + + // track is entering or created in the volume + if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) { + startHit = true; + } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) { + stopHit = true; + } + + // increment energy loss at all steps except entrance + if (!startHit) { + mTrackData.mEnergyLoss += fMC->Edep(); + } + if (!(startHit | stopHit)) { + return false; // do noting + } + + if (startHit) { + mTrackData.mEnergyLoss = 0.; + fMC->TrackMomentum(mTrackData.mMomentumStart); + fMC->TrackPosition(mTrackData.mPositionStart); + mTrackData.mTrkStatusStart = status; + mTrackData.mHitStarted = true; + } + if (stopHit) { + TLorentzVector positionStop; + fMC->TrackPosition(positionStop); + // Retrieve the indices with the volume path + int stave(0), halfstave(0), chipinmodule(0), module; + fMC->CurrentVolOffID(1, chipinmodule); + fMC->CurrentVolOffID(2, module); + fMC->CurrentVolOffID(3, halfstave); + fMC->CurrentVolOffID(4, stave); + + Hit* p = addHit(stack->GetCurrentTrackNumber(), lay, mTrackData.mPositionStart.Vect(), positionStop.Vect(), + mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(), + mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status); + // p->SetTotalEnergy(vmc->Etot()); + + // RS: not sure this is needed + // Increment number of Detector det points in TParticle + stack->addHit(GetDetId()); + } + + return true; +} + +o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, + const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus, + unsigned char endStatus) +{ + mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus); + return &(mHits->back()); +} + +} // namespace ecal +} // namespace o2 + +ClassImp(o2::ecal::Detector); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/simulation/src/ECalSimulationLinkDef.h b/Detectors/Upgrades/ALICE3/ECal/simulation/src/ECalSimulationLinkDef.h new file mode 100644 index 0000000000000..167342773f196 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/ECal/simulation/src/ECalSimulationLinkDef.h @@ -0,0 +1,21 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::ecal::Detector + ; +#pragma link C++ class o2::base::DetImpl < o2::ecal::Detector> + ; + +#endif diff --git a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Magnet.h b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Magnet.h index 2a2ac011a6aaa..673e3ded075ac 100644 --- a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Magnet.h +++ b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Magnet.h @@ -35,11 +35,11 @@ class Alice3Magnet : public Alice3PassiveBase Alice3Magnet(const Alice3Magnet& orig); Alice3Magnet& operator=(const Alice3Magnet&); - float mInnerWrapInnerRadius{150.f}; // cm + float mInnerWrapInnerRadius{160.f}; // cm // Version including the Ecal according SD float mInnerWrapThickness{1.f}; // cm - float mCoilInnerRadius{170.f}; // cm + float mCoilInnerRadius{180.f}; // cm float mCoilThickness{0.3f}; // cm - float mRestMaterialRadius{170.3f}; // cm + float mRestMaterialRadius{180.3f}; // cm float mRestMaterialThickness{6.8f}; // cm float mOuterWrapInnerRadius{200.f}; // cm float mOuterWrapThickness{3.f}; // cm diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index de8c31a23c50f..8520031bcad73 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -111,7 +111,7 @@ o2_add_test_root_macro(analyzeOriginHits.C O2::DetectorsCommonDataFormats) if(ENABLE_UPGRADES) - set(upgradeTargets O2::Alice3DetectorsPassive O2::ITS3Simulation O2::TRKSimulation O2::FT3Simulation O2::FCTSimulation O2::IOTOFSimulation O2::RICHSimulation) + set(upgradeTargets O2::Alice3DetectorsPassive O2::ITS3Simulation O2::TRKSimulation O2::FT3Simulation O2::FCTSimulation O2::IOTOFSimulation O2::RICHSimulation O2::ECalSimulation) endif() o2_add_test_root_macro(build_geometry.C diff --git a/macro/build_geometry.C b/macro/build_geometry.C index ec959bfa00511..eb996d0482640 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -250,6 +251,11 @@ void build_geometry(FairRunSim* run = nullptr) // ALICE 3 RICH addReadoutDetector(new o2::rich::Detector(isReadout("RCH"))); } + + if (isActivated("ECL")) { + // ALICE 3 ECAL + addReadoutDetector(new o2::ecal::Detector(isReadout("ECL"))); + } #endif if (isActivated("ITS")) { diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 58e5d9e5af402..afaa7486ae013 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -44,6 +44,7 @@ target_link_libraries(allsim $<$:O2::FCTSimulation> $<$:O2::IOTOFSimulation> $<$:O2::RICHSimulation> + $<$:O2::ECalSimulation> O2::Generators) add_library(internal::allsim ALIAS allsim) From f98944059f9558e5b7a493f9e77cdeed6a59fd7d Mon Sep 17 00:00:00 2001 From: Casper van Veen <96796377+Cas1997@users.noreply.github.com> Date: Thu, 15 Feb 2024 18:31:03 +0100 Subject: [PATCH 43/50] ALICE 3: Beam pipe vacuum vessel, IRIS vacuum vessel update (#12696) * Special scenarios for the FCT. These 6 special setups allow to test the FCT with a vacuum vessel and windowed beam pipe. * Improved beam pipe description * Fixed parameters of pipe * Fixed overlap issues * Beampipe update + FCT SD + FT3 bug fix * Layer placement fix FCT + TRK IRIS Vacuum vessel Material name fic * Adhere to clang format * Remove comment Co-authored-by: Matteo Concas * Small style fix --------- Co-authored-by: Matteo Concas --- .../ALICE3/FCT/simulation/src/Detector.cxx | 46 +++-- .../ALICE3/FCT/simulation/src/FCTLayer.cxx | 6 +- .../include/FT3Simulation/FT3Layer.h | 17 +- .../ALICE3/FT3/simulation/src/Detector.cxx | 25 ++- .../include/Alice3DetectorsPassive/Pipe.h | 43 ++-- .../Upgrades/ALICE3/Passive/src/Pipe.cxx | 187 ++++++++++++------ .../include/TRKSimulation/TRKServices.h | 11 +- .../ALICE3/TRK/simulation/src/Detector.cxx | 4 +- .../ALICE3/TRK/simulation/src/TRKServices.cxx | 66 ++++++- macro/build_geometry.C | 2 +- 10 files changed, 268 insertions(+), 139 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx index f5d5255be1c0c..458df289d0bb2 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx @@ -22,13 +22,13 @@ #include "SimulationDataFormat/TrackReference.h" // FairRoot includes -#include "FairDetector.h" // for FairDetector +#include "FairDetector.h" // for FairDetector #include // for LOG, LOG_IF -#include "FairModule.h" // for FairModule -#include "FairRootManager.h" // for FairRootManager -#include "FairRun.h" // for FairRun -#include "FairRuntimeDb.h" // for FairRuntimeDb -#include "FairVolume.h" // for FairVolume +#include "FairModule.h" // for FairModule +#include "FairRootManager.h" // for FairRootManager +#include "FairRun.h" // for FairRun +#include "FairRuntimeDb.h" // for FairRuntimeDb +#include "FairVolume.h" // for FairVolume #include "FairRootManager.h" #include "TGeoManager.h" // for TGeoManager, gGeoManager @@ -92,7 +92,6 @@ void Detector::buildFCTFromFile(std::string configFileName) } std::string tempstr; float z_layer, r_in, r_out_l_side, Layerx2X0; - char delimiter; int layerNumber = 0; int layerNumberSquare = 0; int layerNumberDisk = 0; @@ -155,12 +154,7 @@ void Detector::exportLayout() { // Export FCT Layout description to file. One line per disk // z_layer r_in r_out Layerx2X0 - - TDatime* time = new TDatime(); - TString configFileName = "FCT_layout_"; - configFileName.Append(Form("%d.cfg", time->GetTime())); - - // std::string configFileName = "FCT_layout.cfg"; + TString configFileName = "FCT_layout.cfg"; LOG(info) << "Exporting FCT Detector layout to " << configFileName; @@ -212,23 +206,25 @@ void Detector::buildBasicFCT(const FCTBaseParam& param) //_________________________________________________________________________________________________ void Detector::buildFCTV1() { - // Build default FCT detector + // Build FCT according to Scoping Document LOG(info) << "Building FCT Detector: V1"; - mNumberOfLayers = 9; + mNumberOfLayers = 11; Float_t layersx2X0 = 1.e-2; std::vector> layersConfig{ - {-442.0, 6.0, 44.1, layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} - {-444.0, 6.0, 44.3, layersx2X0}, - {-446.0, 6.0, 44.5, layersx2X0}, - {-448.0, 6.0, 44.7, layersx2X0}, - {-450.0, 6.1, 44.9, layersx2X0}, - {-460.0, 6.2, 45.9, layersx2X0}, - {-470.0, 6.3, 46.9, layersx2X0}, - {-480.0, 6.5, 47.9, layersx2X0}, - {-490.0, 6.6, 48.9, layersx2X0}}; + {442.0, 5.0, 17.0, layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} + {444.0, 5.0, 17.0, layersx2X0}, + {446.0, 5.0, 17.0, layersx2X0}, + {448.0, 5.0, 17.0, layersx2X0}, + {450.0, 5.0, 17.0, layersx2X0}, + {452.0, 5.0, 17.0, layersx2X0}, + {460.0, 5.0, 17.0, layersx2X0}, + {470.0, 5.0, 18.0, layersx2X0}, + {480.0, 5.0, 18.0, layersx2X0}, + {490.0, 5.0, 19.0, layersx2X0}, + {500.0, 5.0, 19.0, layersx2X0}}; mLayerID.clear(); mLayerName.clear(); @@ -488,6 +484,7 @@ void Detector::ConstructGeometry() break; } } + exportLayout(); // Create detector materials @@ -541,6 +538,7 @@ void Detector::createGeometry() } vALIC->AddNode(volFCT, 2, new TGeoTranslation(0., 30., 0.)); } + LOG(info) << "Registering FCT SensitiveLayerIDs:"; for (int iLayer = 0; iLayer < mLayers.size(); iLayer++) { auto layerID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_%d", GeometryTGeo::getFCTSensorPattern(), mLayers[iLayer].getLayerNumber())) : 0; diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx index a0d1896c42266..100721c455363 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTLayer.cxx @@ -41,10 +41,8 @@ FCTLayer::~FCTLayer() = default; FCTLayer::FCTLayer(Int_t layerNumber, std::string layerName, Float_t z, Float_t rIn, Float_t rOut_SideL, Float_t Layerx2X0, Int_t type) : mLayerNumber(layerNumber), mLayerName(layerName), mx2X0(Layerx2X0), mType(type), mInnerRadius(rIn) { - // Creates a simple parametrized FCT layer covering the given - // (rIn, rOut_SideL) range at the z layer position - mZ = -std::abs(z); - if (type == 0) { // Disk + mZ = z; + if (type == 0 || type == 2) { // Disk mOuterRadius = rOut_SideL; } else if (type == 1) { // Square mSideLength = rOut_SideL; diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/FT3Layer.h b/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/FT3Layer.h index ad087ad979728..7159f2a6d1d9f 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/FT3Layer.h +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/FT3Layer.h @@ -49,6 +49,7 @@ class FT3Layer : public TObject /// getters auto getInnerRadius() const { return mInnerRadius; } auto getOuterRadius() const { return mOuterRadius; } + auto getDirection() const { return mDirection; } auto getZ() const { return mZ; } auto getx2X0() const { return mx2X0; } @@ -57,14 +58,14 @@ class FT3Layer : public TObject virtual void createLayer(TGeoVolume* motherVolume); private: - Int_t mLayerNumber = -1; ///< Current layer number - Int_t mDirection; ///< Layer direction 0=Forward 1 = Backward - std::string mLayerName; ///< Current layer name - Double_t mInnerRadius; ///< Inner radius of this layer - Double_t mOuterRadius; ///< Outer radius of this layer - Double_t mZ; ///< Z position of the layer - Double_t mChipThickness; ///< Chip thickness - Double_t mx2X0; ///< Layer material budget x/X0 + Int_t mLayerNumber = -1; ///< Current layer number + Int_t mDirection; ///< Layer direction 0=Forward 1 = Backward + std::string mLayerName; ///< Current layer name + Double_t mInnerRadius; ///< Inner radius of this layer + Double_t mOuterRadius; ///< Outer radius of this layer + Double_t mZ; ///< Z position of the layer + Double_t mChipThickness; ///< Chip thickness + Double_t mx2X0; ///< Layer material budget x/X0 ClassDefOverride(FT3Layer, 0); // ALICE 3 EndCaps geometry }; diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx index 888be687b9f0f..625f2b28182c5 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx @@ -22,12 +22,12 @@ #include "SimulationDataFormat/TrackReference.h" // FairRoot includes -#include "FairDetector.h" // for FairDetector +#include "FairDetector.h" // for FairDetector #include // for LOG, LOG_IF -#include "FairRootManager.h" // for FairRootManager -#include "FairRun.h" // for FairRun -#include "FairRuntimeDb.h" // for FairRuntimeDb -#include "FairVolume.h" // for FairVolume +#include "FairRootManager.h" // for FairRootManager +#include "FairRun.h" // for FairRun +#include "FairRuntimeDb.h" // for FairRuntimeDb +#include "FairVolume.h" // for FairVolume #include "FairRootManager.h" #include "TGeoManager.h" // for TGeoManager, gGeoManager @@ -106,10 +106,17 @@ void Detector::buildFT3FromFile(std::string configFileName) iss >> r_out; iss >> Layerx2X0; - std::string layerName = GeometryTGeo::getFT3LayerPattern() + std::string("_") + std::to_string(layerNumber); + int direction = 1; // Forwards + if (z_layer < 0) { + // Backwards + direction = 0; + } + + std::string directionName = std::to_string(direction); + std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber); mLayerName[0].push_back(layerName); - LOG(info) << "Adding Layer " << layerName << " at z = " << z_layer << " ; r_in = " << r_in << " ; r_out = " << r_out << " x/X0 = " << Layerx2X0; - auto& thisLayer = mLayers[0].emplace_back(0, layerNumber, layerName, z_layer, r_in, r_out, Layerx2X0); + LOG(info) << "Adding Layer " << layerName << " at z = " << z_layer << " ; direction = " << direction << " ; r_in = " << r_in << " ; r_out = " << r_out << " x/X0 = " << Layerx2X0; + auto& thisLayer = mLayers[0].emplace_back(direction, layerNumber, layerName, z_layer, r_in, r_out, Layerx2X0); layerNumber++; } @@ -665,7 +672,7 @@ void Detector::defineSensitiveVolumes() if (mLayers.size() == 1) { for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) { volumeName = o2::ft3::GeometryTGeo::getFT3SensorPattern() + std::to_string(iLayer); - v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), 0, iLayer)); + v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), mLayers[0][iLayer].getDirection(), iLayer)); LOG(info) << "Adding FT3 Sensitive Volume => " << v->GetName(); AddSensitiveVolume(v); } diff --git a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h index 80d9d58f95d4a..47b803c1bcbd1 100644 --- a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h +++ b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h @@ -27,44 +27,47 @@ class Alice3Pipe : public Alice3PassiveBase Alice3Pipe(const char* name, const char* title = "Alice 3 Pipe", const bool isTRKActivated = false, - const float rMinInnerPipe = 0.f, - const float innerThickness = 0.f, - const float innerLength = 0.f, - const float rMinOuterPipe = 0.f, - const float outerThickness = 0.f, - const float outerLength = 0.f); + const bool isFT3Activated = false, + const float pipeRIn = 0.f, + const float pipeThickness = 0.f, + const float a3ipLength = 0.f, + const float vacuumVesselRIn = 0.f, + const float vacuumVesselThickness = 0.f, + const float vacuumVesselLength = 0.f); void ConstructGeometry() override; /// Clone this object (used in MT mode only) FairModule* CloneModule() const override; - float getInnerRmin() const { return mBeInnerPipeRmin; } - float getInnerRmax() const { return mBeInnerPipeRmin + mBeInnerPipeThick; } - float getInnerWidth() const { return mBeInnerPipeThick; } - float getInnerDz() const { return mInnerIpHLength; } + float getPipeRIn() const { return mPipeRIn; } + float getPipeRMax() const { return mPipeRIn + mPipeThick; } + float getPipeWidth() const { return mPipeThick; } + float getA3IPLength() const { return mA3IPLength; } - float getOuterRmin() const { return mBeOuterPipeRmin; } - float getOuterRmax() const { return mBeOuterPipeRmin + mBeOuterPipeThick; } - float getOuterWidth() const { return mBeOuterPipeThick; } - float getOuterDz() const { return mOuterIpHLength; } + float getVacuumVesselRIn() const { return mVacuumVesselRIn; } + float getVacuumVesselRMax() const { return mVacuumVesselRIn + mVacuumVesselThick; } + float getVacuumVesselWidth() const { return mVacuumVesselThick; } + float getVacuumVesselLength() const { return mVacuumVesselLength; } bool IsTRKActivated() const { return mIsTRKActivated; } + bool IsFT3Activated() const { return mIsFT3Activated; } private: void createMaterials(); Alice3Pipe(const Alice3Pipe& orig) = default; Alice3Pipe& operator=(const Alice3Pipe&); - float mBeInnerPipeRmin = 0.; // inner diameter of the inner Be section - float mBeInnerPipeThick = 0.; // inner beam pipe section thickness - float mInnerIpHLength = 0.; // half length of the inner beampipe around the IP + float mPipeRIn = 0.; // inner diameter of the pipe + float mPipeThick = 0.; // inner beam pipe section thickness + float mA3IPLength = 0.; // Length of A3IP - float mBeOuterPipeRmin = 0.; // inner diameter of the outer Be section - float mBeOuterPipeThick = 0.; // outer beam pipe section thickness - float mOuterIpHLength = 0.; // half length of the outer beampipe around the IP + float mVacuumVesselRIn = 0.; // inner diameter of the vacuum vessel + float mVacuumVesselThick = 0.; // outer beam pipe section thickness + float mVacuumVesselLength = 0.; // half length of the outer beampipe around the IP bool mIsTRKActivated = true; // If TRK is not active don't create TRK layers allocations in the vacuum volume + bool mIsFT3Activated = true; ClassDefOverride(Alice3Pipe, 1); }; diff --git a/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx b/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx index a5bc1d059fde0..f7f4c1844f7df 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx +++ b/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx @@ -18,7 +18,8 @@ #include "TGeoMaterial.h" // for TGeoMaterial #include "TGeoMedium.h" // for TGeoMedium #include "TGeoVolume.h" // for TGeoVolume -#include "TGeoCompositeShape.h" // forTGeoCompositeShape +#include "TGeoCompositeShape.h" // for TGeoCompositeShape +#include "TCanvas.h" // force availability of assert #ifdef NDEBUG #undef NDEBUG @@ -31,20 +32,22 @@ Alice3Pipe::Alice3Pipe() : Alice3PassiveBase{"Alice3PIPE", ""} {} Alice3Pipe::Alice3Pipe(const char* name, const char* title, bool isTRKActivated, - float rMinInnerPipe, - float innerThickness, - float innerLength, - float rMinOuterPipe, - float outerThickness, - float outerLength) + bool isFT3Activated, + float pipeRIn, + float pipeThickness, + float a3ipLength, + float vacuumVesselRIn, + float vacuumVesselThickness, + float vacuumVesselLength) : Alice3PassiveBase{name, title}, mIsTRKActivated{isTRKActivated}, - mBeInnerPipeRmin{rMinInnerPipe}, - mBeInnerPipeThick{innerThickness}, - mInnerIpHLength{innerLength}, - mBeOuterPipeRmin{rMinOuterPipe}, - mBeOuterPipeThick{outerThickness}, - mOuterIpHLength{outerLength} + mIsFT3Activated{isFT3Activated}, + mPipeRIn{pipeRIn}, + mPipeThick{pipeThickness}, + mA3IPLength{a3ipLength}, + mVacuumVesselRIn{vacuumVesselRIn}, + mVacuumVesselThick{vacuumVesselThickness}, + mVacuumVesselLength{vacuumVesselLength} { } @@ -68,8 +71,6 @@ void Alice3Pipe::ConstructGeometry() // // Class describing the beam Alice3Pipe geometry // - float z, zsh, z0; - // // Rotation Matrices // const float kDegRad = TMath::Pi() / 180.; @@ -93,75 +94,139 @@ void Alice3Pipe::ConstructGeometry() LOG(fatal) << "Could not find the top volume"; } - //---------------- Outermost Be pipe around the IP ---------- - // Outer pipe has to be filled with vacuum. There we have also TRK layers, which we don't want to depend on the pipe volume. - // Eventually, we will depend on some information passed from the outside. - // For A3PIP-only simulations, we don't want TRK's shade. - // Strategy used here is to use a composite shape where shapes of TRK layers are subtracted to the vacuum volume - TGeoTube* outerBeTube = new TGeoTube("OUT_PIPEsh", mBeOuterPipeRmin, mBeOuterPipeRmin + mBeOuterPipeThick, mOuterIpHLength); - TGeoVolume* outerBeTubeVolume = new TGeoVolume("OUT_PIPE", outerBeTube, kMedBe); - outerBeTubeVolume->SetLineColor(kGreen - 9); - - TGeoTube* outerBerylliumTubeVacuumBase = new TGeoTube("OUT_PIPEVACUUM_BASEsh", mBeInnerPipeRmin + mBeInnerPipeThick, mBeOuterPipeRmin, mOuterIpHLength); // Vacuum filling for outer pipe - TGeoCompositeShape* outerBerylliumTubeVacuumComposite; // Composite volume to subctract to vacuum - TGeoVolume* outerBerylliumTubeVacuumVolume; // Final volume to be used + // We split the naming of the parts if the beam pipe for ALICE 3 into parts + // - pipe + // - vacuum vessel (which hosts the primary vacuum) + // - iris vacuum vessel (which hosts the secondary vacuum) - TString compositeFormula{"OUT_PIPEVACUUM_BASEsh"}; // If pipe is alone we won't subctract anything + // A3IP update + // Vacuum + TGeoTube* vacuumBasePipe = new TGeoTube("PIPEVACUUM_BASEsh", 0., mPipeRIn, mA3IPLength / 2.); + TGeoTube* vacuumBaseVacuumVessel = new TGeoTube("VACUUM_VESSELVACUUM_BASEsh", mPipeRIn, mVacuumVesselRIn, mVacuumVesselLength / 2.); + // Excavate volumes from the vacuum such that there is place for the TRK barrel layers and FT3 disc layers of the IRIS tracker + // And the other passive shapes: coldplate, iris tracker vacuum vessel + TGeoCompositeShape* vacuumComposite; + TGeoVolume* vacuumVolume; + TString compositeFormula{"PIPEVACUUM_BASEsh+VACUUM_VESSELVACUUM_BASEsh"}; TString subtractorsFormula; if (!mIsTRKActivated) { std::vector trkLayerShapes; - std::vector> layersQuotas = {std::array{0.5f, 50.f, 50.e-4}, // TODO: Set layers dynamically. {radius, zLen, thickness} - std::array{1.2f, 50.f, 50.e-4}, - std::array{2.5f, 50.f, 50.e-4}}; + std::vector> layersQuotas = {std::array{0.5f, 50.f, 100.e-4}, // TODO: Set layers dynamically. {radius, zLen, thickness} + std::array{1.2f, 50.f, 100.e-4}, + std::array{2.5f, 50.f, 100.e-4}}; - subtractorsFormula = "TRKLAYER_0sh"; // First volume to be subctracted (at least one has to be provided) for (auto iLayer{0}; iLayer < layersQuotas.size(); ++iLayer) { // Create TRK layers shapes auto& layerData = layersQuotas[iLayer]; - trkLayerShapes.emplace_back(new TGeoTube(Form("TRKLAYER_%dsh", iLayer), layerData[0], layerData[0] + layerData[2], layerData[1] / 2)); - if (iLayer > 0) { - subtractorsFormula += Form("+TRKLAYER_%dsh", iLayer); + trkLayerShapes.emplace_back(new TGeoTube(Form("TRKLAYER_%dsh", iLayer), layerData[0], layerData[0] + layerData[2], layerData[1] / 2.)); + if (iLayer != 0) { + subtractorsFormula += "+"; } + subtractorsFormula += Form("TRKLAYER_%dsh", iLayer); } - // Escavate vacuum for hosting cold plate - TGeoTube* coldPlate = new TGeoTube("TRK_COLDPLATEsh", 2.6f, 2.6f + 150.e-3, 50.f / 2); + // IRIS vacuum vessel and coldplate dimensions + float coldplateRIn = 2.6f; // cm + float coldplateThick = 150.e-3; // cm + float coldplateLength = 50.f; // cm + float irisVacuumVesselInnerRIn = 0.48f; // cm + float irisVacuumVesselOuterRIn = coldplateRIn + coldplateThick; + float irisVacuumVesselLength = 70.f; // cm + float irisVacuumVesselThick = 150.e-4; // cm + + // Excavate vacuum for hosting cold plate and IRIS tracker + TGeoTube* coldPlate = new TGeoTube("TRK_COLDPLATEsh", coldplateRIn, coldplateRIn + coldplateThick, coldplateLength / 2.); subtractorsFormula += "+TRK_COLDPLATEsh"; + TGeoTube* irisVacuumVesselInner = new TGeoTube("TRK_IRISVACUUMVESSELINNERsh", irisVacuumVesselInnerRIn, irisVacuumVesselInnerRIn + irisVacuumVesselThick, irisVacuumVesselLength / 2.); + subtractorsFormula += "+TRK_IRISVACUUMVESSELINNERsh"; + + TGeoTube* irisVacuumVesselOuter = new TGeoTube("TRK_IRISVACUUMVESSELOUTERsh", irisVacuumVesselOuterRIn, irisVacuumVesselOuterRIn + irisVacuumVesselThick, irisVacuumVesselLength / 2.); + subtractorsFormula += "+TRK_IRISVACUUMVESSELOUTERsh"; + + TGeoTube* irisVacuumVesselWall = new TGeoTube("TRK_IRISVACUUMVESSELWALLsh", irisVacuumVesselInnerRIn, irisVacuumVesselOuterRIn + irisVacuumVesselThick, irisVacuumVesselThick / 2.); + TGeoTranslation* posIrisVacVWallNegZSide = new TGeoTranslation("IRISWALLNEGZ", 0., 0., -irisVacuumVesselLength / 2. - irisVacuumVesselThick / 2.); + posIrisVacVWallNegZSide->RegisterYourself(); + subtractorsFormula += "+TRK_IRISVACUUMVESSELWALLsh:IRISWALLNEGZ"; + + TGeoTranslation* posIrisVacVWallPosZSide = new TGeoTranslation("IRISWALLPOSZ", 0., 0., irisVacuumVesselLength / 2. + irisVacuumVesselThick / 2.); + posIrisVacVWallPosZSide->RegisterYourself(); + subtractorsFormula += "+TRK_IRISVACUUMVESSELWALLsh:IRISWALLPOSZ"; + } + + if (!mIsFT3Activated) { + std::vector ft3DiscShapes; + std::vector ft3DiscPositions; + + std::vector> discsQuotas = {std::array{0.5f, 2.5f, 100.e-4, 26.}, // TODO: Set discs dynamically. {rIn, rOut, thickness, zpos} + std::array{0.5f, 2.5f, 100.e-4, 30.}, + std::array{0.5f, 2.5f, 100.e-4, 34.}, + std::array{0.5f, 2.5f, 100.e-4, -26.}, + std::array{0.5f, 2.5f, 100.e-4, -30.}, + std::array{0.5f, 2.5f, 100.e-4, -34.}}; + TString tempSubtractorsFormula = ""; + if (!mIsTRKActivated) { + tempSubtractorsFormula = "+"; + } + for (auto iDisc{0}; iDisc < discsQuotas.size(); ++iDisc) { + auto& discData = discsQuotas[iDisc]; + ft3DiscShapes.emplace_back(new TGeoTube(Form("FT3DISC_%dsh", iDisc), discData[0], discData[1], discData[2] / 2.)); + ft3DiscPositions.emplace_back(new TGeoTranslation(Form("t%d", iDisc), 0., 0., discData[3])); + ft3DiscPositions[iDisc]->RegisterYourself(); + if (iDisc != 0) { + tempSubtractorsFormula += "+"; + } + tempSubtractorsFormula += Form("FT3DISC_%dsh:t%d", iDisc, iDisc); + } + subtractorsFormula += tempSubtractorsFormula; + } + + // Pipe tubes + Double_t pipeLengthHalf = mA3IPLength / 2. - mVacuumVesselThick - mVacuumVesselLength / 2.; + TGeoTube* pipe = new TGeoTube("PIPEsh", mPipeRIn, mPipeRIn + mPipeThick, pipeLengthHalf / 2.); + TGeoTube* vacuumVesselTube = new TGeoTube("VACUUM_VESSEL_TUBEsh", mVacuumVesselRIn, mVacuumVesselRIn + mVacuumVesselThick, mVacuumVesselLength / 2.); + TGeoTube* vacuumVesselWall = new TGeoTube("VACUUM_VESSEL_WALLsh", mPipeRIn, mVacuumVesselRIn + mVacuumVesselThick, mVacuumVesselThick / 2.); + + // Pipe and vacuum vessel positions + TGeoTranslation* posVacuumVesselWallNegZSide = new TGeoTranslation("WALLNEGZ", 0, 0, -mVacuumVesselLength / 2. - mVacuumVesselThick / 2.); + posVacuumVesselWallNegZSide->RegisterYourself(); + TGeoTranslation* posVacuumVesselWallPosZSide = new TGeoTranslation("WALLPOSZ", 0, 0, mVacuumVesselLength / 2. + mVacuumVesselThick / 2.); + posVacuumVesselWallPosZSide->RegisterYourself(); + TGeoTranslation* posPipeNegZSide = new TGeoTranslation("PIPENEGZ", 0, 0, -mVacuumVesselLength / 2. - mVacuumVesselThick - pipeLengthHalf / 2.); + posPipeNegZSide->RegisterYourself(); + TGeoTranslation* posPipePosZSide = new TGeoTranslation("PIPEPOSZ", 0, 0, mVacuumVesselLength / 2. + mVacuumVesselThick + pipeLengthHalf / 2.); + posPipePosZSide->RegisterYourself(); + + // Pipe composite shape and volume + TString pipeCompositeFormula = + "VACUUM_VESSEL_WALLsh:WALLNEGZ" + "+VACUUM_VESSEL_WALLsh:WALLPOSZ" + "+VACUUM_VESSEL_TUBEsh" + "+PIPEsh:PIPEPOSZ" + "+PIPEsh:PIPENEGZ"; + + if (subtractorsFormula.Length()) { LOG(info) << "Subtractors formula before : " << subtractorsFormula; subtractorsFormula = Form("-(%s)", subtractorsFormula.Data()); LOG(info) << "Subtractors formula after: " << subtractorsFormula; - outerBerylliumTubeVacuumComposite = new TGeoCompositeShape("OUT_PIPEVACUUMsh", (compositeFormula + subtractorsFormula).Data()); - outerBerylliumTubeVacuumVolume = new TGeoVolume("OUT_PIPEVACUUM", outerBerylliumTubeVacuumComposite, kMedVac); + vacuumComposite = new TGeoCompositeShape("VACUUM_BASEsh", (compositeFormula + subtractorsFormula).Data()); + vacuumVolume = new TGeoVolume("VACUUM_BASE", vacuumComposite, kMedVac); } else { - outerBerylliumTubeVacuumVolume = new TGeoVolume("OUT_PIPEVACUUM", outerBerylliumTubeVacuumBase, kMedVac); + vacuumComposite = new TGeoCompositeShape("VACUUM_BASEsh", compositeFormula.Data()); + vacuumVolume = new TGeoVolume("VACUUM_BASE", vacuumComposite, kMedVac); } - outerBerylliumTubeVacuumVolume->SetVisibility(1); - outerBerylliumTubeVacuumVolume->SetTransparency(50); - outerBerylliumTubeVacuumVolume->SetLineColor(kGreen); - - // outerBeTubeVolume->AddNode(outerBerylliumTubeVacuumVolume, 1, gGeoIdentity); - barrel->AddNode(outerBerylliumTubeVacuumVolume, 1, new TGeoTranslation(0, 30.f, 0)); - - barrel->AddNode(outerBeTubeVolume, 1, new TGeoTranslation(0, 30.f, 0)); // Add to surrounding geometry - - //---------------- Innermost Be pipe around the IP ---------- - TGeoTube* innerBeTube = - new TGeoTube("INN_PIPEsh", mBeInnerPipeRmin, mBeInnerPipeRmin + mBeInnerPipeThick, mInnerIpHLength); - TGeoVolume* innerBeTubeVolume = new TGeoVolume("INN_PIPE", innerBeTube, kMedBe); - innerBeTubeVolume->SetLineColor(kGreen - 9); + TGeoCompositeShape* pipeComposite = new TGeoCompositeShape("A3IPsh", pipeCompositeFormula); + TGeoVolume* pipeVolume = new TGeoVolume("A3IP", pipeComposite, kMedBe); - TGeoTube* berylliumTubeVacuum = - new TGeoTube("INN_PIPEVACUUMsh", 0., mBeInnerPipeRmin, mInnerIpHLength); - TGeoVolume* innerBerylliumTubeVacuumVolume = new TGeoVolume("INN_PIPEVACUUM", berylliumTubeVacuum, kMedVac); - innerBerylliumTubeVacuumVolume->SetVisibility(1); - innerBerylliumTubeVacuumVolume->SetLineColor(kGreen); + // Add everything to the barrel + barrel->AddNode(vacuumVolume, 1, new TGeoTranslation(0, 30.f, 0)); + barrel->AddNode(pipeVolume, 1, new TGeoTranslation(0, 30.f, 0)); - barrel->AddNode(innerBeTubeVolume, 1, new TGeoTranslation(0, 30.f, 0)); - barrel->AddNode(innerBerylliumTubeVacuumVolume, 1, new TGeoTranslation(0, 30.f, 0)); + vacuumVolume->SetLineColor(kGreen + 3); + pipeVolume->SetLineColor(kGreen + 3); } void Alice3Pipe::createMaterials() diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h index 129fb74d38867..563a97d8f0a53 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKServices.h @@ -56,9 +56,9 @@ class TRKServices : public FairModule protected: // Coldplate - float mColdPlateRMin; - float mColdPlateZLength; - float mColdPlateThickness; + float mColdPlateRMin; // cm + float mColdPlateZLength; // cm + float mColdPlateThickness; // cm float mColdPlateX0; // Services @@ -70,6 +70,11 @@ class TRKServices : public FairModule float mMiddleDiskThickness = 1.0; // cm std::vector mCableFanWeights = {0.5, 0.3, 0.2}; // relative weights of the fan layers + // IRIS vacuum vessel + float mRInIRISVacV; // cm + float mROutIRISVacV; // cm + float mZLengthIRISVacV; // cm + float mThicknessIRISVacV; // cm ClassDefOverride(TRKServices, 1); }; } // namespace trk diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 5e46e791cf6b9..db326eba84091 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -77,10 +77,10 @@ void Detector::configDefault() mLayers.clear(); LOGP(warning, "Loading default configuration for ALICE3 TRK"); - mLayers.emplace_back(0, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(0)}, 0.55f, 50.f, 100.e-4); // Adjusted rmin not to overlap with inner BP + mLayers.emplace_back(0, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(0)}, 0.5f, 50.f, 100.e-4); mLayers.emplace_back(1, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(1)}, 1.2f, 50.f, 100.e-4); mLayers.emplace_back(2, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(2)}, 2.5f, 50.f, 100.e-4); - mLayers.emplace_back(3, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(3)}, 3.78f, 124.f, 100.e-3); // Adjusted rmin not to overlap with outer BP + mLayers.emplace_back(3, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(3)}, 3.78f, 124.f, 100.e-3); mLayers.emplace_back(4, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(4)}, 7.f, 124.f, 100.e-3); mLayers.emplace_back(5, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(5)}, 12.f, 124.f, 100.e-3); mLayers.emplace_back(6, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(6)}, 20.f, 124.f, 100.e-3); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx index 99d7bee98f56b..3c1426b431f17 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,10 @@ TRKServices::TRKServices(float rMin, float zLength, float thickness) mColdPlateRMin = rMin; mColdPlateZLength = zLength; mColdPlateThickness = thickness; + mZLengthIRISVacV = 70.; + mThicknessIRISVacV = 150.e-4; + mRInIRISVacV = 0.48; + mROutIRISVacV = mColdPlateRMin + mColdPlateThickness; } void TRKServices::createMaterials() @@ -83,6 +88,22 @@ void TRKServices::createMaterials() float wPolyurethane[4] = {0.017077588, 0.237314387, 0.203327619, 0.542280405}; float dPolyurethane = 1.25; + // Aluminium 5083 - alloy of Mn, Fe, Cu, Mg, Si, Zn, Cr, Ti, Al + // Al5083 is considered as material for the iris vacuum vessel + // https://www.smithmetal.com/5083.htm + float aAl5083[9] = {54.938, 55.845, 63.546, 24.305, 28.086, 65.38, 51.996, 47.867, 26.982}; + float zAl5083[9] = {25., 26., 29., 12., 14., 30., 24., 22., 13.}; + // The concentration of certain metals in Al5083 have a range. What will be used for the alloy for the iris vacuum vessel will have to be checked + float wAl5083[9] = {0.007, 0.004, 0.001, 0.0445, 0.004, 0.0025, 0.0015, 0.0015, 0.934}; + float dAl5083 = 2.650; + + // AlBeMet AM162H is a nanocomposite, not an alloy + // Considered here as well https://indico.cern.ch/event/1168385/contributions/5355805/attachments/2681743/4652030/Jul%2010%201030-1045%20AM%20(Hawaii)%20M1Or1C-05%20AlBeMet.pdf + float aAlBeMet[2] = {26.982, 9.012}; + float zAlBeMet[2] = {13., 4.}; + float wAlBeMet[2] = {0.38, 0.62}; + float dAlBeMet = 2.071; + matmgr.Mixture("ALICE3_TRKSERVICES", 66, "CERAMIC", aCer, zCer, dCer, 2, wCer); // Ceramic for cold plate matmgr.Mixture("ALICE3_TRKSERVICES", 68, "AIR", aAir, zAir, dAir, 4, wAir); // Air for placeholding cables matmgr.Mixture("ALICE3_TRKSERVICES", 69, "POLYETHYLENE", aPolyethylene, zPolyethylene, .95, 2, wPolyethylene); // Polyethylene for fibers @@ -90,6 +111,9 @@ void TRKServices::createMaterials() matmgr.Mixture("ALICE3_TRKSERVICES", 71, "SILICONDIOXIDE", aSiO2, zSiO2, dSiO2, 2, wSiO2); // Fused silica SiO2 matmgr.Mixture("ALICE3_TRKSERVICES", 72, "WATER", aWater, zWater, dWater, 2, wWater); // Water for cooling pipes matmgr.Material("ALICE3_TRKSERVICES", 67, "COPPER", 63.546, 29, 8.96, 1.43, 15.1); // Copper for cables + matmgr.Material("ALICE3_TRKSERVICES", 73, "BERYLLIUM", 9.01, 4., 1.848, 35.3, 36.7); // Beryllium - Candidate for IRIS vacuum vessel + matmgr.Mixture("ALICE3_TRKSERVICES", 74, "ALUMINIUM5083", aAl5083, zAl5083, dAl5083, 9, wAl5083); // AL5083 - Candidate for IRIS vacuum vessel + matmgr.Mixture("ALICE3_TRKSERVICES", 75, "ALUMINIUM-BERYLLIUM-METAL", aAlBeMet, zAlBeMet, dAlBeMet, 2, wAlBeMet); // Aluminium-Beryllium-metal - Candidate for IRIS vacuum vessel // Danger zone: following mixtures do not use the interface of MaterialManager // TGeoMixture* fiber = new TGeoMixture("ALICE3_TRKSERVICES_FIBER", 2 /*nel*/); @@ -104,13 +128,16 @@ void TRKServices::createMaterials() // coolingBundle->AddElement(gGeoManager->GetMaterial("POLYURETHANE"), 0.56); // coolingBundle->AddElement(gGeoManager->GetMaterial("WATER"), 0.44); - matmgr.Medium("ALICE3_TRKSERVICES", 1, "CERAMIC", 66, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Ceramic for cold plate - matmgr.Medium("ALICE3_TRKSERVICES", 2, "COPPER", 67, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Copper for cables - matmgr.Medium("ALICE3_TRKSERVICES", 3, "AIR", 68, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Air for placeholding cables - matmgr.Medium("ALICE3_TRKSERVICES", 4, "POLYETHYLENE", 69, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Polyethylene for fibers - matmgr.Medium("ALICE3_TRKSERVICES", 5, "POLYURETHANE", 70, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Polyurethane for cooling pipes - matmgr.Medium("ALICE3_TRKSERVICES", 6, "SILICONDIOXIDE", 71, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Fused silica SiO2 - matmgr.Medium("ALICE3_TRKSERVICES", 7, "WATER", 72, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Water for cooling pipes + matmgr.Medium("ALICE3_TRKSERVICES", 1, "CERAMIC", 66, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Ceramic for cold plate + matmgr.Medium("ALICE3_TRKSERVICES", 2, "COPPER", 67, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Copper for cables + matmgr.Medium("ALICE3_TRKSERVICES", 3, "AIR", 68, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Air for placeholding cables + matmgr.Medium("ALICE3_TRKSERVICES", 4, "POLYETHYLENE", 69, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Polyethylene for fibers + matmgr.Medium("ALICE3_TRKSERVICES", 5, "POLYURETHANE", 70, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Polyurethane for cooling pipes + matmgr.Medium("ALICE3_TRKSERVICES", 6, "SILICONDIOXIDE", 71, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Fused silica SiO2 + matmgr.Medium("ALICE3_TRKSERVICES", 7, "WATER", 72, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Water for cooling pipes + matmgr.Medium("ALICE3_TRKSERVICES", 8, "BERYLLIUM", 73, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Beryllium for IRIS vacuum vessel + matmgr.Medium("ALICE3_TRKSERVICES", 9, "ALUMINIUM5083", 74, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // Al5083 for IRIS vacuum vessel + matmgr.Medium("ALICE3_TRKSERVICES", 10, "ALUMINIUM-BERYLLIUM-METAL", 75, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin); // AlBeMet for IRIS vacuum vessel } void TRKServices::createServices(TGeoVolume* motherVolume) @@ -136,6 +163,31 @@ void TRKServices::createColdplate(TGeoVolume* motherVolume) LOGP(info, "Inserting {} in {} ", coldPlateVolume->GetName(), motherVolume->GetName()); motherVolume->AddNode(coldPlateVolume, 1, nullptr); + + // IRIS Tracker Vacuum Vessel + TGeoTube* irisVacuumVesselInnerTube = new TGeoTube("TRK_IRISVACUUMVESSEL_INNERTUBEsh", mRInIRISVacV, mRInIRISVacV + mThicknessIRISVacV, mZLengthIRISVacV / 2.); + TGeoTube* irisVacuumVesselOuterTube = new TGeoTube("TRK_IRISVACUUMVESSEL_OUTERTUBEsh", mROutIRISVacV, mROutIRISVacV + mThicknessIRISVacV, mZLengthIRISVacV / 2.); + TGeoTube* irisVacuumVesselWall = new TGeoTube("TRK_IRISVACUUMVESSEL_WALLsh", mRInIRISVacV, mROutIRISVacV + mThicknessIRISVacV, mThicknessIRISVacV / 2.); + TGeoTranslation* irisVacVWallNegZ = new TGeoTranslation("IRISVACVWALLNEGZ", 0., 0., -mZLengthIRISVacV / 2. - mThicknessIRISVacV / 2.); + irisVacVWallNegZ->RegisterYourself(); + TGeoTranslation* irisVacVWallPosZ = new TGeoTranslation("IRISVACVWALLPOSZ", 0., 0., mZLengthIRISVacV / 2. + mThicknessIRISVacV / 2.); + irisVacVWallPosZ->RegisterYourself(); + TString irisCompositeFormula = + "TRK_IRISVACUUMVESSEL_INNERTUBEsh" + "+TRK_IRISVACUUMVESSEL_OUTERTUBEsh" + "+TRK_IRISVACUUMVESSEL_WALLsh:IRISVACVWALLNEGZ" + "+TRK_IRISVACUUMVESSEL_WALLsh:IRISVACVWALLPOSZ"; + TGeoCompositeShape* irisVacuumVesselComposite = new TGeoCompositeShape("TRK_IRISVACUUMVESSELsh", irisCompositeFormula); + + const TGeoMedium* medBe = matmgr.getTGeoMedium("ALICE3_TRKSERVICES_BERYLLIUM"); + TGeoVolume* irisVacuumVesselVolume = new TGeoVolume("TRK_IRISVACUUMVESSEL", irisVacuumVesselComposite, medBe); + + irisVacuumVesselVolume->SetVisibility(1); + irisVacuumVesselVolume->SetLineColor(kGreen); + + LOGP(info, "Creating IRIS Tracker vacuum vessel"); + LOGP(info, "Inserting {} in {} ", irisVacuumVesselVolume->GetName(), motherVolume->GetName()); + motherVolume->AddNode(irisVacuumVesselVolume, 1, nullptr); } void TRKServices::createOuterDisksServices(TGeoVolume* motherVolume) diff --git a/macro/build_geometry.C b/macro/build_geometry.C index eb996d0482640..ba41be9ed66ae 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -164,7 +164,7 @@ void build_geometry(FairRunSim* run = nullptr) #ifdef ENABLE_UPGRADES // upgraded beampipe at the interaction point (IP) if (isActivated("A3IP")) { - run->AddModule(new o2::passive::Alice3Pipe("A3IP", "Alice 3 beam pipe", !isActivated("TRK"), 0.48f, 0.025f, 2000.f, 3.7f, 0.08f, 2000.f)); + run->AddModule(new o2::passive::Alice3Pipe("A3IP", "Alice 3 beam pipe", !isActivated("TRK"), !isActivated("FT3"), 1.8f, 0.08f, 1000.f, 3.7f, 0.08f, 76.f)); } // the absorber From dbba97303d67290c82b500fb7421bb4c8e240495 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 15 Feb 2024 18:46:40 +0100 Subject: [PATCH 44/50] Do not add o2-tfidinfo-writer-workflow with input from readers --- prodtests/full-system-test/dpl-workflow.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 88eabad09bcb1..8fe075da30934 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -457,9 +457,11 @@ if [[ ! -z $INPUT_DETECTOR_LIST ]]; then fi fi -# if root output is requested, record info of processed TFs DataHeader for replay of root files -ROOT_OUTPUT_ASKED=`declare -p | cut -d' ' -f3 | cut -d'=' -f1 | grep ENABLE_ROOT_OUTPUT_` -[[ -z "$DISABLE_ROOT_OUTPUT" ]] || [[ ! -z $ROOT_OUTPUT_ASKED ]] && add_W o2-tfidinfo-writer-workflow +if [[ -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] && [[ -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS} ]]; then + # if root output is requested, record info of processed TFs DataHeader for replay of root files + ROOT_OUTPUT_ASKED=`declare -p | cut -d' ' -f3 | cut -d'=' -f1 | grep ENABLE_ROOT_OUTPUT_` + [[ -z "$DISABLE_ROOT_OUTPUT" ]] || [[ ! -z $ROOT_OUTPUT_ASKED ]] && add_W o2-tfidinfo-writer-workflow +fi # if TPC correction with IDC from CCDB was requested has_detector TPC && [[ ${NEED_TPC_SCALERS_WF:-} == 1 ]] && add_W o2-tpc-scaler-workflow " ${TPC_SCALERS_CONF:-} " From 81c9393ec0eff8e327de007987803129e5b73172 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 15 Feb 2024 18:47:34 +0100 Subject: [PATCH 45/50] Fix missing HBFUtilsInitialize plugins in various reader workflows --- .../workflow/src/recpoints-reader-workflow.cxx | 10 ++++++++++ .../workflow/src/digit-reader-workflow.cxx | 10 +++++++++- .../Workflow/src/tracks-reader-workflow.cxx | 18 +++++++++++++++--- .../workflow/io/src/digit-reader-workflow.cxx | 6 ++++++ .../io/src/trd-track-reader-workflow.cxx | 9 ++++++++- .../workflow/src/digits-reader-workflow.cxx | 7 +++++++ 6 files changed, 55 insertions(+), 5 deletions(-) diff --git a/Detectors/FIT/FT0/workflow/src/recpoints-reader-workflow.cxx b/Detectors/FIT/FT0/workflow/src/recpoints-reader-workflow.cxx index 376a8385941ce..d323b4135d7ea 100644 --- a/Detectors/FIT/FT0/workflow/src/recpoints-reader-workflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/recpoints-reader-workflow.cxx @@ -16,13 +16,20 @@ #include "Framework/CallbackService.h" #include "Framework/ControlService.h" +#include "Framework/CallbacksPolicy.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/Task.h" #include "FT0Workflow/RecPointReaderSpec.h" #include "CommonUtils/ConfigurableParam.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" using namespace o2::framework; +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) { @@ -32,6 +39,7 @@ void customize(std::vector& workflowOptions) {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}}; std::string keyvaluehelp("Semicolon separated key=value strings"); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); + o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -43,5 +51,7 @@ WorkflowSpec defineDataProcessing(const ConfigContext& ctx) o2::conf::ConfigurableParam::updateFromString(ctx.options().get("configKeyValues")); DataProcessorSpec producer = o2::ft0::getRecPointReaderSpec(ctx.options().get("disable-mc")); specs.push_back(producer); + // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit + o2::raw::HBFUtilsInitializer hbfIni(ctx, specs); return specs; } diff --git a/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx b/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx index 7fc7e285ac99e..71b4b82a14126 100644 --- a/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx +++ b/Detectors/ITSMFT/common/workflow/src/digit-reader-workflow.cxx @@ -12,11 +12,18 @@ #include "ITSMFTWorkflow/DigitReaderSpec.h" #include "CommonUtils/ConfigurableParam.h" #include "Framework/ConfigParamSpec.h" +#include "Framework/CallbacksPolicy.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" using namespace o2::framework; // ------------------------------------------------------------------ +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) { @@ -27,7 +34,7 @@ void customize(std::vector& workflowOptions) ConfigParamSpec{"runmft", VariantType::Bool, false, {"expect MFT data"}}, ConfigParamSpec{"suppress-triggers-output", VariantType::Bool, false, {"suppress dummy triggers output"}}, ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}}; - + o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -49,5 +56,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) } else { wf.emplace_back(o2::itsmft::getITSDigitReaderSpec(useMC, calib, withTriggers)); } + o2::raw::HBFUtilsInitializer hbfIni(cfgc, wf); return wf; } diff --git a/Detectors/MUON/MID/Workflow/src/tracks-reader-workflow.cxx b/Detectors/MUON/MID/Workflow/src/tracks-reader-workflow.cxx index b7a9e47b3f98e..6c61656b95e50 100644 --- a/Detectors/MUON/MID/Workflow/src/tracks-reader-workflow.cxx +++ b/Detectors/MUON/MID/Workflow/src/tracks-reader-workflow.cxx @@ -15,16 +15,25 @@ #include #include "Framework/ConfigParamSpec.h" +#include "Framework/CallbacksPolicy.h" #include "MIDWorkflow/TrackReaderSpec.h" #include "CommonUtils/ConfigurableParam.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" using namespace o2::framework; +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) { - workflowOptions.emplace_back("disable-mc", VariantType::Bool, false, ConfigParamSpec::HelpString{"Disable MC info"}); - workflowOptions.emplace_back("configKeyValues", VariantType::String, "", ConfigParamSpec::HelpString{"Semicolon separated key=value strings ..."}); + std::vector options{{"disable-mc", VariantType::Bool, false, ConfigParamSpec::HelpString{"Disable MC info"}}, + {"configKeyValues", VariantType::String, "", ConfigParamSpec::HelpString{"Semicolon separated key=value strings ..."}}}; + o2::raw::HBFUtilsInitializer::addConfigOption(options); + std::swap(workflowOptions, options); } #include "Framework/runDataProcessing.h" @@ -32,5 +41,8 @@ void customize(std::vector& workflowOptions) WorkflowSpec defineDataProcessing(const ConfigContext& config) { bool useMC = !config.options().get("disable-mc"); - return WorkflowSpec{o2::mid::getTrackReaderSpec(useMC)}; + WorkflowSpec specs{o2::mid::getTrackReaderSpec(useMC)}; + // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit + o2::raw::HBFUtilsInitializer hbfIni(config, specs); + return specs; } diff --git a/Detectors/TRD/workflow/io/src/digit-reader-workflow.cxx b/Detectors/TRD/workflow/io/src/digit-reader-workflow.cxx index 1754de641d903..b6059ecf8e9fb 100644 --- a/Detectors/TRD/workflow/io/src/digit-reader-workflow.cxx +++ b/Detectors/TRD/workflow/io/src/digit-reader-workflow.cxx @@ -18,6 +18,11 @@ using namespace o2::framework; // ------------------------------------------------------------------ +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) { @@ -45,5 +50,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto dataSubspec = configcontext.options().get("digit-subspec"); WorkflowSpec specs; specs.emplace_back(o2::trd::getTRDDigitReaderSpec(useMC, sendTriggerRecords, dataSubspec)); + o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); return specs; } diff --git a/Detectors/TRD/workflow/io/src/trd-track-reader-workflow.cxx b/Detectors/TRD/workflow/io/src/trd-track-reader-workflow.cxx index 38247cfdfae44..e4305ee30fa19 100644 --- a/Detectors/TRD/workflow/io/src/trd-track-reader-workflow.cxx +++ b/Detectors/TRD/workflow/io/src/trd-track-reader-workflow.cxx @@ -14,12 +14,18 @@ #include "Framework/ConfigParamSpec.h" #include "TRDWorkflowIO/TRDTrackReaderSpec.h" #include "ReconstructionDataFormats/GlobalTrackID.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" using namespace o2::framework; using GTrackID = o2::dataformats::GlobalTrackID; // ------------------------------------------------------------------ +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) { @@ -29,7 +35,7 @@ void customize(std::vector& workflowOptions) {"track-types", VariantType::String, std::string{GTrackID::ALL}, {"comma-separated list of sources to use for tracking"}}, {"output-strict", o2::framework::VariantType::Bool, false, {"outputs specs should correspond to strict matching mode"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; - + o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -58,5 +64,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (GTrackID::includesSource(GTrackID::Source::TPCTRD, srcTRD)) { specs.emplace_back(o2::trd::getTRDTPCTrackReaderSpec(useMC, configcontext.options().get("output-strict"))); } + o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); return specs; } diff --git a/Detectors/ZDC/workflow/src/digits-reader-workflow.cxx b/Detectors/ZDC/workflow/src/digits-reader-workflow.cxx index 81e6f1f1ac3cf..0501d46cf6be5 100644 --- a/Detectors/ZDC/workflow/src/digits-reader-workflow.cxx +++ b/Detectors/ZDC/workflow/src/digits-reader-workflow.cxx @@ -16,6 +16,7 @@ #include "Framework/CallbackService.h" #include "Framework/ControlService.h" +#include "Framework/CallbacksPolicy.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/Task.h" #include "ZDCWorkflow/DigitReaderSpec.h" @@ -24,6 +25,11 @@ using namespace o2::framework; +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) { @@ -34,6 +40,7 @@ void customize(std::vector& workflowOptions) std::string keyvaluehelp("Semicolon separated key=value strings"); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {keyvaluehelp}}); + o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } From 4ae651c75237e785e42edcf76ec4e017024d8bcf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 15 Feb 2024 10:44:11 +0100 Subject: [PATCH 46/50] DPL: allow extracting data from processing context directly using arguments --- .../TPC/workflow/src/FileReaderWorkflow.cxx | 20 ++++---- .../Core/include/Framework/AlgorithmSpec.h | 48 +++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx b/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx index c50b5685cdcd0..091674b447105 100644 --- a/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx +++ b/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx @@ -38,13 +38,13 @@ void customize(std::vector& workflowOptions) using namespace o2::framework; -enum struct Input { Clusters, - Tracks +enum struct InputType { Clusters, + Tracks }; -const std::unordered_map InputMap{ - {"clusters", Input::Clusters}, - {"tracks", Input::Tracks}}; +const std::unordered_map InputMap{ + {"clusters", InputType::Clusters}, + {"tracks", InputType::Tracks}}; /// MC info is processed by default, disabled by using command line option `--disable-mc` /// @@ -56,24 +56,24 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) auto inputType = cfgc.options().get("input-type"); bool doMC = not cfgc.options().get("disable-mc"); - std::vector