17#include <TStopwatch.h>
48#include <TLegendEntry.h>
79 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mDrawOnly(drawOnly), mPostProcOnly(postProcOnly)
91 bool refitPV(
o2::dataformats::PrimaryVertex& pv,
int vid);
93 bool processITSTrack(const
o2::its::
TrackITS& iTrack, const
o2::dataformats::PrimaryVertex& pv,
o2::checkresid::
Track& resTrack,
o2::track::
PID pid);
95 void fillHistos(const
o2::checkresid::
Track& trc);
96 void postProcessHistos();
99 o2::globaltracking::RecoContainer* mRecoData =
nullptr;
101 bool mMeanVertexUpdated = false;
102 float mITSROFrameLengthMUS = 0.
f;
103 o2::dataformats::MeanVertexObject mMeanVtx{};
104 std::vector<o2::BaseCluster<float>> mITSClustersArray;
107 std::shared_ptr<DataRequest> mDataRequest;
108 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
109 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
112 bool mDrawOnly =
false;
113 bool mPostProcOnly =
false;
115 bool mFillHistos =
true;
116 bool mFillTree =
true;
117 std::vector<std::unique_ptr<o2::HistoManager>> mHManV{};
118 std::vector<o2::dataformats::PrimaryVertex> mPVUsed;
126 mDraw = ic.
options().
get<
bool>(
"draw-report");
127 mFillHistos = !ic.
options().
get<
bool>(
"no-hist");
128 mFillTree = !ic.
options().
get<
bool>(
"no-tree");
129 mNThreads = ic.
options().
get<
int>(
"nthreads");
134 std::string nm =
params.outname;
141 if (!mDrawOnly && mFillHistos) {
144 if (!
params.ext_hm_list.empty()) {
148 if (vecNames.size() != vecLegends.size()) {
149 LOGP(warn,
"{} legend names provided for {} external histomanagers, will use file names as legends", vecLegends.size(), vecNames.size());
153 for (
const auto& vn : vecNames) {
154 LOGP(info,
"Loading external HistoManager {}", vn);
155 mHManV.emplace_back() = std::make_unique<o2::HistoManager>(
"", vn,
true);
156 auto hm = mHManV.back().get();
158 LOGP(error,
"Failed to load histograms from {}", vn);
161 hm->SetName(useLeg ? vecLegends[cntH].c_str() : vn.c_str());
172 LOGP(warn,
"No OpenMP");
177 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(fmt::format(
"{}.root",
params.outname).c_str(),
"recreate");
199 mRecoData = &recoData;
201 mRecoData = &recoData;
202 updateTimeDependentParams(pc);
211 static bool initOnceDone =
false;
218 if (!grp->isDetContinuousReadOut(
DetID::ITS)) {
219 mITSROFrameLengthMUS = alpParams.roFrameLengthTrig / 1.e3;
228 if (mMeanVertexUpdated) {
229 mMeanVertexUpdated =
false;
238 LOGP(fatal,
"ITS data is not loaded");
246 auto pattIt = patterns.begin();
247 mITSClustersArray.clear();
248 mITSClustersArray.reserve(clusITS.size());
256 static int TFCount = 0;
257 int nv = vtxRefs.size() - 1;
258 std::vector<std::vector<checkresid::Track>> slots;
260 slots.resize(mNThreads);
261 int nvGood = 0, nvUse = 0, nvRefFail = 0;
262 long pvFitDuration{};
263 for (
int iv = 0; iv < nv; iv++) {
264 const auto& vtref = vtxRefs[iv];
265 auto pve = pvvec[iv];
266 if (pve.getNContributors() <
params.minPVContributors) {
271 LOGP(
debug,
"Refitting PV#{} of {} tracks", iv, pve.getNContributors());
272 auto tStartPVF = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
273 bool res = refitPV(pve, iv);
274 pvFitDuration += std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count() - tStartPVF;
281 mPVUsed.push_back(pve);
282 const auto& itsContRefs = vtref.getITSGloContributors();
283 int idMinITSGlo = 0, idMaxITSGlo = 0;
284 if (
params.useITSGloContributors) {
285 if (itsContRefs.getFirstEntry() < vtref.getEntries() && itsContRefs.getEntries() == 0) {
286 LOGP(fatal,
"Usage of stored ITS global contributors is requested but they are missing");
288 idMinITSGlo = itsContRefs.getFirstEntry();
289 idMaxITSGlo = idMinITSGlo + itsContRefs.getEntries();
296 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
302#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
304 for (
int i = idMin;
i < idMax;
i++) {
305 auto vid = trackIndex[
i];
306 bool pvCont = vid.isPVContributor();
307 if (!pvCont && (
params.pvcontribOnly ||
params.useITSGloContributors)) {
312 if (
params.useITSGloContributors) {
313 int id = idMinITSGlo + cntPVCont;
314 if (
id >= idMaxITSGlo) {
315 LOGP(fatal,
"Calculated GlobalContributor ITS track index {} exceeds number of stored indices {}",
id, itsContRefs.getEntries());
317 pidITS = trackIndex[
id].getSource();
326 const auto& itsTrack = mRecoData->
getITSTrack(gidITS);
327 if (itsTrack.getNClusters() <
params.minITSCl) {
331 if (!
params.useITSGloContributors) {
332 pidITS = trc.getPID();
334 auto pt = trc.getPt();
335 if (pt < params.minPt || pt >
params.maxPt) {
338 if (std::abs(trc.getTgl()) >
params.maxTgl) {
342 auto& accum = slots[omp_get_thread_num()];
344 auto& accum = slots[0];
346 auto& resTrack = accum.emplace_back();
348 if (!processITSTrack(itsTrack, pve, resTrack, pidITS)) {
356 for (
const auto& accum : slots) {
357 for (
const auto& tr : accum) {
359 (*mDBGOut) <<
"res" <<
"tr=" << tr <<
"\n";
367 (*mDBGOut) <<
"pvUsed" <<
"pv=" << mPVUsed <<
"\n";
370 for (
const auto& pv : mPVUsed) {
371 mHMan->
getHisto(20000 + 0)->Fill(pv.getX());
372 mHMan->
getHisto(20000 + 1)->Fill(pv.getY());
373 mHMan->
getHisto(20000 + 2)->Fill(pv.getZ());
374 mHMan->
getHisto(20000 + 3)->Fill(pv.getNContributors());
377 LOGP(info,
"processed {} PVs out of {} good vertices (out of {} in total), PV refits took {} mus, {} refits failed", nvUse, nvGood, nv, pvFitDuration, nvRefFail);
384 auto trFitInw = iTrack.getParamOut();
385 auto trFitOut = iTrack.getParamIn();
386 trFitInw.setPID(pid);
387 trFitOut.setPID(pid);
391 float bz = prop->getNominalBz();
392 std::array<const o2::BaseCluster<float>*, 8> clArr{};
394 std::array<o2::track::TrackParCov, 8> extrapOut, extrapInw;
397 return refLin ? tr.rotate(
alpha, *refLin, bz) : tr.rotate(
alpha);
402 if (!rotateTrack(tr,
i == 0 ? pvAlpha : geom->getSensorRefAlpha(clArr[
i]->getSensorID()), refLin) ||
403 !prop->propagateTo(tr, refLin, clArr[
i]->getX(), true)) {
407 if (!tr.update(*clArr[
i])) {
411 extrapDest[
i].invalidate();
417 auto inv2d = [](
float s00,
float s11,
float s01) -> std::array<float, 3> {
418 auto det = s00 * s11 - s01 * s01;
420 LOGP(error,
"Singular det {}, input: {} {} {}", det, s00, s11, s01);
421 return {0.f, 0.f, 0.f};
424 return {s11 * det, s00 * det, -s01 * det};
428 if (!prop->propagateToDCA(pv, trFitOut, bz)) {
429 LOGP(
debug,
"Failed to propagateToDCA, {}", trFitOut.asString());
433 if (
params.addPVAsCluster) {
434 float cosAlp, sinAlp;
435 pvAlpha = trFitOut.getAlpha();
436 o2::math_utils::sincos(trFitOut.getAlpha(), sinAlp, cosAlp);
437 bcPV.
setXYZ(pv.getX() * cosAlp + pv.getY() * sinAlp, -pv.getX() * sinAlp + pv.getY() * cosAlp, pv.getZ());
438 bcPV.
setSigmaY2(0.5 * (pv.getSigmaX2() + pv.getSigmaY2()));
444 int nCl = iTrack.getNClusters();
445 for (
int i = 0;
i <
nCl;
i++) {
446 const auto& curClu = mITSClustersArray[itsClRefs[iTrack.
getClusterEntry(
i)]];
448 int llr = geom->getLayer(curClu.getSensorID());
449 if (clArr[1 + llr]) {
450 LOGP(error,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), curClu.getSensorID());
452 clArr[1 + geom->getLayer(curClu.getSensorID())] = &curClu;
455 o2::track::TrackPar refLinIBOut0, refLinOBInw0, *refLinOBInw =
nullptr, *refLinIBOut =
nullptr;
456 if (
params.useStableRef) {
457 refLinOut = &(refLinOut0 = trFitOut);
458 refLinInw = &(refLinInw0 = trFitInw);
460 trFitOut.resetCovariance();
461 trFitOut.setCov(trFitOut.getQ2Pt() * trFitOut.getQ2Pt() * trFitOut.getCov()[14], 14);
462 trFitInw.resetCovariance();
463 trFitInw.setCov(trFitInw.getQ2Pt() * trFitInw.getQ2Pt() * trFitInw.getCov()[14], 14);
465 for (
int i = 0;
i <= 7;
i++) {
468 if (!(resOut = accountCluster(
i, extrapOut, trFitOut, refLinOut)) || !(resInw = accountCluster(7 -
i, extrapInw, trFitInw, refLinInw))) {
474 if (
i == 3 && resOut == 1 && resInw == 1 &&
params.doIBOB && nCl == 7) {
479 refLinIBOut = &(refLinIBOut0 = refLinOut0);
480 refLinOBInw = &(refLinOBInw0 = refLinInw0);
483 if (!resTrack.
trOBInw.getXatLabR(
params.rCompIBOB, xRref, bz) ||
484 !prop->propagateTo(resTrack.
trOBInw, refLinOBInw, xRref,
true) ||
485 !rotateTrack(resTrack.
trOBInw, resTrack.
trOBInw.getPhiPos(), refLinOBInw) ||
486 !rotateTrack(resTrack.
trIBOut, resTrack.
trOBInw.getAlpha(), refLinIBOut) ||
487 !prop->propagateTo(resTrack.
trIBOut, refLinIBOut, resTrack.
trOBInw.getX(),
true)) {
494 bool innerDone =
false;
496 for (
int i = 0;
i <= 7;
i++) {
499 const auto &tInw = extrapInw[
i], &tOut = extrapOut[
i];
500 auto wInw = inv2d(tInw.getSigmaY2(), tInw.getSigmaZ2(), tInw.getSigmaZY());
501 auto wOut = inv2d(tOut.getSigmaY2(), tOut.getSigmaZ2(), tOut.getSigmaZY());
502 if (wInw[0] == 0.f || wOut[0] == 0.f) {
505 std::array<float, 3> wTot = {wInw[0] + wOut[0], wInw[1] + wOut[1], wInw[2] + wOut[2]};
506 auto cTot = inv2d(wTot[0], wTot[1], wTot[2]);
507 auto ywi = wInw[0] * tInw.getY() + wInw[2] * tInw.getZ() + wOut[0] * tOut.getY() + wOut[2] * tOut.getZ();
508 auto zwi = wInw[2] * tInw.getY() + wInw[1] * tInw.getZ() + wOut[2] * tOut.getY() + wOut[1] * tOut.getZ();
509 auto yw = ywi * cTot[0] + zwi * cTot[2];
510 auto zw = ywi * cTot[2] + zwi * cTot[1];
512 auto phi =
i == 0 ? tInw.getPhi() : tInw.getPhiPos();
513 o2::math_utils::bringTo02Pi(phi);
514 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);
516 resTrack.
track = tInw;
520 LOGP(
debug,
"No cluster on lr {}",
i);
530 std::vector<o2::track::TrackParCov>
tracks;
531 std::vector<bool> useTrack;
532 std::vector<GTrackID> gidsITS;
533 int ntr = pv.getNContributors(), ntrIni = ntr;
535 useTrack.reserve(ntr);
536 gidsITS.reserve(ntr);
539 const auto& itsContRefs = vtref.getITSGloContributors();
540 if (
params.useITSGloContributors && itsContRefs.getEntries()) {
541 int itr = itsContRefs.getFirstEntry(), itLim = itr + itsContRefs.getEntries();
542 for (; itr < itLim; itr++) {
543 auto tid = trackIndex[itr];
544 tracks.emplace_back().setPID(tid.getSource());
548 int itr = vtref.getFirstEntry(), itLim = itr + vtref.getEntries();
549 for (; itr < itLim; itr++) {
550 auto tid = trackIndex[itr];
558 useTrack.resize(ntr);
560#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
562 for (
int itr = 0; itr < ntr; itr++) {
563 if (!(useTrack[itr] = refitITStrack(tracks[itr], gidsITS[itr]))) {
568 for (
auto v : useTrack) {
572 LOGP(warn,
"Abandon vertex refit: NcontribNew = {} vs NcontribOld = {}", ntr, ntrIni);
575 LOGP(
debug,
"Original vtx: Nc:{} {}, chi2={}", pv.getNContributors(), pv.
asString(), pv.getChi2());
578 LOGP(
debug,
"Refitted vtx: Nc:{} {}, chi2={}", ntr, pv.
asString(), pv.getChi2());
579 if (pv.getChi2() < 0.f) {
580 LOGP(warn,
"Failed to refit PV {}", pvSave.asString());
592 auto pid = track.getPID();
593 track = trkITS.getParamOut();
594 track.resetCovariance();
595 track.setCov(track.getQ2Pt() * track.getQ2Pt() * track.getCov()[14], 14);
597 auto nCl = trkITS.getNumberOfClusters();
600 float bz = prop->getNominalBz();
603 for (
int iCl = 0; iCl <
nCl; iCl++) {
604 const auto& cls = mITSClustersArray[itsClRefs[trkITS.getClusterEntry(iCl)]];
605 auto alpha = geom->getSensorRefAlpha(cls.getSensorID());
606 if (!(
params.useStableRef ? track.rotate(
alpha, refLin, bz) : track.rotate(
alpha)) ||
607 !prop->propagateTo(track,
params.useStableRef ? &refLin : nullptr, cls.
getX(), true)) {
608 LOGP(
debug,
"refitITStrack failed on propagation to cl#{}, alpha={}, x={} | {}", iCl,
alpha, cls.getX(), track.asString());
611 if (!track.update(cls)) {
612 LOGP(
debug,
"refitITStrack failed on update with cl#{}, | {}", iCl, track.asString());
622 int np = trc.
points.size();
623 auto pt = trc.
track.getPt();
624 if (pt < params.minPt || pt >
params.maxPt) {
627 for (
int ip = 0; ip < np; ip++) {
628 const auto& pnt = trc.
points[ip];
629 int il = pnt.lr >= 0 ? pnt.lr + 1 : 0;
630 mHMan->
getHisto2F(il * 10 + 0 * 100)->Fill(pnt.phi, pnt.dy);
631 mHMan->
getHisto2F(il * 10 + 0 * 100 + 1000)->Fill(pnt.z, pnt.dy);
632 mHMan->
getHisto2F(il * 10 + 0 * 100 + 2000)->Fill(pt, pnt.dy);
633 mHMan->
getHisto2F(il * 10 + 0 * 100 + 3000)->Fill(trc.
track.getTgl(), pnt.dy);
635 auto pull = pnt.dy / std::sqrt(pnt.sig2y);
636 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5)->Fill(pnt.phi, pull);
637 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5 + 1000)->Fill(pnt.z, pull);
638 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5 + 2000)->Fill(pt, pull);
639 mHMan->
getHisto2F(il * 10 + 0 * 100 + 5 + 3000)->Fill(trc.
track.getTgl(), pull);
641 mHMan->
getHisto2F(il * 10 + 1 * 100)->Fill(pnt.phi, pnt.dz);
642 mHMan->
getHisto2F(il * 10 + 1 * 100 + 1000)->Fill(pnt.z, pnt.dz);
643 mHMan->
getHisto2F(il * 10 + 1 * 100 + 2000)->Fill(pt, pnt.dz);
644 mHMan->
getHisto2F(il * 10 + 1 * 100 + 3000)->Fill(trc.
track.getTgl(), pnt.dz);
646 auto pull = pnt.dz / std::sqrt(pnt.sig2z);
647 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5)->Fill(pnt.phi, pull);
648 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5 + 1000)->Fill(pnt.z, pull);
649 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5 + 2000)->Fill(pt, pull);
650 mHMan->
getHisto2F(il * 10 + 1 * 100 + 5 + 3000)->Fill(trc.
track.getTgl(), pull);
655 for (
int ip = 0; ip < 5; ip++) {
659 mHMan->
getHisto2F(12000 + ip * 10)->Fill(pt, d);
661 float sg = trc.
trIBOut.getCovarElem(ip, ip) + trc.
trOBInw.getCovarElem(ip, ip);
663 auto pull = d / std::sqrt(sg);
666 mHMan->
getHisto2F(12000 + ip * 10 + 5)->Fill(pt, pull);
667 mHMan->
getHisto2F(13000 + ip * 10 + 5)->Fill(trc.
track.getTgl(), pull);
673void CheckResidSpec::bookHistos()
676 mHManV.emplace_back() = std::make_unique<o2::HistoManager>(
"", fmt::format(
"{}_hman.root",
params.outname));
677 mHMan = mHManV.back().get();
678 mHMan->SetName(
params.outname.c_str());
679 auto defLogAxis = [](
float xMn,
float xMx,
int nbin) {
680 if (xMn <= 0 || xMx <= xMn || nbin < 2) {
681 LOGP(fatal,
"Wrong log axis request: xmin = {} xmax = {} nbins = {}", xMn, xMx, nbin);
683 auto dx = std::log(xMx / xMn) / nbin;
684 std::vector<double> xax(nbin + 1);
685 for (
int i = 0;
i <= nbin;
i++) {
686 xax[
i] = xMn * std::exp(dx *
i);
690 float minPt = std::max(0.1f,
params.minPt), maxPt = std::min(50.f,
params.maxPt);
691 auto ptax = defLogAxis(minPt, maxPt,
params.nBinsPt);
693 for (
int il = 0; il < 8; il++) {
694 std::string lrName = il == 0 ?
"Vtx" : fmt::format(
"Lr{}", il - 1);
695 for (
int iyz = 0; iyz < 2; iyz++) {
696 std::string dname = iyz == 0 ?
"dy" :
"dz", dtit = iyz == 0 ?
"#DeltaY" :
"#DeltaZ";
697 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]);
698 mHMan->
addHisto(h2, il * 10 + iyz * 100);
699 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);
700 mHMan->
addHisto(h2p, il * 10 + iyz * 100 + 5);
702 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]);
703 mHMan->
addHisto(hz2, il * 10 + iyz * 100 + 1000);
704 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);
705 mHMan->
addHisto(hz2p, il * 10 + iyz * 100 + 5 + 1000);
707 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]);
708 mHMan->
addHisto(hpt2, il * 10 + iyz * 100 + 2000);
709 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);
710 mHMan->
addHisto(hpt2p, il * 10 + iyz * 100 + 5 + 2000);
712 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]);
713 mHMan->
addHisto(htgl2, il * 10 + iyz * 100 + 3000);
714 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);
715 mHMan->
addHisto(htgl2p, il * 10 + iyz * 100 + 5 + 3000);
719 for (
int ip = 0; ip < 5; ip++) {
720 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]);
721 mHMan->
addHisto(h2, 10000 + ip * 10);
722 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);
723 mHMan->
addHisto(h2p, 10000 + ip * 10 + 5);
725 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]);
726 mHMan->
addHisto(hz2, 11000 + ip * 10);
727 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);
728 mHMan->
addHisto(hz2p, 11000 + ip * 10 + 5);
730 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]);
731 mHMan->
addHisto(hpt2, 12000 + ip * 10);
732 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);
733 mHMan->
addHisto(hpt2p, 12000 + ip * 10 + 5);
735 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]);
736 mHMan->
addHisto(htgl2, 13000 + ip * 10);
737 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);
738 mHMan->
addHisto(htgl2p, 13000 + ip * 10 + 5);
744 mHMan->
addHisto(
new TH1F(
"pvN",
"PV Contributors;Nc;",
params.maxHPVN, 1.5,
params.maxHPVN + 1.5), 20000 + 3);
747void CheckResidSpec::postProcessHistos()
749 printf(
"Fitting histos\n");
751 if (mHManV.empty()) {
752 LOGP(warn,
"nothing to process");
755 mHMan = mHManV[0].get();
758 auto gs =
new TF1(
"gs",
"gaus", -1, 1);
759 int maxH = mPostProcOnly ? mHManV.size() : 1;
761 for (
int ihm = 0; ihm < maxH; ihm++) {
762 auto* histm = mHManV[ihm].get();
763 auto fitSlices = [&](
int id) {
764 auto h2 = histm->getHisto2F(
id);
765 if (!h2 || h2->GetEntries() <
params.minHistoStat2Fit) {
768 h2->FitSlicesY(gs, 0, -1, 0,
"QNR", &arr);
770 TH1* hmean = (TH1*)arr.RemoveAt(1);
772 hmean->SetTitle(Form(
"<%s>", h2->GetTitle()));
773 histm->addHisto(hmean,
id + 1);
775 TH1* hsig = (TH1*)arr.RemoveAt(2);
777 hsig->SetTitle(Form(
"#sigma(%s)", h2->GetTitle()));
778 histm->addHisto(hsig,
id + 2);
781 for (
int ioffs = 0; ioffs <= 3; ioffs++) {
782 int offs = ioffs * 1000;
783 for (
int iht = 0; iht < 2; iht++) {
784 int offsV = iht == 0 ? 0 : 5;
785 for (
int il = 0; il < 8; il++) {
786 for (
int iyz = 0; iyz < 2; iyz++) {
787 fitSlices(il * 10 + iyz * 100 + offsV + offs);
790 for (
int ip = 0; ip < 5; ip++) {
791 fitSlices(10000 + ip * 10 + offsV + offs);
800void CheckResidSpec::drawHistos()
802 gROOT->SetBatch(
true);
803 gStyle->SetTitleX(0.2);
804 gStyle->SetTitleY(0.88);
805 gStyle->SetTitleW(0.25);
806 gStyle->SetOptStat(0);
807 int nhm = mHManV.size();
808 std::array<unsigned int, 3> hcol{EColor::kRed, EColor::kBlue, EColor::kGreen + 2};
809 std::unique_ptr<TLegend> lg;
810 lg = std::make_unique<TLegend>(0.12, 0.13, 0.9, 0.13 + std::min(0.5f, nhm * 0.2f / 3.f));
812 lg->SetBorderSize(0);
813 for (
int i = 0;
i < nhm;
i++) {
814 auto hman = mHManV[
i].get();
815 if (!hman || hman->GetLast() < 1) {
818 hman->setMarkerStyle(20 +
i + (
i % 2) * 4, 0.5);
819 hman->setColor(hcol[
i % hcol.size()]);
820 auto le = lg->AddEntry(hman->getHisto(1), hman->GetName(),
"lp");
821 le->SetTextColor(hcol[
i % hcol.size()]);
823 TCanvas cly(
"cly",
"", 600, 800), clz(
"clz",
"", 600, 800), clpar(
"clpar",
"", 600, 800);
824 TCanvas czly(
"czly",
"", 600, 800), czlz(
"czlz",
"", 600, 800), czlpar(
"czlpar",
"", 600, 800);
827 auto AddLabel = [](
const char* txt,
float x = 0.1,
float y = 0.9,
int color = kBlack,
float size = 0.04) {
828 TLatex* lt =
new TLatex(
x,
y, txt);
830 lt->SetTextColor(
color);
831 lt->SetTextSize(
size);
836 auto drawResLr = [
this](TCanvas& canv,
int offs,
const float resMM[8],
bool logX) {
839 int nh = this->mHManV.size();
840 for (
int i = 0;
i < 8;
i++) {
843 for (
int j = 0;
j < nh;
j++) {
844 auto hman = this->mHManV[
j].get();
845 if (!hman || hman->GetLast() < 1) {
848 if (
auto histo = hman->getHisto(10 *
i + offs)) {
849 histo->Draw(same ?
"same" :
"");
851 histo->SetMinimum(-resMM[
i]);
852 histo->SetMaximum(resMM[
i]);
862 auto drawResPar = [
this](TCanvas& canv,
int offs,
const float resMM[8],
bool logX) {
865 int nh = this->mHManV.size();
866 for (
int i = 0;
i < 5;
i++) {
869 for (
int j = 0;
j < nh;
j++) {
870 auto hman = this->mHManV[
j].get();
871 if (!hman || hman->GetLast() < 1) {
874 if (
auto histo = hman->getHisto(10 *
i + offs)) {
875 histo->Draw(same ?
"same" :
"");
877 histo->SetMinimum(-resMM[
i]);
878 histo->SetMaximum(resMM[
i]);
888 cly.Print(Form(
"%s_hman.pdf[",
params.outname.c_str()));
889 drawResLr(cly, 1,
params.resMMLrY,
false);
892 AddLabel(
"Y residuals", 0.1, 0.95);
893 cly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
895 drawResLr(clz, 101,
params.resMMLrZ,
false);
898 AddLabel(
"Z residuals", 0.1, 0.95);
899 clz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
901 drawResLr(czly, 1001,
params.resMMLrY,
false);
904 AddLabel(
"Y residuals", 0.1, 0.95);
905 czly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
907 drawResLr(czlz, 1101,
params.resMMLrZ,
false);
910 AddLabel(
"Z residuals", 0.1, 0.95);
911 czlz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
913 drawResLr(czly, 2001,
params.resMMLrY,
true);
916 AddLabel(
"Y residuals", 0.1, 0.95);
917 czly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
919 drawResLr(czlz, 2101,
params.resMMLrZ,
true);
922 AddLabel(
"Z residuals", 0.1, 0.95);
923 czlz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
925 drawResLr(czly, 3001,
params.resMMLrY,
false);
928 AddLabel(
"Y residuals", 0.1, 0.95);
929 czly.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
931 drawResLr(czlz, 3101,
params.resMMLrZ,
false);
934 AddLabel(
"Z residuals", 0.1, 0.95);
935 czlz.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
937 drawResPar(clpar, 10001,
params.resMMPar,
false);
940 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
941 clpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
943 drawResPar(czlpar, 11001,
params.resMMPar,
false);
946 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
947 czlpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
949 drawResPar(czlpar, 12001,
params.resMMPar,
true);
952 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
953 czlpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
955 drawResPar(czlpar, 13001,
params.resMMPar,
false);
958 AddLabel(
"IB-OB tracks params differences at R = 12 cm", 0.2, 0.8);
959 czlpar.Print(Form(
"%s_hman.pdf",
params.outname.c_str()));
961 cly.Print(Form(
"%s_hman.pdf]",
params.outname.c_str()));
983 mMeanVertexUpdated =
true;
987 LOG(info) <<
"cluster dictionary updated";
995 std::vector<OutputSpec> outputs;
996 auto dataRequest = std::make_shared<DataRequest>();
997 if (!drawOnly && !postProcOnly) {
999 dataRequest->requestTracks(srcTracks, useMC);
1000 dataRequest->requestClusters(srcClusters, useMC);
1001 dataRequest->requestPrimaryVertices(useMC);
1002 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
1004 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,
1010 dataRequest->inputs,
true);
1014 {
"nthreads", VariantType::Int, 1, {
"number of threads"}},
1015 {
"no-tree", VariantType::Bool,
false, {
"do not fill residuals tree"}},
1016 {
"no-hist", VariantType::Bool,
false, {
"do not fill residuals histograms"}},
1017 {
"draw-report", VariantType::Bool,
false, {
"fill residuals report"}},
1025 AlgorithmSpec{adaptFromTask<CheckResidSpec>(dataRequest, ggRequest, srcTracks, drawOnly, postProcOnly)},
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.
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 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)
create a processor spec
o2::dataformats::GlobalTrackID GTrackID
constexpr double LHCBunchSpacingNS
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
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
int int int float float float int nCl
const TrackingFrameInfo *const const Cluster *const const float const float bz
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
struct o2::upgrades_utils::@469 tracks
structure to keep trigger-related info
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() 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() 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"