17#include <TStopwatch.h>
66 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mUseMC(useMC)
83 bool refitPV(
o2::dataformats::PrimaryVertex& pv,
int vid);
85 bool processITSTrack(const
o2::its::
TrackITS& iTrack, const
o2::dataformats::PrimaryVertex& pv,
o2::checkresid::
Track& resTrack);
87 o2::globaltracking::RecoContainer* mRecoData =
nullptr;
89 bool mMeanVertexUpdated = false;
90 float mITSROFrameLengthMUS = 0.
f;
91 o2::dataformats::MeanVertexObject mMeanVtx{};
92 std::vector<o2::BaseCluster<float>> mITSClustersArray;
95 std::shared_ptr<DataRequest> mDataRequest;
96 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
98 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
107 std::string dbgnm = maxLanes == 1 ?
"checkResid.root" : fmt::format(
"checkResid_t{}.root", lane);
108 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(dbgnm.c_str(),
"recreate");
109 mNThreads = ic.
options().
get<
int>(
"nthreads");
112 LOGP(warn,
"No OpenMP");
122 mRecoData = &recoData;
124 mRecoData = &recoData;
125 updateTimeDependentParams(pc);
136 static bool initOnceDone =
false;
143 if (!grp->isDetContinuousReadOut(
DetID::ITS)) {
144 mITSROFrameLengthMUS = alpParams.roFrameLengthTrig / 1.e3;
153 if (mMeanVertexUpdated) {
154 mMeanVertexUpdated =
false;
157 bool updateMaps =
false;
180 LOGP(fatal,
"ITS data is not loaded");
188 auto pattIt = patterns.begin();
189 mITSClustersArray.clear();
190 mITSClustersArray.reserve(clusITS.size());
198 static int TFCount = 0;
199 int nv = vtxRefs.size() - 1;
200 std::vector<std::vector<checkresid::Track>> slots;
201 slots.resize(mNThreads);
202 int nvGood = 0, nvUse = 0, nvRefFail = 0;
203 long pvFitDuration{};
204 for (
int iv = 0; iv < nv; iv++) {
205 const auto& vtref = vtxRefs[iv];
206 auto pve = pvvec[iv];
207 if (pve.getNContributors() <
params.minPVContributors) {
212 LOGP(
debug,
"Refitting PV#{} of {} tracks", iv, pve.getNContributors());
213 auto tStartPVF = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
214 bool res = refitPV(pve, iv);
215 pvFitDuration += std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count() - tStartPVF;
226 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
232 LOGP(fatal,
"Cut on TPC tracks is requested by they are not loaded");
235#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
237 for (
int i = idMin;
i < idMax;
i++) {
238 auto vid = trackIndex[
i];
239 bool pvCont = vid.isPVContributor();
240 if (!pvCont &&
params.pvcontribOnly) {
251 auto pt = trc.getPt();
252 if (pt < params.minPt || pt >
params.maxPt) {
255 const auto& itsTrack = mRecoData->
getITSTrack(gidITS);
256 if (itsTrack.getNClusters() <
params.minITSCl) {
260 auto& accum = slots[omp_get_thread_num()];
262 auto& accum = slots[0];
264 auto& resTrack = accum.emplace_back();
266 if (!processITSTrack(itsTrack, pve, resTrack)) {
274 for (
const auto& accum : slots) {
275 for (
const auto& tr : accum) {
276 (*mDBGOut) <<
"res" <<
"tr=" << tr <<
"\n";
279 LOGP(info,
"processed {} PVs out of {} good vertices (out of {} in total), PV refits took {} mus, {} refits failed", nvUse, nvGood, nv, pvFitDuration, nvRefFail);
286 auto trFitInw = iTrack.getParamOut();
287 auto trFitOut = iTrack.getParamIn();
291 float bz = prop->getNominalBz();
292 std::array<const o2::BaseCluster<float>*, 8> clArr{};
294 std::array<o2::track::TrackParCov, 8> extrapOut, extrapInw;
297 return refLin ? tr.rotate(
alpha, *refLin, bz) : tr.rotate(
alpha);
302 if (!rotateTrack(tr,
i == 0 ? pvAlpha : geom->getSensorRefAlpha(clArr[
i]->getSensorID()), refLin) ||
303 !prop->propagateTo(tr, refLin, clArr[
i]->getX(), true)) {
307 if (!tr.update(*clArr[
i])) {
311 extrapDest[
i].invalidate();
317 auto inv2d = [](
float s00,
float s11,
float s01) -> std::array<float, 3> {
318 auto det = s00 * s11 - s01 * s01;
320 return {0.f, 0.f, 0.f};
323 return {s11 * det, s00 * det, -s01 * det};
327 if (!prop->propagateToDCA(pv, trFitOut, bz)) {
328 LOGP(
debug,
"Failed to propagateToDCA, {}", trFitOut.asString());
331 float cosAlp, sinAlp;
332 pvAlpha = trFitOut.getAlpha();
333 o2::math_utils::sincos(trFitOut.getAlpha(), sinAlp, cosAlp);
335 if (
params.addPVAsCluster) {
336 bcPV.
setXYZ(pv.getX() * cosAlp + pv.getY() * sinAlp, -pv.getX() * sinAlp + pv.getY() * cosAlp, pv.getZ());
337 bcPV.
setSigmaY2(0.5 * (pv.getSigmaX2() + pv.getSigmaY2()));
343 int nCl = iTrack.getNClusters();
344 for (
int i = 0;
i < nCl;
i++) {
345 const auto& curClu = mITSClustersArray[itsClRefs[iTrack.
getClusterEntry(
i)]];
347 int llr = geom->getLayer(curClu.getSensorID());
348 if (clArr[1 + llr]) {
349 LOGP(error,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), curClu.getSensorID());
351 clArr[1 + geom->getLayer(curClu.getSensorID())] = &curClu;
354 o2::track::TrackPar refLinIBOut0, refLinOBInw0, *refLinOBInw =
nullptr, *refLinIBOut =
nullptr;
355 if (
params.useStableRef) {
356 refLinOut = &(refLinOut0 = trFitOut);
357 refLinInw = &(refLinInw0 = trFitInw);
359 trFitOut.resetCovariance();
360 trFitOut.setCov(trFitOut.getQ2Pt() * trFitOut.getQ2Pt() * trFitOut.getCov()[14], 14);
361 trFitInw.resetCovariance();
362 trFitInw.setCov(trFitInw.getQ2Pt() * trFitInw.getQ2Pt() * trFitInw.getCov()[14], 14);
364 for (
int i = 0;
i <= 7;
i++) {
367 if (!(resOut = accountCluster(
i, extrapOut, trFitOut, refLinOut)) || !(resInw = accountCluster(7 -
i, extrapInw, trFitInw, refLinInw))) {
373 if (
i == 3 && resOut == 1 && resInw == 1 &&
params.doIBOB && nCl == 7) {
378 refLinIBOut = &(refLinIBOut0 = refLinOut0);
379 refLinOBInw = &(refLinOBInw0 = refLinInw0);
382 if (!resTrack.
trOBInw.getXatLabR(
params.rCompIBOB, xRref, bz) ||
383 !prop->propagateTo(resTrack.
trOBInw, refLinOBInw, xRref,
true) ||
384 !rotateTrack(resTrack.
trOBInw, resTrack.
trOBInw.getPhiPos(), refLinOBInw) ||
385 !rotateTrack(resTrack.
trIBOut, resTrack.
trOBInw.getAlpha(), refLinIBOut) ||
386 !prop->propagateTo(resTrack.
trIBOut, refLinIBOut, resTrack.
trOBInw.getX(),
true)) {
393 bool innerDone =
false;
395 for (
int i = 0;
i <= 7;
i++) {
398 const auto &tInw = extrapInw[
i], &tOut = extrapOut[
i];
399 auto wInw = inv2d(tInw.getSigmaY2(), tInw.getSigmaZ2(), tInw.getSigmaZY());
400 auto wOut = inv2d(tOut.getSigmaY2(), tOut.getSigmaZ2(), tOut.getSigmaZY());
401 if (wInw[0] == 0.f || wOut[0] == 0.f) {
404 std::array<float, 3> wTot = {wInw[0] + wOut[0], wInw[1] + wOut[1], wInw[2] + wOut[2]};
405 auto cTot = inv2d(wTot[0], wTot[1], wTot[2]);
406 auto ywi = wInw[0] * tInw.getY() + wInw[2] * tInw.getZ() + wOut[0] * tOut.getY() + wOut[2] * tOut.getZ();
407 auto zwi = wInw[2] * tInw.getY() + wInw[1] * tInw.getZ() + wOut[2] * tOut.getY() + wOut[1] * tOut.getZ();
408 auto yw = ywi * cTot[0] + zwi * cTot[2];
409 auto zw = ywi * cTot[2] + zwi * cTot[1];
411 auto phi =
i == 0 ? tInw.getPhi() : tInw.getPhiPos();
412 o2::math_utils::bringTo02Pi(phi);
413 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);
415 resTrack.
track = tInw;
419 LOGP(
debug,
"No cluster on lr {}",
i);
429 std::vector<o2::track::TrackParCov>
tracks;
430 std::vector<bool> useTrack;
431 std::vector<GTrackID> gidsITS;
432 int ntr = pv.getNContributors(), ntrIni = ntr;
434 useTrack.reserve(ntr);
435 gidsITS.reserve(ntr);
438 int itr = vtref.getFirstEntry(), itLim = itr + vtref.getEntries();
439 for (; itr < itLim; itr++) {
440 auto vid = trackIndex[itr];
441 if (vid.isPVContributor()) {
447 useTrack.resize(ntr);
449#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
451 for (
int itr = 0; itr < ntr; itr++) {
452 if (!(useTrack[itr] = refitITStrack(tracks[itr], gidsITS[itr]))) {
457 for (
auto v : useTrack) {
461 LOGP(warn,
"Abandon vertex refit: NcontribNew = {} vs NcontribOld = {}", ntr, ntrIni);
464 LOGP(
debug,
"Original vtx: Nc:{} {}, chi2={}", pv.getNContributors(), pv.
asString(), pv.getChi2());
467 LOGP(
debug,
"Refitted vtx: Nc:{} {}, chi2={}", ntr, pv.
asString(), pv.getChi2());
468 if (pv.getChi2() < 0.f) {
469 LOGP(warn,
"Failed to refit PV {}", pvSave.asString());
481 auto pid = track.getPID();
482 track = trkITS.getParamOut();
484 auto nCl = trkITS.getNumberOfClusters();
487 float bz = prop->getNominalBz();
490 for (
int iCl = 0; iCl < nCl; iCl++) {
491 const auto& cls = mITSClustersArray[itsClRefs[trkITS.getClusterEntry(iCl)]];
492 auto alpha = geom->getSensorRefAlpha(cls.getSensorID());
493 if (!(
params.useStableRef ? track.rotate(
alpha, refLin, bz) : track.rotate(
alpha)) ||
494 !prop->propagateTo(track,
params.useStableRef ? &refLin : nullptr, cls.
getX(), true)) {
495 LOGP(
debug,
"refitITStrack failed on propagation to cl#{}, alpha={}, x={} | {}", iCl,
alpha, cls.getX(), track.asString());
498 if (!track.update(cls)) {
499 LOGP(
debug,
"refitITStrack failed on update with cl#{}, | {}", iCl, track.asString());
527 mMeanVertexUpdated =
true;
531 LOG(info) <<
"cluster dictionary updated";
539 std::vector<OutputSpec> outputs;
540 auto dataRequest = std::make_shared<DataRequest>();
541 dataRequest->requestTracks(srcTracks, useMC);
542 dataRequest->requestClusters(srcClusters, useMC);
543 dataRequest->requestPrimaryVertices(useMC);
544 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
552 dataRequest->inputs.emplace_back(
"meanvtx",
"GLO",
"MEANVERTEX", 0, Lifetime::Condition,
ccdbParamSpec(
"GLO/Calib/MeanVertex", {}, 1));
554 {
"nthreads", VariantType::Int, 1, {
"number of threads"}},
563 AlgorithmSpec{adaptFromTask<CheckResidSpec>(dataRequest, ggRequest, srcTracks, useMC )},
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)
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(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, bool useMC)
~CheckResidSpec() final=default
void run(ProcessingContext &pc) final
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
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.
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)
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 useMC)
create a processor spec
constexpr double LHCBunchSpacingNS
Defining PrimaryVertex 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
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
struct o2::upgrades_utils::@453 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
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
auto getITSTracksClusterRefs() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
auto getPrimaryVertexMatchedTrackRefs() const
auto getITSClustersPatterns() const
GTrackID getTPCContributorGID(GTrackID source) 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
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"