17#include <TStopwatch.h>
49#include <TLegendEntry.h>
81 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mDrawOnly(drawOnly), mPostProcOnly(postProcOnly)
93 bool refitPV(
o2::dataformats::PrimaryVertex& pv,
int vid);
95 bool processITSTrack(const
o2::its::
TrackITS& iTrack, const
o2::dataformats::PrimaryVertex& pv,
o2::checkresid::
Track& resTrack,
o2::track::
PID pid);
97 void fillHistos(const
o2::checkresid::
Track& trc);
98 void postProcessHistos();
101 o2::globaltracking::RecoContainer* mRecoData =
nullptr;
103 bool mMeanVertexUpdated = false;
104 float mITSROFrameLengthMUS = 0.
f;
105 o2::dataformats::MeanVertexObject mMeanVtx{};
109 std::shared_ptr<DataRequest> mDataRequest;
110 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
111 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
114 bool mDrawOnly =
false;
115 bool mPostProcOnly =
false;
117 bool mFillHistos =
true;
118 bool mFillTree =
true;
119 std::vector<std::unique_ptr<o2::HistoManager>> mHManV{};
120 std::vector<o2::dataformats::PrimaryVertex> mPVUsed;
128 mDraw = ic.
options().
get<
bool>(
"draw-report");
129 mFillHistos = !ic.
options().
get<
bool>(
"no-hist");
130 mFillTree = !ic.
options().
get<
bool>(
"no-tree");
131 mNThreads = ic.
options().
get<
int>(
"nthreads");
136 std::string nm =
params.outname;
143 if (!mDrawOnly && mFillHistos) {
146 if (!
params.ext_hm_list.empty()) {
150 if (vecNames.size() != vecLegends.size()) {
151 LOGP(warn,
"{} legend names provided for {} external histomanagers, will use file names as legends", vecLegends.size(), vecNames.size());
155 for (
const auto& vn : vecNames) {
156 LOGP(info,
"Loading external HistoManager {}", vn);
157 mHManV.emplace_back() = std::make_unique<o2::HistoManager>(
"", vn,
true);
158 auto hm = mHManV.back().get();
160 LOGP(error,
"Failed to load histograms from {}", vn);
163 hm->SetName(useLeg ? vecLegends[cntH].c_str() : vn.c_str());
174 LOGP(warn,
"No OpenMP");
179 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(fmt::format(
"{}.root",
params.outname).c_str(),
"recreate");
201 mRecoData = &recoData;
203 mRecoData = &recoData;
204 updateTimeDependentParams(pc);
213 static bool initOnceDone =
false;
220 if (!grp->isDetContinuousReadOut(DetID::ITS)) {
221 mITSROFrameLengthMUS = alpParams.roFrameLengthTrig / 1.e3;
223 mITSROFrameLengthMUS = alpParams.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS * 1e-3;
226 geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G, o2::math_utils::TransformType::T2G));
230 if (mMeanVertexUpdated) {
231 mMeanVertexUpdated =
false;
240 LOGP(fatal,
"ITS data is not loaded");
247 mITSClustersArray.
init(nLr);
248 for (
int lr = 0; lr < nLr; lr++) {
252 mITSClustersArray.
getClusters().reserve(mITSClustersArray.
size() + clusITS.size());
261 static int TFCount = 0;
262 int nv = vtxRefs.size() - 1;
263 std::vector<std::vector<checkresid::Track>> slots;
265 slots.resize(mNThreads);
266 int nvGood = 0, nvUse = 0, nvRefFail = 0;
267 long pvFitDuration{};
268 for (
int iv = 0; iv < nv; iv++) {
269 const auto& vtref = vtxRefs[iv];
270 auto pve = pvvec[iv];
271 if (pve.getNContributors() <
params.minPVContributors) {
276 LOGP(
debug,
"Refitting PV#{} of {} tracks", iv, pve.getNContributors());
277 auto tStartPVF = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
278 bool res = refitPV(pve, iv);
279 pvFitDuration += std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count() - tStartPVF;
286 mPVUsed.push_back(pve);
287 const auto& itsContRefs = vtref.getITSGloContributors();
288 int idMinITSGlo = 0, idMaxITSGlo = 0;
289 if (
params.useITSGloContributors) {
290 if (itsContRefs.getFirstEntry() < vtref.getEntries() && itsContRefs.getEntries() == 0) {
291 LOGP(fatal,
"Usage of stored ITS global contributors is requested but they are missing");
293 idMinITSGlo = itsContRefs.getFirstEntry();
294 idMaxITSGlo = idMinITSGlo + itsContRefs.getEntries();
301 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
303 if (!dm[DetID::ITS]) {
307#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
309 for (
int i = idMin;
i < idMax;
i++) {
310 auto vid = trackIndex[
i];
311 bool pvCont = vid.isPVContributor();
312 if (!pvCont && (
params.pvcontribOnly ||
params.useITSGloContributors)) {
317 if (
params.useITSGloContributors) {
318 int id = idMinITSGlo + cntPVCont;
319 if (
id >= idMaxITSGlo) {
320 LOGP(fatal,
"Calculated GlobalContributor ITS track index {} exceeds number of stored indices {}",
id, itsContRefs.getEntries());
322 pidITS = trackIndex[
id].getSource();
331 const auto& itsTrack = mRecoData->
getITSTrack(gidITS);
332 if (itsTrack.getNClusters() <
params.minITSCl) {
336 if (!
params.useITSGloContributors) {
337 pidITS = trc.getPID();
339 auto pt = trc.getPt();
340 if (pt < params.minPt || pt >
params.maxPt) {
343 if (std::abs(trc.getTgl()) >
params.maxTgl) {
347 auto& accum = slots[omp_get_thread_num()];
349 auto& accum = slots[0];
351 auto& resTrack = accum.emplace_back();
353 if (!processITSTrack(itsTrack, pve, resTrack, pidITS)) {
361 for (
const auto& accum : slots) {
362 for (
const auto& tr : accum) {
364 (*mDBGOut) <<
"res" <<
"tr=" << tr <<
"\n";
372 (*mDBGOut) <<
"pvUsed" <<
"pv=" << mPVUsed <<
"\n";
375 for (
const auto& pv : mPVUsed) {
376 mHMan->
getHisto(20000 + 0)->Fill(pv.getX());
377 mHMan->
getHisto(20000 + 1)->Fill(pv.getY());
378 mHMan->
getHisto(20000 + 2)->Fill(pv.getZ());
379 mHMan->
getHisto(20000 + 3)->Fill(pv.getNContributors());
382 LOGP(info,
"processed {} PVs out of {} good vertices (out of {} in total), PV refits took {} mus, {} refits failed", nvUse, nvGood, nv, pvFitDuration, nvRefFail);
389 auto trFitInw = iTrack.getParamOut();
390 auto trFitOut = iTrack.getParamIn();
391 trFitInw.setPID(pid);
392 trFitOut.setPID(pid);
396 float bz = prop->getNominalBz();
397 std::array<const o2::BaseCluster<float>*, 8> clArr{};
399 std::array<o2::track::TrackParCov, 8> extrapOut, extrapInw;
402 return refLin ? tr.rotate(
alpha, *refLin, bz) : tr.rotate(
alpha);
407 if (!rotateTrack(tr,
i == 0 ? pvAlpha : geom->getSensorRefAlpha(clArr[
i]->getSensorID()), refLin) ||
408 !prop->propagateTo(tr, refLin, clArr[
i]->getX(), true)) {
412 if (!tr.update(*clArr[
i])) {
416 extrapDest[
i].invalidate();
422 auto inv2d = [](
float s00,
float s11,
float s01) -> std::array<float, 3> {
423 auto det = s00 * s11 - s01 * s01;
425 LOGP(error,
"Singular det {}, input: {} {} {}", det, s00, s11, s01);
426 return {0.f, 0.f, 0.f};
429 return {s11 * det, s00 * det, -s01 * det};
433 if (!prop->propagateToDCA(pv, trFitOut, bz)) {
434 LOGP(
debug,
"Failed to propagateToDCA, {}", trFitOut.asString());
438 if (
params.addPVAsCluster) {
439 float cosAlp, sinAlp;
440 pvAlpha = trFitOut.getAlpha();
441 o2::math_utils::sincos(trFitOut.getAlpha(), sinAlp, cosAlp);
442 bcPV.
setXYZ(pv.getX() * cosAlp + pv.getY() * sinAlp, -pv.getX() * sinAlp + pv.getY() * cosAlp, pv.getZ());
443 bcPV.
setSigmaY2(0.5 * (pv.getSigmaX2() + pv.getSigmaY2()));
449 int nCl = iTrack.getNClusters();
450 for (
int i = 0;
i <
nCl;
i++) {
451 const auto& curClu = mITSClustersArray[itsClRefs[iTrack.
getClusterEntry(
i)]];
453 int llr = geom->getLayer(curClu.getSensorID());
454 if (clArr[1 + llr]) {
455 LOGP(error,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), curClu.getSensorID());
457 clArr[1 + geom->getLayer(curClu.getSensorID())] = &curClu;
460 o2::track::TrackPar refLinIBOut0, refLinOBInw0, *refLinOBInw =
nullptr, *refLinIBOut =
nullptr;
461 if (
params.useStableRef) {
462 refLinOut = &(refLinOut0 = trFitOut);
463 refLinInw = &(refLinInw0 = trFitInw);
465 trFitOut.resetCovariance();
466 trFitOut.setCov(trFitOut.getQ2Pt() * trFitOut.getQ2Pt() * trFitOut.getCov()[14], 14);
467 trFitInw.resetCovariance();
468 trFitInw.setCov(trFitInw.getQ2Pt() * trFitInw.getQ2Pt() * trFitInw.getCov()[14], 14);
470 for (
int i = 0;
i <= 7;
i++) {
473 if (!(resOut = accountCluster(
i, extrapOut, trFitOut, refLinOut)) || !(resInw = accountCluster(7 -
i, extrapInw, trFitInw, refLinInw))) {
479 if (
i == 3 && resOut == 1 && resInw == 1 &&
params.doIBOB && nCl == 7) {
484 refLinIBOut = &(refLinIBOut0 = refLinOut0);
485 refLinOBInw = &(refLinOBInw0 = refLinInw0);
488 if (!resTrack.
trOBInw.getXatLabR(
params.rCompIBOB, xRref, bz) ||
489 !prop->propagateTo(resTrack.
trOBInw, refLinOBInw, xRref,
true) ||
490 !rotateTrack(resTrack.
trOBInw, resTrack.
trOBInw.getPhiPos(), refLinOBInw) ||
491 !rotateTrack(resTrack.
trIBOut, resTrack.
trOBInw.getAlpha(), refLinIBOut) ||
492 !prop->propagateTo(resTrack.
trIBOut, refLinIBOut, resTrack.
trOBInw.getX(),
true)) {
499 bool innerDone =
false;
501 for (
int i = 0;
i <= 7;
i++) {
504 const auto &tInw = extrapInw[
i], &tOut = extrapOut[
i];
505 auto wInw = inv2d(tInw.getSigmaY2(), tInw.getSigmaZ2(), tInw.getSigmaZY());
506 auto wOut = inv2d(tOut.getSigmaY2(), tOut.getSigmaZ2(), tOut.getSigmaZY());
507 if (wInw[0] == 0.f || wOut[0] == 0.f) {
510 std::array<float, 3> wTot = {wInw[0] + wOut[0], wInw[1] + wOut[1], wInw[2] + wOut[2]};
511 auto cTot = inv2d(wTot[0], wTot[1], wTot[2]);
512 auto ywi = wInw[0] * tInw.getY() + wInw[2] * tInw.getZ() + wOut[0] * tOut.getY() + wOut[2] * tOut.getZ();
513 auto zwi = wInw[2] * tInw.getY() + wInw[1] * tInw.getZ() + wOut[2] * tOut.getY() + wOut[1] * tOut.getZ();
514 auto yw = ywi * cTot[0] + zwi * cTot[2];
515 auto zw = ywi * cTot[2] + zwi * cTot[1];
517 auto phi =
i == 0 ? tInw.getPhi() : tInw.getPhiPos();
518 o2::math_utils::bringTo02Pi(phi);
519 resTrack.
points.emplace_back(clArr[
i]->
getY() - yw, clArr[
i]->getZ() - zw, cTot[0] + clArr[
i]->getSigmaY2(), cTot[1] + clArr[
i]->getSigmaZ2(), phi, clArr[
i]->getZ(), clArr[
i]->
getSensorID(),
i - 1);
521 resTrack.
track = tInw;
525 LOGP(
debug,
"No cluster on lr {}",
i);
535 std::vector<o2::track::TrackParCov>
tracks;
536 std::vector<bool> useTrack;
537 std::vector<GTrackID> gidsITS;
538 int ntr = pv.getNContributors(), ntrIni = ntr;
540 useTrack.reserve(ntr);
541 gidsITS.reserve(ntr);
544 const auto& itsContRefs = vtref.getITSGloContributors();
545 if (
params.useITSGloContributors && itsContRefs.getEntries()) {
546 int itr = itsContRefs.getFirstEntry(), itLim = itr + itsContRefs.getEntries();
547 for (; itr < itLim; itr++) {
548 auto tid = trackIndex[itr];
549 tracks.emplace_back().setPID(tid.getSource());
553 int itr = vtref.getFirstEntry(), itLim = itr + vtref.getEntries();
554 for (; itr < itLim; itr++) {
555 auto tid = trackIndex[itr];
563 useTrack.resize(ntr);
565#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
567 for (
int itr = 0; itr < ntr; itr++) {
568 if (!(useTrack[itr] = refitITStrack(
tracks[itr], gidsITS[itr]))) {
573 for (
auto v : useTrack) {
577 LOGP(warn,
"Abandon vertex refit: NcontribNew = {} vs NcontribOld = {}", ntr, ntrIni);
580 LOGP(
debug,
"Original vtx: Nc:{} {}, chi2={}", pv.getNContributors(), pv.
asString(), pv.getChi2());
583 LOGP(
debug,
"Refitted vtx: Nc:{} {}, chi2={}", ntr, pv.
asString(), pv.getChi2());
584 if (pv.getChi2() < 0.f) {
585 LOGP(warn,
"Failed to refit PV {}", pvSave.asString());
598 track = trkITS.getParamOut();
599 track.resetCovariance();
602 auto nCl = trkITS.getNumberOfClusters();
605 float bz = prop->getNominalBz();
608 for (
int iCl = 0; iCl <
nCl; iCl++) {
609 const auto& cls = mITSClustersArray[itsClRefs[trkITS.getClusterEntry(iCl)]];
610 auto alpha = geom->getSensorRefAlpha(cls.getSensorID());
613 LOGP(
debug,
"refitITStrack failed on propagation to cl#{}, alpha={}, x={} | {}", iCl,
alpha, cls.getX(),
track.asString());
616 if (!
track.update(cls)) {
617 LOGP(
debug,
"refitITStrack failed on update with cl#{}, | {}", iCl,
track.asString());
627 int np = trc.
points.size();
628 auto pt = trc.
track.getPt();
629 if (pt < params.minPt || pt >
params.maxPt) {
632 for (
int ip = 0; ip < np; ip++) {
633 const auto& pnt = trc.
points[ip];
634 int il = pnt.lr >= 0 ? pnt.lr + 1 : 0;
635 mHMan->
getHisto2F(il * 10 + 0 * 100)->Fill(pnt.phi, pnt.dy);
636 mHMan->
getHisto2F(il * 10 + 0 * 100 + 1000)->Fill(pnt.z, pnt.dy);
637 mHMan->
getHisto2F(il * 10 + 0 * 100 + 2000)->Fill(pt, pnt.dy);
638 mHMan->
getHisto2F(il * 10 + 0 * 100 + 3000)->Fill(trc.
track.getTgl(), pnt.dy);
640 auto pull = pnt.dy / std::sqrt(pnt.sig2y);
641 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5)->Fill(pnt.phi, pull);
642 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5 + 1000)->Fill(pnt.z, pull);
643 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5 + 2000)->Fill(pt, pull);
644 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5 + 3000)->Fill(trc.
track.getTgl(), pull);
646 mHMan->
getHisto2F(il * 10 + 1 * 100)->Fill(pnt.phi, pnt.dz);
647 mHMan->
getHisto2F(il * 10 + 1 * 100 + 1000)->Fill(pnt.z, pnt.dz);
648 mHMan->
getHisto2F(il * 10 + 1 * 100 + 2000)->Fill(pt, pnt.dz);
649 mHMan->
getHisto2F(il * 10 + 1 * 100 + 3000)->Fill(trc.
track.getTgl(), pnt.dz);
651 auto pull = pnt.dz / std::sqrt(pnt.sig2z);
652 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5)->Fill(pnt.phi, pull);
653 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5 + 1000)->Fill(pnt.z, pull);
654 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5 + 2000)->Fill(pt, pull);
655 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5 + 3000)->Fill(trc.
track.getTgl(), pull);
660 for (
int ip = 0; ip < 5; ip++) {
664 mHMan->
getHisto2F(12000 + ip * 10)->Fill(pt, d);
666 float sg = trc.
trIBOut.getCovarElem(ip, ip) + trc.
trOBInw.getCovarElem(ip, ip);
668 auto pull = d / std::sqrt(sg);
671 mHMan->
getHisto2F(12000 + ip * 10 + 5)->Fill(pt, pull);
672 mHMan->
getHisto2F(13000 + ip * 10 + 5)->Fill(trc.
track.getTgl(), pull);
678void CheckResidSpec::bookHistos()
681 mHManV.emplace_back() = std::make_unique<o2::HistoManager>(
"", fmt::format(
"{}_hman.root",
params.outname));
682 mHMan = mHManV.back().get();
683 mHMan->SetName(
params.outname.c_str());
684 auto defLogAxis = [](
float xMn,
float xMx,
int nbin) {
685 if (xMn <= 0 || xMx <= xMn || nbin < 2) {
686 LOGP(fatal,
"Wrong log axis request: xmin = {} xmax = {} nbins = {}", xMn, xMx, nbin);
688 auto dx = std::log(xMx / xMn) / nbin;
689 std::vector<double> xax(nbin + 1);
690 for (
int i = 0;
i <= nbin;
i++) {
691 xax[
i] = xMn * std::exp(dx *
i);
695 float minPt = std::max(0.1f,
params.minPt), maxPt = std::min(50.f,
params.maxPt);
696 auto ptax = defLogAxis(minPt, maxPt,
params.nBinsPt);
698 for (
int il = 0; il < 8; il++) {
699 std::string lrName = il == 0 ?
"Vtx" : fmt::format(
"Lr{}", il - 1);
700 for (
int iyz = 0; iyz < 2; iyz++) {
701 std::string dname = iyz == 0 ?
"dy" :
"dz", dtit = iyz == 0 ?
"#DeltaY" :
"#DeltaZ";
702 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, -
params.maxDYZ[il],
params.maxDYZ[il]);
703 mHMan->
addHisto(h2, il * 10 + iyz * 100);
704 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);
705 mHMan->
addHisto(h2p, il * 10 + iyz * 100 + 5);
707 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, -
params.maxDYZ[il],
params.maxDYZ[il]);
708 mHMan->
addHisto(hz2, il * 10 + iyz * 100 + 1000);
709 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);
710 mHMan->
addHisto(hz2p, il * 10 + iyz * 100 + 5 + 1000);
712 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, -
params.maxDYZ[il],
params.maxDYZ[il]);
713 mHMan->
addHisto(hpt2, il * 10 + iyz * 100 + 2000);
714 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);
715 mHMan->
addHisto(hpt2p, il * 10 + iyz * 100 + 5 + 2000);
717 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, -
params.maxDYZ[il],
params.maxDYZ[il]);
718 mHMan->
addHisto(htgl2, il * 10 + iyz * 100 + 3000);
719 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);
720 mHMan->
addHisto(htgl2p, il * 10 + iyz * 100 + 5 + 3000);
724 for (
int ip = 0; ip < 5; ip++) {
725 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]);
726 mHMan->
addHisto(h2, 10000 + ip * 10);
727 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);
728 mHMan->
addHisto(h2p, 10000 + ip * 10 + 5);
730 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]);
731 mHMan->
addHisto(hz2, 11000 + ip * 10);
732 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);
733 mHMan->
addHisto(hz2p, 11000 + ip * 10 + 5);
735 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]);
736 mHMan->
addHisto(hpt2, 12000 + ip * 10);
737 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);
738 mHMan->
addHisto(hpt2p, 12000 + ip * 10 + 5);
740 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]);
741 mHMan->
addHisto(htgl2, 13000 + ip * 10);
742 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);
743 mHMan->
addHisto(htgl2p, 13000 + ip * 10 + 5);
749 mHMan->
addHisto(
new TH1F(
"pvN",
"PV Contributors;Nc;",
params.maxHPVN, 1.5,
params.maxHPVN + 1.5), 20000 + 3);
752void CheckResidSpec::postProcessHistos()
754 printf(
"Fitting histos\n");
756 if (mHManV.empty()) {
757 LOGP(warn,
"nothing to process");
760 mHMan = mHManV[0].get();
763 auto gs =
new TF1(
"gs",
"gaus", -1, 1);
764 int maxH = mPostProcOnly ? mHManV.size() : 1;
766 for (
int ihm = 0; ihm < maxH; ihm++) {
767 auto* histm = mHManV[ihm].get();
768 auto fitSlices = [&](
int id) {
769 auto h2 = histm->getHisto2F(
id);
770 if (!h2 || h2->GetEntries() <
params.minHistoStat2Fit) {
773 h2->FitSlicesY(gs, 0, -1, 0,
"QNR", &arr);
775 TH1* hmean = (TH1*)arr.RemoveAt(1);
777 hmean->SetTitle(Form(
"<%s>", h2->GetTitle()));
778 histm->addHisto(hmean,
id + 1);
780 TH1* hsig = (TH1*)arr.RemoveAt(2);
782 hsig->SetTitle(Form(
"#sigma(%s)", h2->GetTitle()));
783 histm->addHisto(hsig,
id + 2);
786 for (
int ioffs = 0; ioffs <= 3; ioffs++) {
787 int offs = ioffs * 1000;
788 for (
int iht = 0; iht < 2; iht++) {
789 int offsV = iht == 0 ? 0 : 5;
790 for (
int il = 0; il < 8; il++) {
791 for (
int iyz = 0; iyz < 2; iyz++) {
792 fitSlices(il * 10 + iyz * 100 + offsV + offs);
795 for (
int ip = 0; ip < 5; ip++) {
796 fitSlices(10000 + ip * 10 + offsV + offs);
805void CheckResidSpec::drawHistos()
807 gROOT->SetBatch(
true);
808 gStyle->SetTitleX(0.2);
809 gStyle->SetTitleY(0.88);
810 gStyle->SetTitleW(0.25);
811 gStyle->SetOptStat(0);
812 int nhm = mHManV.size();
813 std::array<unsigned int, 3> hcol{EColor::kRed, EColor::kBlue, EColor::kGreen + 2};
814 std::unique_ptr<TLegend> lg;
815 lg = std::make_unique<TLegend>(0.12, 0.13, 0.9, 0.13 + std::min(0.5f, nhm * 0.2f / 3.f));
817 lg->SetBorderSize(0);
818 for (
int i = 0;
i < nhm;
i++) {
819 auto hman = mHManV[
i].get();
820 if (!hman || hman->GetLast() < 1) {
823 hman->setMarkerStyle(20 +
i + (
i % 2) * 4, 0.5);
824 hman->setColor(hcol[
i % hcol.size()]);
825 auto le = lg->AddEntry(hman->getHisto(1), hman->GetName(),
"lp");
826 le->SetTextColor(hcol[
i % hcol.size()]);
828 TCanvas cly(
"cly",
"", 600, 800), clz(
"clz",
"", 600, 800), clpar(
"clpar",
"", 600, 800);
829 TCanvas czly(
"czly",
"", 600, 800), czlz(
"czlz",
"", 600, 800), czlpar(
"czlpar",
"", 600, 800);
832 auto AddLabel = [](
const char* txt,
float x = 0.1,
float y = 0.9,
int color = kBlack,
float size = 0.04) {
833 TLatex* lt =
new TLatex(
x,
y, txt);
835 lt->SetTextColor(
color);
836 lt->SetTextSize(
size);
841 auto drawResLr = [
this](TCanvas& canv,
int offs,
const float resMM[8],
bool logX) {
844 int nh = this->mHManV.size();
845 for (
int i = 0;
i < 8;
i++) {
848 for (
int j = 0;
j < nh;
j++) {
849 auto hman = this->mHManV[
j].get();
850 if (!hman || hman->GetLast() < 1) {
853 if (
auto histo = hman->getHisto(10 *
i + offs)) {
854 histo->Draw(same ?
"same" :
"");
856 histo->SetMinimum(-resMM[
i]);
857 histo->SetMaximum(resMM[
i]);
867 auto drawResPar = [
this](TCanvas& canv,
int offs,
const float resMM[8],
bool logX) {
870 int nh = this->mHManV.size();
871 for (
int i = 0;
i < 5;
i++) {
874 for (
int j = 0;
j < nh;
j++) {
875 auto hman = this->mHManV[
j].get();
876 if (!hman || hman->GetLast() < 1) {
879 if (
auto histo = hman->getHisto(10 *
i + offs)) {
880 histo->Draw(same ?
"same" :
"");
882 histo->SetMinimum(-resMM[
i]);
883 histo->SetMaximum(resMM[
i]);
893 cly.Print(Form(
"%s_hman.pdf[",
params.outname.c_str()));
894 drawResLr(cly, 1,
params.resMMLrY,
false);
897 AddLabel(
"Y residuals", 0.1, 0.95);
898 cly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
900 drawResLr(clz, 101,
params.resMMLrZ,
false);
903 AddLabel(
"Z residuals", 0.1, 0.95);
904 clz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
906 drawResLr(czly, 1001,
params.resMMLrY,
false);
909 AddLabel(
"Y residuals", 0.1, 0.95);
910 czly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
912 drawResLr(czlz, 1101,
params.resMMLrZ,
false);
915 AddLabel(
"Z residuals", 0.1, 0.95);
916 czlz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
918 drawResLr(czly, 2001,
params.resMMLrY,
true);
921 AddLabel(
"Y residuals", 0.1, 0.95);
922 czly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
924 drawResLr(czlz, 2101,
params.resMMLrZ,
true);
927 AddLabel(
"Z residuals", 0.1, 0.95);
928 czlz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
930 drawResLr(czly, 3001,
params.resMMLrY,
false);
933 AddLabel(
"Y residuals", 0.1, 0.95);
934 czly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
936 drawResLr(czlz, 3101,
params.resMMLrZ,
false);
939 AddLabel(
"Z residuals", 0.1, 0.95);
940 czlz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
942 drawResPar(clpar, 10001,
params.resMMPar,
false);
945 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
946 clpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
948 drawResPar(czlpar, 11001,
params.resMMPar,
false);
951 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
952 czlpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
954 drawResPar(czlpar, 12001,
params.resMMPar,
true);
957 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
958 czlpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
960 drawResPar(czlpar, 13001,
params.resMMPar,
false);
963 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
964 czlpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
966 cly.Print(Form(
"%s_hman.pdf]",
params.outname.c_str()));
988 mMeanVertexUpdated =
true;
992 LOG(info) <<
"cluster dictionary updated";
1000 std::vector<OutputSpec> outputs;
1001 auto dataRequest = std::make_shared<DataRequest>();
1002 dataRequest->setITSPerLayer(itsStag);
1003 if (!drawOnly && !postProcOnly) {
1005 dataRequest->requestTracks(srcTracks, useMC);
1006 dataRequest->requestClusters(srcClusters, useMC);
1007 dataRequest->requestPrimaryVertices(useMC);
1008 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
1010 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,
1016 dataRequest->inputs,
true);
1020 {
"nthreads", VariantType::Int, 1, {
"number of threads"}},
1021 {
"no-tree", VariantType::Bool,
false, {
"do not fill residuals tree"}},
1022 {
"no-hist", VariantType::Bool,
false, {
"do not fill residuals histograms"}},
1023 {
"draw-report", VariantType::Bool,
false, {
"fill residuals report"}},
1031 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
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
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
GLenum const GLfloat * params
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
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 TrackingFrameInfo *const const Cluster *const const float const float bz
const bool const int TrackITSInternal< NLayers > & track
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
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"