25#include <TStopwatch.h>
58#include <TLegendEntry.h>
90 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mDrawOnly(drawOnly), mPostProcOnly(postProcOnly)
102 bool refitPV(
o2::dataformats::PrimaryVertex& pv,
int vid);
104 bool processITSTrack(const
o2::its::
TrackITS& iTrack, const
o2::dataformats::PrimaryVertex& pv,
o2::checkresid::
Track& resTrack,
o2::track::
PID pid);
106 void fillHistos(const
o2::checkresid::
Track& trc);
107 void postProcessHistos();
110 o2::itsmft::ChipMappingITS mChipMap;
111 o2::globaltracking::RecoContainer* mRecoData =
nullptr;
113 bool mMeanVertexUpdated = false;
114 float mITSROFrameLengthMUS = 0.
f;
115 o2::dataformats::MeanVertexObject mMeanVtx{};
117 std::vector<int16_t> mITSClusterSizes;
120 std::shared_ptr<DataRequest> mDataRequest;
121 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
122 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
125 bool mDrawOnly =
false;
126 bool mPostProcOnly =
false;
128 bool mFillHistos =
true;
129 bool mFillTree =
true;
130 std::vector<std::unique_ptr<o2::HistoManager>> mHManV{};
131 std::vector<o2::dataformats::PrimaryVertex> mPVUsed;
139 mDraw = ic.
options().
get<
bool>(
"draw-report");
140 mFillHistos = !ic.
options().
get<
bool>(
"no-hist");
141 mFillTree = !ic.
options().
get<
bool>(
"no-tree");
142 mNThreads = ic.
options().
get<
int>(
"nthreads");
147 std::string nm =
params.outname;
154 if (!mDrawOnly && mFillHistos) {
157 if (!
params.ext_hm_list.empty()) {
161 if (vecNames.size() != vecLegends.size()) {
162 LOGP(warn,
"{} legend names provided for {} external histomanagers, will use file names as legends", vecLegends.size(), vecNames.size());
166 for (
const auto& vn : vecNames) {
167 LOGP(info,
"Loading external HistoManager {}", vn);
168 mHManV.emplace_back() = std::make_unique<o2::HistoManager>(
"", vn,
true);
169 auto hm = mHManV.back().get();
171 LOGP(error,
"Failed to load histograms from {}", vn);
174 hm->SetName(useLeg ? vecLegends[cntH].c_str() : vn.c_str());
185 LOGP(warn,
"No OpenMP");
190 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(fmt::format(
"{}.root",
params.outname).c_str(),
"recreate");
208 for (
const auto& hm : mHManV) {
219 mRecoData = &recoData;
221 mRecoData = &recoData;
222 updateTimeDependentParams(pc);
231 static bool initOnceDone =
false;
238 if (!grp->isDetContinuousReadOut(DetID::ITS)) {
239 mITSROFrameLengthMUS = alpParams.roFrameLengthTrig / 1.e3;
241 mITSROFrameLengthMUS = alpParams.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS * 1e-3;
244 geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G, o2::math_utils::TransformType::T2G));
248 if (mMeanVertexUpdated) {
249 mMeanVertexUpdated =
false;
258 LOGP(fatal,
"ITS data is not loaded");
265 mITSClustersArray.
init(nLr);
266 mITSClusterSizes.clear();
267 for (
int lr = 0; lr < nLr; lr++) {
273 mITSClustersArray.
getClusters().reserve(mITSClustersArray.
size() + clusITS.size());
274 mITSClusterSizes.reserve(mITSClusterSizes.size() + clusITS.size());
275 for (
const auto&
clu : clusITS) {
276 const auto pattID =
clu.getPatternID();
279 mITSClusterSizes.emplace_back(patt.
getNPixels());
281 mITSClusterSizes.emplace_back(mITSDict->
getNpixels(pattID));
293 static int TFCount = 0;
294 int nv = vtxRefs.size() - 1;
295 std::vector<std::vector<checkresid::Track>> slots;
297 slots.resize(mNThreads);
298 int nvGood = 0, nvUse = 0, nvRefFail = 0;
299 long pvFitDuration{};
300 for (
int iv = 0; iv < nv; iv++) {
301 const auto& vtref = vtxRefs[iv];
302 auto pve = pvvec[iv];
303 if (pve.getNContributors() <
params.minPVContributors) {
308 LOGP(
debug,
"Refitting PV#{} of {} tracks", iv, pve.getNContributors());
309 auto tStartPVF = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
310 bool res = refitPV(pve, iv);
311 pvFitDuration += std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count() - tStartPVF;
318 mPVUsed.push_back(pve);
319 const auto& itsContRefs = vtref.getITSGloContributors();
320 int idMinITSGlo = 0, idMaxITSGlo = 0;
321 if (
params.useITSGloContributors) {
322 if (itsContRefs.getFirstEntry() < vtref.getEntries() && itsContRefs.getEntries() == 0) {
323 LOGP(fatal,
"Usage of stored ITS global contributors is requested but they are missing");
325 idMinITSGlo = itsContRefs.getFirstEntry();
326 idMaxITSGlo = idMinITSGlo + itsContRefs.getEntries();
333 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
335 if (!dm[DetID::ITS]) {
339#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
341 for (
int i = idMin;
i < idMax;
i++) {
342 auto vid = trackIndex[
i];
343 bool pvCont = vid.isPVContributor();
344 if (!pvCont && (
params.pvcontribOnly ||
params.useITSGloContributors)) {
349 if (
params.useITSGloContributors) {
350 int id = idMinITSGlo + cntPVCont;
351 if (
id >= idMaxITSGlo) {
352 LOGP(fatal,
"Calculated GlobalContributor ITS track index {} exceeds number of stored indices {}",
id, itsContRefs.getEntries());
354 pidITS = trackIndex[
id].getSource();
363 const auto& itsTrack = mRecoData->
getITSTrack(gidITS);
364 if (itsTrack.getNClusters() <
params.minITSCl) {
368 if (!
params.useITSGloContributors) {
369 pidITS = trc.getPID();
371 auto pt = trc.getPt();
372 if (pt < params.minPt || pt >
params.maxPt) {
375 if (std::abs(trc.getTgl()) >
params.maxTgl) {
379 auto& accum = slots[omp_get_thread_num()];
381 auto& accum = slots[0];
383 auto& resTrack = accum.emplace_back();
385 if (!processITSTrack(itsTrack, pve, resTrack, pidITS)) {
393 for (
const auto& accum : slots) {
394 for (
const auto& tr : accum) {
396 (*mDBGOut) <<
"res" <<
"tr=" << tr <<
"\n";
404 (*mDBGOut) <<
"pvUsed" <<
"pv=" << mPVUsed <<
"\n";
407 for (
const auto& pv : mPVUsed) {
408 mHMan->
getHisto(20000 + 0)->Fill(pv.getX());
409 mHMan->
getHisto(20000 + 1)->Fill(pv.getY());
410 mHMan->
getHisto(20000 + 2)->Fill(pv.getZ());
411 mHMan->
getHisto(20000 + 3)->Fill(pv.getNContributors());
414 LOGP(info,
"processed {} PVs out of {} good vertices (out of {} in total), PV refits took {} mus, {} refits failed", nvUse, nvGood, nv, pvFitDuration, nvRefFail);
421 auto trFitInw = iTrack.getParamOut();
422 auto trFitOut = iTrack.getParamIn();
423 trFitInw.setPID(pid);
424 trFitOut.setPID(pid);
428 float bz = prop->getNominalBz();
429 std::array<const o2::BaseCluster<float>*, 8> clArr{};
430 std::array<int16_t, 8> clSizeArr{};
432 std::array<o2::track::TrackParCov, 8> extrapOut, extrapInw;
436 return refLin ? tr.rotate(
alpha, *refLin, bz) : tr.rotate(
alpha);
441 if (!rotateTrack(tr,
i == 0 ? pvAlpha : geom->getSensorRefAlpha(clArr[
i]->
getSensorID()), refLin) ||
442 !prop->propagateTo(tr, refLin, clArr[
i]->
getX(),
true)) {
446 if (!tr.update(*clArr[
i])) {
450 extrapDest[
i].invalidate();
456 auto inv2d = [](
float s00,
float s11,
float s01) -> std::array<float, 3> {
457 auto det = s00 * s11 - s01 * s01;
459 LOGP(error,
"Singular det {}, input: {} {} {}", det, s00, s11, s01);
460 return {0.f, 0.f, 0.f};
463 return {s11 * det, s00 * det, -s01 * det};
467 if (!prop->propagateToDCA(pv, trFitOut, bz)) {
468 LOGP(
debug,
"Failed to propagateToDCA, {}", trFitOut.asString());
472 if (
params.addPVAsCluster) {
473 float cosAlp, sinAlp;
474 pvAlpha = trFitOut.getAlpha();
475 o2::math_utils::sincos(trFitOut.getAlpha(), sinAlp, cosAlp);
476 bcPV.
setXYZ(pv.getX() * cosAlp + pv.getY() * sinAlp, -pv.getX() * sinAlp + pv.getY() * cosAlp, pv.getZ());
477 bcPV.
setSigmaY2(0.5 * (pv.getSigmaX2() + pv.getSigmaY2()));
483 int nCl = iTrack.getNClusters();
484 for (
int i = 0;
i <
nCl;
i++) {
485 const auto& curClu = mITSClustersArray[itsClRefs[iTrack.
getClusterEntry(
i)]];
487 int llr = geom->getLayer(curClu.getSensorID());
488 if (clArr[1 + llr]) {
489 LOGP(error,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), curClu.getSensorID());
491 clArr[1 + geom->getLayer(curClu.getSensorID())] = &curClu;
492 clSizeArr[1 + geom->getLayer(curClu.getSensorID())] = mITSClusterSizes[itsClRefs[iTrack.
getClusterEntry(
i)]];
495 o2::track::TrackPar refLinIBOut0, refLinOBInw0, *refLinOBInw =
nullptr, *refLinIBOut =
nullptr;
496 if (
params.useStableRef) {
497 refLinOut = &(refLinOut0 = trFitOut);
498 refLinInw = &(refLinInw0 = trFitInw);
500 trFitOut.resetCovariance();
501 trFitOut.setCov(trFitOut.getQ2Pt() * trFitOut.getQ2Pt() * trFitOut.getCov()[14], 14);
502 trFitInw.resetCovariance();
503 trFitInw.setCov(trFitInw.getQ2Pt() * trFitInw.getQ2Pt() * trFitInw.getCov()[14], 14);
505 for (
int i = 0;
i <= 7;
i++) {
508 if (!(resOut = accountCluster(
i, extrapOut, trFitOut, refLinOut)) || !(resInw = accountCluster(7 -
i, extrapInw, trFitInw, refLinInw))) {
514 if (
i == 3 && resOut == 1 && resInw == 1 && (
params.doIBOB ||
params.doIBOBresiduals) &&
nCl == 7) {
515 if (
params.doIBOBresiduals) {
516 trIBOutForIOB = trFitOut;
517 trOBInwForIOB = trFitInw;
523 refLinIBOut = &(refLinIBOut0 = refLinOut0);
524 refLinOBInw = &(refLinOBInw0 = refLinInw0);
527 if (!resTrack.
trOBInw.getXatLabR(
params.rCompIBOB, xRref, bz) ||
528 !prop->propagateTo(resTrack.
trOBInw, refLinOBInw, xRref,
true) ||
529 !rotateTrack(resTrack.
trOBInw, resTrack.
trOBInw.getPhiPos(), refLinOBInw) ||
530 !rotateTrack(resTrack.
trIBOut, resTrack.
trOBInw.getAlpha(), refLinIBOut) ||
531 !prop->propagateTo(resTrack.
trIBOut, refLinIBOut, resTrack.
trOBInw.getX(),
true)) {
542 if (!rotateTrack(tr,
alpha,
nullptr) || !prop->propagateTo(tr,
nullptr, clArr[
i]->
getX(),
true)) {
543 return {0.f, 0.f, 0.f, 0.f};
545 return {clArr[
i]->getY() - tr.getY(), clArr[
i]->getZ() - tr.getZ(), tr.getSigmaY2() + clArr[
i]->getSigmaY2(), tr.getSigmaZ2() + clArr[
i]->getSigmaZ2()};
547 bool haveIOBTracks =
params.doIBOBresiduals &&
nCl == 7 && trIBOutForIOB.getX() > 1 && trOBInwForIOB.getX() > 1;
549 bool innerDone =
false;
551 for (
int i = 0;
i <= 7;
i++) {
554 const auto &tInw = extrapInw[
i], &tOut = extrapOut[
i];
555 auto wInw = inv2d(tInw.getSigmaY2(), tInw.getSigmaZ2(), tInw.getSigmaZY());
556 auto wOut = inv2d(tOut.getSigmaY2(), tOut.getSigmaZ2(), tOut.getSigmaZY());
557 if (wInw[0] == 0.f || wOut[0] == 0.f) {
560 std::array<float, 3> wTot = {wInw[0] + wOut[0], wInw[1] + wOut[1], wInw[2] + wOut[2]};
561 auto cTot = inv2d(wTot[0], wTot[1], wTot[2]);
562 auto ywi = wInw[0] * tInw.getY() + wInw[2] * tInw.getZ() + wOut[0] * tOut.getY() + wOut[2] * tOut.getZ();
563 auto zwi = wInw[2] * tInw.getY() + wInw[1] * tInw.getZ() + wOut[2] * tOut.getY() + wOut[1] * tOut.getZ();
564 auto yw = ywi * cTot[0] + zwi * cTot[2];
565 auto zw = ywi * cTot[2] + zwi * cTot[1];
567 auto phi =
i == 0 ? tInw.getPhi() : tInw.getPhiPos();
568 o2::math_utils::bringTo02Pi(phi);
569 std::array<float, 4> iob{0.f, 0.f, 0.f, 0.f};
573 iob = extrapIOB(trOBInwForIOB,
i);
575 iob = extrapIOB(trIBOutForIOB,
i);
578 resTrack.
points.emplace_back(clArr[
i]->
getY() - yw, clArr[
i]->getZ() - zw, cTot[0] + clArr[
i]->getSigmaY2(), cTot[1] + clArr[
i]->getSigmaZ2(),
579 iob[0], iob[1], iob[2], iob[3], phi, clArr[
i]->getZ(), 0.5 * (tInw.getSnp() + tOut.getSnp()), clSizeArr[
i], clArr[
i]->getSensorID(),
i - 1);
581 resTrack.
track = tInw;
585 LOGP(
debug,
"No cluster on lr {}",
i);
595 std::vector<o2::track::TrackParCov>
tracks;
596 std::vector<bool> useTrack;
597 std::vector<GTrackID> gidsITS;
598 int ntr = pv.getNContributors(), ntrIni = ntr;
600 useTrack.reserve(ntr);
601 gidsITS.reserve(ntr);
604 const auto& itsContRefs = vtref.getITSGloContributors();
605 if (
params.useITSGloContributors && itsContRefs.getEntries()) {
606 int itr = itsContRefs.getFirstEntry(), itLim = itr + itsContRefs.getEntries();
607 for (; itr < itLim; itr++) {
608 auto tid = trackIndex[itr];
609 tracks.emplace_back().setPID(tid.getSource());
613 int itr = vtref.getFirstEntry(), itLim = itr + vtref.getEntries();
614 for (; itr < itLim; itr++) {
615 auto tid = trackIndex[itr];
623 useTrack.resize(ntr);
625#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
627 for (
int itr = 0; itr < ntr; itr++) {
628 if (!(useTrack[itr] = refitITStrack(
tracks[itr], gidsITS[itr]))) {
633 for (
auto v : useTrack) {
637 LOGP(warn,
"Abandon vertex refit: NcontribNew = {} vs NcontribOld = {}", ntr, ntrIni);
640 LOGP(
debug,
"Original vtx: Nc:{} {}, chi2={}", pv.getNContributors(), pv.
asString(), pv.getChi2());
643 LOGP(
debug,
"Refitted vtx: Nc:{} {}, chi2={}", ntr, pv.
asString(), pv.getChi2());
644 if (pv.getChi2() < 0.f) {
645 LOGP(warn,
"Failed to refit PV {}", pvSave.asString());
658 track = trkITS.getParamOut();
659 track.resetCovariance();
662 auto nCl = trkITS.getNumberOfClusters();
665 float bz = prop->getNominalBz();
668 for (
int iCl = 0; iCl <
nCl; iCl++) {
669 const auto& cls = mITSClustersArray[itsClRefs[trkITS.getClusterEntry(iCl)]];
670 auto alpha = geom->getSensorRefAlpha(cls.getSensorID());
673 LOGP(
debug,
"refitITStrack failed on propagation to cl#{}, alpha={}, x={} | {}", iCl,
alpha, cls.getX(),
track.asString());
676 if (!
track.update(cls)) {
677 LOGP(
debug,
"refitITStrack failed on update with cl#{}, | {}", iCl,
track.asString());
688 int np = trc.
points.size();
689 auto pt = trc.
track.getPt();
690 if (pt < params.minPt || pt >
params.maxPt) {
693 auto tgl = trc.
track.getTgl();
695 auto fillLayerResid = [&](
int idOffset,
int il,
float phi,
float z,
float dy,
float dz,
float sig2y,
float sig2z) {
696 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100)->Fill(phi, dy);
697 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 1000)->Fill(
z, dy);
698 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 2000)->Fill(pt, dy);
699 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 3000)->Fill(tgl, dy);
701 auto pull = dy / std::sqrt(sig2y);
702 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 5)->Fill(phi, pull);
703 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 5 + 1000)->Fill(
z, pull);
704 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 5 + 2000)->Fill(pt, pull);
705 mHMan->
getHisto2F(idOffset + il * 10 + 0 * 100 + 5 + 3000)->Fill(tgl, pull);
707 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100)->Fill(phi, dz);
708 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 1000)->Fill(
z, dz);
709 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 2000)->Fill(pt, dz);
710 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 3000)->Fill(tgl, dz);
712 auto pull = dz / std::sqrt(sig2z);
713 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 5)->Fill(phi, pull);
714 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 5 + 1000)->Fill(
z, pull);
715 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 5 + 2000)->Fill(pt, pull);
716 mHMan->
getHisto2F(idOffset + il * 10 + 1 * 100 + 5 + 3000)->Fill(tgl, pull);
720 auto fillChipResid = [&](
int idOffset,
int il,
int lr,
int sens,
float dy,
float dz,
float sig2y,
float sig2z) {
721 if (sens >= 0 && geom->getLayer(sens) == lr) {
722 const int halfBarrel = geom->getHalfBarrel(sens);
723 const int chip = geom->getFirstChipIndex(lr) + geom->getChipIdInLayer(sens);
724 const int chipHistoID = idOffset + (2 * il + halfBarrel) * 100 + 15000;
725 if (halfBarrel >= 0 && halfBarrel < 2) {
726 mHMan->
getHisto2F(chipHistoID)->Fill(chip, dy);
727 mHMan->
getHisto2F(chipHistoID + 10)->Fill(chip, dz);
729 mHMan->
getHisto2F(chipHistoID + 5)->Fill(chip, dy / std::sqrt(sig2y));
732 mHMan->
getHisto2F(chipHistoID + 15)->Fill(chip, dz / std::sqrt(sig2z));
738 for (
int ip = 0; ip < np; ip++) {
739 const auto& pnt = trc.
points[ip];
740 int il = pnt.lr >= 0 ? pnt.lr + 1 : 0;
741 fillLayerResid(0, il, pnt.phi, pnt.z, pnt.dy, pnt.dz, pnt.sig2y, pnt.sig2z);
743 fillChipResid(0, il, pnt.lr, pnt.sens, pnt.dy, pnt.dz, pnt.sig2y, pnt.sig2z);
745 if (pnt.sig2yIOB > 0) {
746 fillLayerResid(100000, il, pnt.phi, pnt.z, pnt.dyIOB, pnt.dzIOB, pnt.sig2yIOB, pnt.sig2zIOB);
748 fillChipResid(100000, il, pnt.lr, pnt.sens, pnt.dyIOB, pnt.dzIOB, pnt.sig2yIOB, pnt.sig2zIOB);
754 for (
int ip = 0; ip < 5; ip++) {
758 mHMan->
getHisto2F(12000 + ip * 10)->Fill(pt, d);
760 float sg = trc.
trIBOut.getCovarElem(ip, ip) + trc.
trOBInw.getCovarElem(ip, ip);
762 auto pull = d / std::sqrt(sg);
765 mHMan->
getHisto2F(12000 + ip * 10 + 5)->Fill(pt, pull);
766 mHMan->
getHisto2F(13000 + ip * 10 + 5)->Fill(trc.
track.getTgl(), pull);
772void CheckResidSpec::bookHistos()
775 mHManV.emplace_back() = std::make_unique<o2::HistoManager>(
"", fmt::format(
"{}_hman.root",
params.outname));
776 mHMan = mHManV.back().get();
777 mHMan->SetName(
params.outname.c_str());
778 auto defLogAxis = [](
float xMn,
float xMx,
int nbin) {
779 if (xMn <= 0 || xMx <= xMn || nbin < 2) {
780 LOGP(fatal,
"Wrong log axis request: xmin = {} xmax = {} nbins = {}", xMn, xMx, nbin);
782 auto dx = std::log(xMx / xMn) / nbin;
783 std::vector<double> xax(nbin + 1);
784 for (
int i = 0;
i <= nbin;
i++) {
785 xax[
i] = xMn * std::exp(dx *
i);
789 float minPt = std::max(0.1f,
params.minPt), maxPt = std::min(50.f,
params.maxPt);
790 auto ptax = defLogAxis(minPt, maxPt,
params.nBinsPt);
794 auto bookLayerResidHistos = [&](
int idOffset,
const std::string& suf,
bool bookVtx) {
795 const float dyzScale = idOffset ?
params.IOBScaleFactor : 1.f;
796 for (
int il = bookVtx ? 0 : 1; il < 8; il++) {
797 std::string lrName = il == 0 ?
"Vtx" : fmt::format(
"Lr{}", il - 1);
798 const float maxDYZ =
params.maxDYZ[il] * dyzScale;
799 for (
int iyz = 0; iyz < 2; iyz++) {
800 std::string dname = fmt::format(
"{}{}", iyz == 0 ?
"dy" :
"dz", suf), dtit =
fmt::
format(
"{}{}", iyz == 0 ?
"#DeltaY" :
"#DeltaZ", suf.
empty() ?
"" : (
"_" + suf));
801 auto h2 =
new TH2F(fmt::format(
"{}_{}_{}", dname, lrName,
"phi").c_str(), fmt::format(
"{}_{{{}}} vs {};#phi;{}", dtit, lrName,
"#phi", dtit).c_str(),
params.nBinsPhi, 0, TMath::Pi() * 2,
params.nBinsRes, -maxDYZ, maxDYZ);
802 mHMan->
addHisto(h2, idOffset + il * 10 + iyz * 100);
803 auto h2p =
new TH2F(fmt::format(
"{}_{}_{}_pull", dname, lrName,
"phi").c_str(), fmt::format(
"pull {}_{{{}}} vs {};#phi; pull{}", dtit, lrName,
"phi", dtit).c_str(),
params.nBinsPhi, 0, TMath::Pi() * 2,
params.nBinsRes, -
params.maxPull,
params.maxPull);
804 mHMan->
addHisto(h2p, idOffset + il * 10 + iyz * 100 + 5);
806 auto hz2 =
new TH2F(fmt::format(
"{}_{}_{}", dname, lrName,
"Z").c_str(), fmt::format(
"{}_{{{}}} vs {};Z;{}", dtit, lrName,
"Z", dtit).c_str(),
params.nBinsZ, -
params.zranges[il],
params.zranges[il],
params.nBinsRes, -maxDYZ, maxDYZ);
807 mHMan->
addHisto(hz2, idOffset + il * 10 + iyz * 100 + 1000);
808 auto hz2p =
new TH2F(fmt::format(
"{}_{}_{}_pull", dname, lrName,
"Z").c_str(), fmt::format(
"pull {}_{{{}}} vs {};Z; pull{}", dtit, lrName,
"Z", dtit).c_str(),
params.nBinsZ, -
params.zranges[il],
params.zranges[il],
params.nBinsRes, -
params.maxPull,
params.maxPull);
809 mHMan->
addHisto(hz2p, idOffset + il * 10 + iyz * 100 + 5 + 1000);
811 auto hpt2 =
new TH2F(fmt::format(
"{}_{}_{}", dname, lrName,
"Pt").c_str(), fmt::format(
"{}_{{{}}} vs {};p_{{T}};{}", dtit, lrName,
"p_{T}", dtit).c_str(),
params.nBinsPt, ptax.data(),
params.nBinsRes, -maxDYZ, maxDYZ);
812 mHMan->
addHisto(hpt2, idOffset + il * 10 + iyz * 100 + 2000);
813 auto hpt2p =
new TH2F(fmt::format(
"{}_{}_{}_pull", dname, lrName,
"Pt").c_str(), fmt::format(
"pull {}_{{{}}} vs {};p_{{T}}; pull{}", dtit, lrName,
"p_{T}", dtit).c_str(),
params.nBinsPt, ptax.data(),
params.nBinsRes, -
params.maxPull,
params.maxPull);
814 mHMan->
addHisto(hpt2p, idOffset + il * 10 + iyz * 100 + 5 + 2000);
816 auto htgl2 =
new TH2F(fmt::format(
"{}_{}_{}", dname, lrName,
"tgl").c_str(), fmt::format(
"{}_{{{}}} vs {};tg#lambda;{}", dtit, lrName,
"tg#lambda", dtit).c_str(),
params.nBinsTgl, -
params.maxTgl,
params.maxTgl,
params.nBinsRes, -maxDYZ, maxDYZ);
817 mHMan->
addHisto(htgl2, idOffset + il * 10 + iyz * 100 + 3000);
818 auto htgl2p =
new TH2F(fmt::format(
"{}_{}_{}_pull", dname, lrName,
"tgl").c_str(), fmt::format(
"pull {}_{{{}}} vs {};tg#lambda; pull{}", dtit, lrName,
"tg#lambda", dtit).c_str(),
params.nBinsTgl, -
params.maxTgl,
params.maxTgl,
params.nBinsRes, -
params.maxPull,
params.maxPull);
819 mHMan->
addHisto(htgl2p, idOffset + il * 10 + iyz * 100 + 5 + 3000);
822 const int ilr = il - 1;
824 for (
int ib = 0; ib < 2; ++ib) {
826 auto hc2 =
new TH2F(fmt::format(
"{}_{}_{}", dname, lrName, ib).c_str(), fmt::format(
"{} Lr{} HB{};chip;{}", dname, lrName, ib, dtit).c_str(), nChips, startChip - 0.5, startChip - 0.5 + nChips,
params.nBinsRes, -maxDYZ, maxDYZ);
827 mHMan->
addHisto(hc2, idOffset + (2 * il + ib) * 100 + iyz * 10 + 15000);
828 auto hc2p =
new TH2F(fmt::format(
"{}_{}_{}_pull", dname, lrName, ib).c_str(), fmt::format(
"{} Lr{} HB{} pull;chip;pull{}", dname, lrName, ib, dtit).c_str(), nChips, startChip - 0.5, startChip - 0.5 + nChips,
params.nBinsRes, -
params.maxPull,
params.maxPull);
829 mHMan->
addHisto(hc2p, idOffset + (2 * il + ib) * 100 + iyz * 10 + 5 + 15000);
835 bookLayerResidHistos(0,
"",
true);
836 if (
params.doIBOBresiduals) {
837 bookLayerResidHistos(100000,
"IOB",
true);
840 for (
int ip = 0; ip < 5; ip++) {
841 auto h2 =
new TH2F(fmt::format(
"dPar{}_IBOBphi", ip).c_str(), fmt::format(
"#Delta par{} IB-OB vs phi;#phi;#Delta par{}", ip, ip).c_str(),
params.nBinsPhi, 0, TMath::Pi() * 2,
params.nBinsRes, -
params.maxDPar[ip],
params.maxDPar[ip]);
842 mHMan->
addHisto(h2, 10000 + ip * 10);
843 auto h2p =
new TH2F(fmt::format(
"dPar{}_IBOBphi_pull", ip).c_str(), fmt::format(
"pull #Delta par{} IB-OB vs phi;#phi;pull #Delta par{}", ip, ip).c_str(),
params.nBinsPhi, 0, TMath::Pi() * 2,
params.nBinsRes, -
params.maxPull,
params.maxPull);
844 mHMan->
addHisto(h2p, 10000 + ip * 10 + 5);
846 auto hz2 =
new TH2F(fmt::format(
"dPar{}_IBOBz", ip).c_str(), fmt::format(
"#Delta par{} IB-OB vs Z;Z;#Delta par{}", ip, ip).c_str(),
params.nBinsZ, -20., 20.,
params.nBinsRes, -
params.maxDPar[ip],
params.maxDPar[ip]);
847 mHMan->
addHisto(hz2, 11000 + ip * 10);
848 auto hz2p =
new TH2F(fmt::format(
"dPar{}_IBOBz_pull", ip).c_str(), fmt::format(
"pull #Delta par{} IB-OB vs Z;Z;pull #Delta par{}", ip, ip).c_str(),
params.nBinsZ, -20., 20.,
params.nBinsRes, -
params.maxPull,
params.maxPull);
849 mHMan->
addHisto(hz2p, 11000 + ip * 10 + 5);
851 auto hpt2 =
new TH2F(fmt::format(
"dPar{}_IBOBpt", ip).c_str(), fmt::format(
"#Delta par{} IB-OB vs pT;p_{{T}};#Delta par{}", ip, ip).c_str(),
params.nBinsPt, ptax.data(),
params.nBinsRes, -
params.maxDPar[ip],
params.maxDPar[ip]);
852 mHMan->
addHisto(hpt2, 12000 + ip * 10);
853 auto hpt2p =
new TH2F(fmt::format(
"dPar{}_IBOBpt_pull", ip).c_str(), fmt::format(
"pull #Delta par{} IB-OB vs pT;p_{{T}};pull #Delta par{}", ip, ip).c_str(),
params.nBinsPt, ptax.data(),
params.nBinsRes, -
params.maxPull,
params.maxPull);
854 mHMan->
addHisto(hpt2p, 12000 + ip * 10 + 5);
856 auto htgl2 =
new TH2F(fmt::format(
"dPar{}_IBOBtgl", ip).c_str(), fmt::format(
"#Delta par{} IB-OB vs tg#lambda;tg#lambda;#Delta par{}", ip, ip).c_str(),
params.nBinsTgl, -
params.maxTgl,
params.maxTgl,
params.nBinsRes, -
params.maxDPar[ip],
params.maxDPar[ip]);
857 mHMan->
addHisto(htgl2, 13000 + ip * 10);
858 auto htgl2p =
new TH2F(fmt::format(
"dPar{}_IBOBtgl_pull", ip).c_str(), fmt::format(
"pull #Delta par{} IB-OB vs tg#lambda;tg#lambda;pull #Delta par{}", ip, ip).c_str(),
params.nBinsTgl, -
params.maxTgl,
params.maxTgl,
params.nBinsRes, -
params.maxPull,
params.maxPull);
859 mHMan->
addHisto(htgl2p, 13000 + ip * 10 + 5);
865 mHMan->
addHisto(
new TH1F(
"pvN",
"PV Contributors;Nc;",
params.maxHPVN, 1.5,
params.maxHPVN + 1.5), 20000 + 3);
868void CheckResidSpec::postProcessHistos()
870 printf(
"Fitting histos\n");
872 if (mHManV.empty()) {
873 LOGP(warn,
"nothing to process");
876 mHMan = mHManV[0].get();
879 auto gs =
new TF1(
"gs",
"gaus", -1, 1);
880 int maxH = mPostProcOnly ? mHManV.size() : 1;
882 for (
int ihm = 0; ihm < maxH; ihm++) {
883 auto* histm = mHManV[ihm].get();
887 auto fitSlices = [&](
int id) {
888 auto h2 = histm->getHisto2F(
id);
889 if (!h2 || h2->GetEntries() <
params.minHistoStat2Fit) {
892 h2->FitSlicesY(gs, 0, -1, 0,
"QNR", &arr);
894 TH1* hmean = (TH1*)arr.RemoveAt(1);
896 hmean->SetTitle(Form(
"<%s>", h2->GetTitle()));
897 histm->addHisto(hmean,
id + 1);
899 TH1* hsig = (TH1*)arr.RemoveAt(2);
901 hsig->SetTitle(Form(
"#sigma(%s)", h2->GetTitle()));
902 histm->addHisto(hsig,
id + 2);
905 for (
int ioffs = 0; ioffs <= 3; ioffs++) {
906 int offs = ioffs * 1000;
907 for (
int iht = 0; iht < 2; iht++) {
908 int offsV = iht == 0 ? 0 : 5;
909 for (
int idOffset : {0, 100000}) {
910 for (
int il = 0; il < 8; il++) {
911 for (
int iyz = 0; iyz < 2; iyz++) {
912 fitSlices(idOffset + il * 10 + iyz * 100 + offsV + offs);
916 for (
int ip = 0; ip < 5; ip++) {
917 fitSlices(10000 + ip * 10 + offsV + offs);
921 for (
int idOffset : {0, 100000}) {
922 for (
int il = 1; il < 8; il++) {
923 for (
int ib = 0; ib < 2; ib++) {
924 for (
int iyz = 0; iyz < 2; iyz++) {
925 for (
int iht = 0; iht < 2; iht++) {
926 const int offsV = iht == 0 ? 0 : 5;
927 fitSlices(idOffset + (2 * il + ib) * 100 + iyz * 10 + offsV + 15000);
937void CheckResidSpec::drawHistos()
940 gStyle->SetTitleX(0.3);
941 gStyle->SetTitleY(0.88);
942 gStyle->SetTitleW(0.25);
943 gStyle->SetOptStat(0);
945 int nhm = mHManV.size();
946 std::array<unsigned int, 3> hcol{EColor::kRed, EColor::kBlue, EColor::kGreen + 2};
950 bool useColors = colorNames.size() == hmNames.size() && !colorNames.empty();
951 bool useMarkers = markerIDs.size() == hmNames.size() && !markerIDs.empty();
953 LOGP(warn,
"{} color names provided for {} external histomanagers, will use automatic colors", colorNames.size(), hmNames.size());
956 LOGP(warn,
"{} marker IDs provided for {} external histomanagers, will use automatic markers", markerIDs.size(), hmNames.size());
958 constexpr std::array<std::pair<std::string_view, int>, 15> rootColors{{
959 {
"kWhite", EColor::kWhite},
960 {
"kBlack", EColor::kBlack},
961 {
"kGray", EColor::kGray},
962 {
"kRed", EColor::kRed},
963 {
"kGreen", EColor::kGreen},
964 {
"kBlue", EColor::kBlue},
965 {
"kYellow", EColor::kYellow},
966 {
"kMagenta", EColor::kMagenta},
967 {
"kCyan", EColor::kCyan},
968 {
"kOrange", EColor::kOrange},
969 {
"kSpring", EColor::kSpring},
970 {
"kTeal", EColor::kTeal},
971 {
"kAzure", EColor::kAzure},
972 {
"kViolet", EColor::kViolet},
973 {
"kPink", EColor::kPink},
975 auto parseColor = [&rootColors](
const std::string& token) -> std::optional<int> {
978 for (
unsigned char ch : token) {
979 if (!std::isspace(ch)) {
983 for (
const auto& [
name,
value] : rootColors) {
987 const auto increment = std::string_view(
normalized).substr(
name.size());
988 if (increment.empty()) {
991 if (increment.size() < 2 || (increment.front() !=
'+' && increment.front() !=
'-')) {
995 const auto*
begin = increment.data() + 1;
996 const auto*
end = increment.data() + increment.size();
998 if (error != std::errc{} || parsedEnd !=
end) {
1001 const auto signedOffset = increment.front() ==
'-' ? -
static_cast<long long>(
offset) : static_cast<
long long>(
offset);
1002 const auto color =
static_cast<long long>(
value) + signedOffset;
1003 if (
color < std::numeric_limits<int>::min() ||
color > std::numeric_limits<int>::max()) {
1004 return std::nullopt;
1006 return static_cast<int>(
color);
1008 return std::nullopt;
1010 std::vector<int> colors;
1012 for (
const auto& colorName : colorNames) {
1013 auto color = parseColor(colorName);
1015 LOGP(warn,
"Unrecognized EColor name '{}', will use automatic colors", colorName);
1019 colors.push_back(*
color);
1022 std::vector<int> markers;
1024 for (
const auto& markerID : markerIDs) {
1026 const auto*
begin = markerID.data();
1027 const auto*
end =
begin + markerID.size();
1029 if (error != std::errc{} || parsedEnd !=
end) {
1030 LOGP(warn,
"Unrecognized marker ID '{}', will use automatic markers", markerID);
1034 markers.push_back(
marker);
1037 std::unique_ptr<TLegend> lg;
1038 lg = std::make_unique<TLegend>(0.12, 0.13, 0.9, 0.13 + std::min(0.5f, nhm * 0.2f / 3.f));
1039 lg->SetFillStyle(0);
1040 lg->SetBorderSize(0);
1041 for (
int i = 0;
i < nhm;
i++) {
1042 auto hman = mHManV[
i].get();
1043 if (!hman || hman->GetLast() < 1) {
1046 const int marker = useMarkers ? markers[
i] : 20 +
i + (
i % 2) * 4;
1047 const int color = useColors ? colors[
i] : hcol[
i % hcol.size()];
1048 hman->setMarkerStyle(
marker, 0.5);
1049 hman->setColor(
color);
1050 auto le = lg->AddEntry(hman->getHisto(1), hman->GetName(),
"lp");
1051 le->SetTextColor(
color);
1053 TCanvas cly(
"cly",
"", 600, 800), clz(
"clz",
"", 600, 800), clpar(
"clpar",
"", 600, 800);
1054 TCanvas czly(
"czly",
"", 600, 800), czlz(
"czlz",
"", 600, 800), czlpar(
"czlpar",
"", 600, 800);
1055 TCanvas cchip(
"cchip",
"", 600, 800);
1056 constexpr std::array<const char*, 4> chipTitles{
"#DeltaY",
"pull #DeltaY",
"#DeltaZ",
"pull #DeltaZ"};
1057 auto AddLabel = [](
const char* txt,
float x = 0.1,
float y = 0.9,
int color = kBlack,
float size = 0.04) {
1058 TLatex* lt =
new TLatex(
x,
y, txt);
1060 lt->SetTextColor(
color);
1061 lt->SetTextSize(
size);
1066 auto drawResLr = [
this](TCanvas& canv,
int offs,
const float resMM[8],
bool logX) {
1069 int nh = this->mHManV.size();
1070 for (
int i = 0;
i < 8;
i++) {
1073 for (
int j = 0;
j < nh;
j++) {
1074 auto hman = this->mHManV[
j].get();
1075 if (!hman || hman->GetLast() < 1) {
1078 if (
auto histo = hman->getHisto(10 *
i + offs)) {
1079 histo->Draw(same ?
"same" :
"");
1081 histo->SetMinimum(-resMM[
i]);
1082 histo->SetMaximum(resMM[
i]);
1088 gPad->SetLogx(logX);
1092 auto drawResPar = [
this](TCanvas& canv,
int offs,
const float resMM[8],
bool logX) {
1095 int nh = this->mHManV.size();
1096 for (
int i = 0;
i < 5;
i++) {
1099 for (
int j = 0;
j < nh;
j++) {
1100 auto hman = this->mHManV[
j].get();
1101 if (!hman || hman->GetLast() < 1) {
1104 if (
auto histo = hman->getHisto(10 *
i + offs)) {
1105 histo->Draw(same ?
"same" :
"");
1107 histo->SetMinimum(-resMM[
i]);
1108 histo->SetMaximum(resMM[
i]);
1114 gPad->SetLogx(logX);
1119 auto drawLrResidPages = [&](
const std::string& pdfName,
int idOffset) {
1120 const float dyzScale = idOffset ?
params.IOBScaleFactor : 1.f;
1121 std::array<float, 8> resMMY, resMMZ;
1122 for (
int i = 0;
i < 8;
i++) {
1123 resMMY[
i] =
params.resMMLrY[
i] * dyzScale;
1124 resMMZ[
i] =
params.resMMLrZ[
i] * dyzScale;
1126 drawResLr(cly, idOffset + 1, resMMY.data(),
false);
1129 AddLabel(
"Y residuals", 0.1, 0.95);
1130 cly.Print(pdfName.c_str());
1132 drawResLr(clz, idOffset + 101, resMMZ.data(),
false);
1135 AddLabel(
"Z residuals", 0.1, 0.95);
1136 clz.Print(pdfName.c_str());
1138 drawResLr(czly, idOffset + 1001, resMMY.data(),
false);
1141 AddLabel(
"Y residuals", 0.1, 0.95);
1142 czly.Print(pdfName.c_str());
1144 drawResLr(czlz, idOffset + 1101, resMMZ.data(),
false);
1147 AddLabel(
"Z residuals", 0.1, 0.95);
1148 czlz.Print(pdfName.c_str());
1150 drawResLr(czly, idOffset + 2001, resMMY.data(),
true);
1153 AddLabel(
"Y residuals", 0.1, 0.95);
1154 czly.Print(pdfName.c_str());
1156 drawResLr(czlz, idOffset + 2101, resMMZ.data(),
true);
1159 AddLabel(
"Z residuals", 0.1, 0.95);
1160 czlz.Print(pdfName.c_str());
1162 drawResLr(czly, idOffset + 3001, resMMY.data(),
false);
1165 AddLabel(
"Y residuals", 0.1, 0.95);
1166 czly.Print(pdfName.c_str());
1168 drawResLr(czlz, idOffset + 3101, resMMZ.data(),
false);
1171 AddLabel(
"Z residuals", 0.1, 0.95);
1172 czlz.Print(pdfName.c_str());
1175 const std::string mainPdf = fmt::format(
"{}_hman.pdf",
params.outname);
1176 cly.Print(Form(
"%s[", mainPdf.c_str()));
1177 drawLrResidPages(mainPdf, 0);
1179 drawResPar(clpar, 10001,
params.resMMPar,
false);
1182 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
1183 clpar.Print(mainPdf.c_str());
1185 drawResPar(czlpar, 11001,
params.resMMPar,
false);
1188 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
1189 czlpar.Print(mainPdf.c_str());
1191 drawResPar(czlpar, 12001,
params.resMMPar,
true);
1194 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
1195 czlpar.Print(mainPdf.c_str());
1197 drawResPar(czlpar, 13001,
params.resMMPar,
false);
1200 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
1201 czlpar.Print(mainPdf.c_str());
1203 auto getHMinMax = [
this](
int id,
float marginFrac,
float maxDev,
int roundToMicrons) -> std::tuple<float, float, float> {
1204 float maxV = std::numeric_limits<float>::lowest(), minV = std::numeric_limits<float>::max();
1205 const int nh = this->mHManV.size();
1206 for (
int j = 0;
j < nh;
j++) {
1207 if (!this->mHManV[
j]) {
1210 if (
auto histo = this->mHManV[
j]->getHisto(
id); histo !=
nullptr) {
1211 const int nb = histo->GetNbinsX();
1212 for (
int ib = 1; ib <= nb; ib++) {
1213 float v = histo->GetBinContent(ib);
1214 maxV = std::max(maxV,
v);
1215 minV = std::min(minV,
v);
1220 return {0.f, 1.f, 0.1f};
1222 auto delta = maxV - minV;
1223 maxV += delta * marginFrac;
1224 minV -= delta * marginFrac;
1225 if (roundToMicrons > 0) {
1226 maxV = ((
int(std::ceil(maxV * 1e4)) / roundToMicrons + 1) * roundToMicrons) * 1e-4;
1227 minV = ((
int(std::floor(minV * 1e4)) / roundToMicrons - 1) * roundToMicrons) * 1e-4;
1229 minV = std::max(minV, -maxDev);
1230 maxV = std::min(maxV, maxDev);
1231 return {minV, maxV, std::max(std::abs(minV), std::abs(maxV))};
1233 auto collectSpread = [](TH1* hin, TH1* hout) {
1234 const int nb = hin->GetNbinsX();
1235 for (
int ib = 1; ib <= nb; ib++) {
1236 if (hin->GetBinError(ib) != 0) {
1237 hout->Fill(hin->GetBinContent(ib));
1240 hout->SetLineColor(hin->GetLineColor());
1241 hout->SetMarkerColor(hin->GetMarkerColor());
1242 hout->SetMarkerStyle(hin->GetMarkerStyle());
1244 int nh = this->mHManV.size();
1246 auto drawChipPages = [&](
const std::string& pdfName,
int idOffset) {
1247 for (
int il = 1; il < 8; ++il) {
1248 for (
int iht = 0; iht < 2; iht++) {
1249 for (
int ib = 0; ib < 3; ib++) {
1250 if (iht == 1 && ib < 2) {
1253 for (
int iyz = 0; iyz < 2; iyz++) {
1255 cchip.Divide(1, ib == 2 ? 2 : 4);
1256 bool havePage =
false;
1257 for (
int iv = 0; iv < 2; iv++) {
1258 const float yRange = (iyz == 0 ?
params.resMMLrY[il] :
params.resMMLrZ[il]) * (idOffset ?
params.IOBScaleFactor : 1.f);
1259 const int baseID = idOffset + 15000 + iyz * 10 + 2 * il * 100 + iht * 5 + 1 + iv;
1261 auto [minV, maxV, absMax] = getHMinMax(baseID, 0.15, (iv == 0 ? 2 : 8) * yRange, 10);
1262 auto [minV1, maxV1, absMax1] = getHMinMax(baseID + 100, 0.15, (iv == 0 ? 2 : 8) * yRange, 10);
1263 minV = std::min(minV, minV1);
1264 maxV = std::max(maxV, maxV1);
1265 absMax = std::max(absMax, absMax1);
1267 minV = iv ? 0.f : -
params.maxPull;
1268 maxV = absMax =
params.maxPull;
1271 TH1* firstAuto =
nullptr;
1272 float maxAuto = 0.f;
1273 for (
int j = 0;
j < nh;
j++) {
1274 auto hman = this->mHManV[
j].get();
1278 TH1* hmeans =
nullptr;
1279 for (
int hb = ib == 2 ? 0 : ib; hb < (ib == 2 ? 2 : ib + 1); hb++) {
1280 const int id = baseID + hb * 100;
1281 auto histo = hman->getHisto(
id);
1287 hmeans =
new TH1F(Form(
"%s_layer_spread", histo->GetName()), Form(
"Lr%d %s %s spread", il - 1, chipTitles[2 * iyz + iht], iv ?
"sigma" :
"mean"),
params.nBinsRes, iv == 0 ? minV :
std::
max(0.f, minV), maxV);
1288 hman->addHisto(hmeans, idOffset + 25000 + il * 100 + iyz * 10 + iht * 5 + iv);
1290 hmeans =
new TH1F(Form(
"%s_spread", histo->GetName()), Form(
"%s spread;#<Delta>", histo->GetTitle()),
params.nBinsRes, iv == 0 ? minV :
std::
max(0.f, minV), maxV);
1291 hman->addHisto(hmeans,
id + 2);
1295 hmeans->SetXTitle(iv ?
"<#sigma>, cm" :
"<#Delta>, cm");
1297 collectSpread(histo, hmeans);
1299 histo->SetMaximum(absMax);
1300 histo->SetMinimum(iv ? 0 : -absMax);
1302 histo->SetMarkerSize(0.3);
1303 histo->SetLineStyle(3);
1305 cchip.cd(2 * iv + 1);
1306 histo->Draw(drawn ?
"same" :
"");
1313 cchip.cd(ib == 2 ? iv + 1 : 2 * iv + 2);
1317 maxAuto = std::max(maxAuto, (
float)hmeans->GetMaximum());
1318 hmeans->Draw(drawn ?
"same" :
"");
1319 drawn = havePage =
true;
1322 firstAuto->SetMaximum(maxAuto * 1.25);
1328 cchip.Print(pdfName.c_str());
1335 drawChipPages(mainPdf, 0);
1336 cly.Print(Form(
"%s]", mainPdf.c_str()));
1339 bool haveIOB =
false;
1340 for (
const auto& hm : mHManV) {
1341 if (hm && hm->getHisto2F(100000 + 1 * 10)) {
1347 const std::string iobPdf = fmt::format(
"{}_iob_hman.pdf",
params.outname);
1348 cly.Print(Form(
"%s[", iobPdf.c_str()));
1349 drawLrResidPages(iobPdf, 100000);
1350 drawChipPages(iobPdf, 100000);
1351 cly.Print(Form(
"%s]", iobPdf.c_str()));
1358 if (mHManV.size()) {
1359 postProcessHistos();
1364 if (
auto nh = mHManV.size(); nh > 0 && !mPostProcOnly) {
1365 for (
int ihm = 0; ihm < nh; ihm++) {
1367 mHManV[ihm].get()->write();
1381 mMeanVertexUpdated =
true;
1385 LOG(info) <<
"cluster dictionary updated";
1393 std::vector<OutputSpec> outputs;
1394 auto dataRequest = std::make_shared<DataRequest>();
1395 dataRequest->setITSPerLayer(itsStag);
1396 if (!drawOnly && !postProcOnly) {
1398 dataRequest->requestTracks(srcTracks, useMC);
1399 dataRequest->requestClusters(srcClusters, useMC);
1400 dataRequest->requestPrimaryVertices(useMC);
1401 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
1403 auto ggRequest = drawOnly ? std::make_shared<o2::base::GRPGeomRequest>(
false,
false,
false,
false,
false,
o2::base::GRPGeomRequest::None, dataRequest->inputs) : std::make_shared<o2::base::GRPGeomRequest>(
false,
1409 dataRequest->inputs,
true);
1413 {
"nthreads", VariantType::Int, 1, {
"number of threads"}},
1414 {
"no-tree", VariantType::Bool,
false, {
"do not fill residuals tree"}},
1415 {
"no-hist", VariantType::Bool,
false, {
"do not fill residuals histograms"}},
1416 {
"draw-report", VariantType::Bool,
false, {
"fill residuals report"}},
1424 AlgorithmSpec{adaptFromTask<CheckResidSpec>(dataRequest, ggRequest, srcTracks, drawOnly, postProcOnly)},
Container of the ITS/MFT clusters addressed by the composed (layer,index) ID.
Definition of the GeometryManager class.
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Definition of the GeometryTGeo class.
std::vector< o2::its::TrackITS > tracks
Utility functions for MC particles.
Definition of the Names Generator class.
Wrapper container for different reconstructed object types.
o2::track::TrackParCov TrackParCov
Result of refitting TPC-ITS matched track.
Reference on ITS/MFT clusters set.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
void setSensorID(std::int16_t sid)
void setXYZ(T x, T y, T z)
int addHisto(TH1 *histo, int at=-1)
TH2F * getHisto2F(int id) const
TH1 * getHisto(int id) const
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
~CheckResidSpec() final=default
void run(ProcessingContext &pc) final
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
CheckResidSpec(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, bool drawOnly, bool postProcOnly)
void init(InitContext &ic) final
static const CheckResidConfig & Instance()
static void updateFromString(std::string const &)
Static class with identifiers, bitmasks and names for ALICE detectors.
T get(const char *key) const
ServiceRegistryRef services()
ConfigParamRegistry const & options()
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
static GeometryTGeo * Instance()
int getClusterEntry(int i) const
static constexpr int getNChipsOnLayer(int lr)
static constexpr int getFirstChipsOnLayer(int lr)
int getNPixels() const
Returns the number of fired pixels.
void beginLayer(int lr)
to be called once all the layers were filled
void init(int nLr)
< prepare for filling nLr layer slots, discarding the previous content
static constexpr unsigned short InvalidPatternID
int getNpixels(int n) const
Returns the number of fired pixels of the n_th element.
bool isGroup(int n) const
Returns true if the element corresponds to a group of rare topologies.
void initMeanVertexConstraint()
PVertex refitVertexFull(const std::vector< bool > useTrack, const o2d::VertexBase &vtxSeed)
bool prepareVertexRefit(const TR &tracks, const o2d::VertexBase &vtxSeed)
void setMeanVertex(const o2d::MeanVertexObject *v)
GLfloat GLfloat GLfloat alpha
GLuint const GLchar * name
GLsizei const GLfloat * value
GLenum const GLfloat * params
GLint GLenum GLboolean normalized
GLint GLint GLsizei GLint GLenum format
GLdouble GLdouble GLdouble z
uint8_t int statusCode int
o2::framework::DataProcessorSpec getCheckResidSpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool drawOnly, bool postProcOnly, bool itsStag)
create a processor spec
o2::dataformats::GlobalTrackID GTrackID
Defining ITS Vertex explicitly as messageable.
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
constexpr int MaxITSLayers
constexpr unsigned int nChips
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const itsmft::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
o2::track::TrackParCov int int int float int nCl
const bool const int TrackITSInternal< NLayers > & track
const float const float const float bz
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
Enum< T >::Iterator begin(Enum< T >)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
o2::track::TrackPar track
o2::track::TrackParCov trIBOut
o2::track::TrackParCov trOBInw
std::vector< Point > points
auto getITSTracks() const
GTrackID getITSContributorGID(GTrackID source) const
bool isTrackSourceLoaded(int src) const
auto getITSTracksClusterRefs() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
auto getPrimaryVertexMatchedTrackRefs() const
auto getITSClustersPatterns(int layer=0) const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
auto getITSClusters(int layer=0) const
static std::vector< std::string > tokenize(const std::string &src, char delim, bool trimToken=true, bool skipEmpty=true)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"