1616#include " TPCWorkflow/MIPTrackFilterSpec.h"
1717
1818#include < algorithm>
19- #include < iterator>
2019#include < vector>
2120#include < memory>
2221#include < random>
2322
2423// o2 includes
2524#include " DataFormatsTPC/TrackTPC.h"
2625#include " DataFormatsTPC/TrackCuts.h"
27- #include " DetectorsCalibration/Utils .h"
26+ #include " Framework/CCDBParamSpec .h"
2827#include " Framework/Logger.h"
2928#include " DetectorsBase/GRPGeomHelper.h"
3029#include " Framework/Task.h"
3332#include " Framework/ConfigParamRegistry.h"
3433#include " TPCWorkflow/ProcessingHelpers.h"
3534#include " Headers/DataHeader.h"
35+ #include " DataFormatsGlobalTracking/RecoContainer.h"
36+ #include " ReconstructionDataFormats/PrimaryVertex.h"
37+ #include " DataFormatsCalibration/MeanVertexObject.h"
38+ #include " ReconstructionDataFormats/VtxTrackRef.h"
3639
3740using namespace o2 ::framework;
41+ using DataRequest = o2::globaltracking::DataRequest;
42+ using GID = o2::dataformats::GlobalTrackID;
3843
3944namespace o2 ::tpc
4045{
4146
4247class MIPTrackFilterDevice : public Task
4348{
4449 public:
45- MIPTrackFilterDevice (std::shared_ptr<o2::base::GRPGeomRequest> gr) : mGRPGeomRequest (gr) {}
50+ MIPTrackFilterDevice (std::shared_ptr<o2::base::GRPGeomRequest> gr, std::shared_ptr<DataRequest> dr, GID::mask_t trackSourcesMask)
51+ : mGRPGeomRequest (gr), mDataRequest (dr), mTrackSourcesMask (trackSourcesMask) {}
4652
4753 void init (framework::InitContext& ic) final ;
4854 void run (ProcessingContext& pc) final ;
@@ -53,16 +59,20 @@ class MIPTrackFilterDevice : public Task
5359 void sendOutput (DataAllocator& output);
5460
5561 std::shared_ptr<o2::base::GRPGeomRequest> mGRPGeomRequest ;
56- TrackCuts mCuts {}; // /< Tracks cuts object
57- std::vector<TrackTPC> mMIPTracks ; // /< Filtered MIP tracks
58- unsigned int mProcessEveryNthTF {1 }; // /< process every Nth TF only
59- int mMaxTracksPerTF {-1 }; // /< max number of MIP tracks processed per TF
60- uint32_t mTFCounter {0 }; // /< counter to keep track of the TFs
61- int mProcessNFirstTFs {0 }; // /< number of first TFs which are not sampled
62- float mDCACut {-1 }; // /< DCA cut
63- bool mSendDummy {false }; // /< send empty data in case TF is skipped
64-
65- bool acceptDCA (const TrackTPC& track);
62+ std::shared_ptr<DataRequest> mDataRequest ;
63+ GID::mask_t mTrackSourcesMask ;
64+ TrackCuts mCuts {}; // /< Tracks cuts object
65+ std::vector<TrackTPC> mMIPTracks ; // /< Filtered MIP tracks
66+ o2::dataformats::MeanVertexObject mVtx ; // /< Mean vertex object
67+ unsigned int mProcessEveryNthTF {1 }; // /< process every Nth TF only
68+ int mMaxTracksPerTF {-1 }; // /< max number of MIP tracks processed per TF
69+ uint32_t mTFCounter {0 }; // /< counter to keep track of the TFs
70+ int mProcessNFirstTFs {0 }; // /< number of first TFs which are not sampled
71+ float mDCACut {-1 }; // /< DCA cut
72+ float mDCAZCut {-1 }; // /< DCA z cut
73+ bool mSendDummy {false }; // /< send empty data in case TF is skipped
74+
75+ bool acceptDCA (o2::track::TrackPar propTrack, o2::math_utils::Point3D<float > refPoint, bool useDCAz = false );
6676};
6777
6878void MIPTrackFilterDevice::init (framework::InitContext& ic)
@@ -100,13 +110,16 @@ void MIPTrackFilterDevice::init(framework::InitContext& ic)
100110 mCuts .setCutLooper (cutLoopers);
101111
102112 mDCACut = ic.options ().get <float >(" dca-cut" );
113+ mDCAZCut = ic.options ().get <float >(" dca-z-cut" );
103114
104115 o2::base::GRPGeomHelper::instance ().setRequest (mGRPGeomRequest );
105116}
106117
107118void MIPTrackFilterDevice::run (ProcessingContext& pc)
108119{
109120 o2::base::GRPGeomHelper::instance ().checkUpdates (pc);
121+ pc.inputs ().get <o2::dataformats::MeanVertexObject*>(" meanvtx" );
122+
110123 const auto currentTF = processing_helpers::getCurrentTF (pc);
111124 if ((mTFCounter ++ % mProcessEveryNthTF ) && (currentTF >= mProcessNFirstTFs )) {
112125 LOGP (info, " Skipping TF {}" , currentTF);
@@ -117,19 +130,61 @@ void MIPTrackFilterDevice::run(ProcessingContext& pc)
117130 return ;
118131 }
119132
120- const auto tracks = pc.inputs ().get <gsl::span<TrackTPC>>(" tracks" );
121- const auto nTracks = tracks.size ();
122133
123- if ((mMaxTracksPerTF != -1 ) && (nTracks > mMaxTracksPerTF )) {
124- // indices to good tracks
125- std::vector<size_t > indices;
126- indices.reserve (nTracks);
134+ o2::globaltracking::RecoContainer recoData;
135+ recoData.collectData (pc, *mDataRequest );
136+ const auto tracksTPC = recoData.getTPCTracks ();
137+ const auto nTracks = tracksTPC.size ();
138+
139+ // indices to good tracks
140+ std::vector<size_t > indices;
141+ indices.reserve (nTracks);
142+
143+ const auto useGlobalTracks = mTrackSourcesMask [GID::ITSTPC];
144+ o2::math_utils::Point3D<float > vertex = mVtx .getXYZ ();
145+
146+ if (useGlobalTracks) {
147+ auto trackIndex = recoData.getPrimaryVertexMatchedTracks (); // Global ID's for associated tracks
148+ auto vtxRefs = recoData.getPrimaryVertexMatchedTrackRefs (); // references from vertex to these track IDs
149+ std::vector<GID::Source> selSrc{GID::ITSTPC, GID::ITSTPCTRD, GID::ITSTPCTRDTOF}; // for Instance
150+ // LOGP(info, "Number of vertex tracks: {}", vtxRefs.size());
151+ const auto nv = (vtxRefs.size ()>0 ) ? vtxRefs.size () - 1 : 0 ; // note: the last entry groups the tracks which were not related to any vertex, to skip them, use vtxRefs.size()-1
152+
153+ for (int iv = 0 ; iv < nv; iv++) {
154+ const auto & vtref = vtxRefs[iv];
155+ // LOGP(info, "Processing vertex {} with {} tracks", iv, vtref.getEntries());
156+ vertex = recoData.getPrimaryVertex (iv).getXYZ ();
157+ // LOGP(info, "Vertex position: x={} y={} z={}", vertex.x(), vertex.y(), vertex.z());
158+
159+ for (auto src : selSrc) {
160+ int idMin = vtxRefs[iv].getFirstEntryOfSource (src), idMax = idMin + vtxRefs[iv].getEntriesOfSource (src);
161+ // LOGP(info, "Source {}: idMin={} idMax={}", GID::getSourceName(src), idMin, idMax);
162+
163+ for (int i = idMin; i < idMax; i++) {
164+ auto vid = trackIndex[i];
165+ const auto & track = recoData.getTrackParam (vid); // this is a COPY of the track param which we will modify during DCA calculation
166+ auto gidTPC = recoData.getTPCContributorGID (vid);
167+ if (gidTPC.isSourceSet ()) {
168+ const auto idxTPC = gidTPC.getIndex ();
169+ if (mCuts .goodTrack (tracksTPC[idxTPC]) && acceptDCA (tracksTPC[idxTPC], vertex, true )) {
170+ indices.emplace_back (idxTPC);
171+ }
172+ }
173+ }
174+ }
175+ }
176+
177+ } else {
127178 for (size_t i = 0 ; i < nTracks; ++i) {
128- if (mCuts .goodTrack (tracks [i]) && acceptDCA (tracks [i])) {
179+ if (mCuts .goodTrack (tracksTPC [i]) && acceptDCA (tracksTPC [i], vertex )) {
129180 indices.emplace_back (i);
130181 }
131182 }
183+ }
184+
185+ size_t nTracksSel = indices.size ();
132186
187+ if ((mMaxTracksPerTF != -1 ) && (nTracksSel > mMaxTracksPerTF )) {
133188 // in case no good tracks have been found
134189 if (indices.empty ()) {
135190 mMIPTracks .clear ();
@@ -144,15 +199,14 @@ void MIPTrackFilterDevice::run(ProcessingContext& pc)
144199 std::shuffle (indices.begin (), indices.end (), rng);
145200
146201 // copy good tracks
147- const int loopEnd = (mMaxTracksPerTF > indices.size ()) ? indices.size () : mMaxTracksPerTF ;
148- for (int i = 0 ; i < loopEnd; ++i) {
149- mMIPTracks .emplace_back (tracks[indices[i]]);
150- }
151- } else {
152- std::copy_if (tracks.begin (), tracks.end (), std::back_inserter (mMIPTracks ), [this ](const auto & track) { return mCuts .goodTrack (track) && acceptDCA (track); });
202+ nTracksSel = (mMaxTracksPerTF > indices.size ()) ? indices.size () : mMaxTracksPerTF ;
203+ }
204+
205+ for (int i = 0 ; i < nTracksSel; ++i) {
206+ mMIPTracks .emplace_back (tracksTPC[indices[i]]);
153207 }
154208
155- LOGP (info, " Filtered {} MIP tracks out of {} total tpc tracks" , mMIPTracks .size (), tracks .size ());
209+ LOGP (info, " Filtered {} / {} MIP tracks out of {} total tpc tracks, using {} " , mMIPTracks .size (), indices .size (), tracksTPC. size (), useGlobalTracks ? " global tracks " : " TPC only tracks " );
156210 sendOutput (pc.outputs ());
157211 mMIPTracks .clear ();
158212}
@@ -162,6 +216,11 @@ void MIPTrackFilterDevice::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
162216 if (o2::base::GRPGeomHelper::instance ().finaliseCCDB (matcher, obj)) {
163217 return ;
164218 }
219+ if (matcher == ConcreteDataMatcher (" GLO" , " MEANVERTEX" , 0 )) {
220+ LOG (info) << " Setting new MeanVertex: " << ((const o2::dataformats::MeanVertexObject*)obj)->asString ();
221+ mVtx = *(const o2::dataformats::MeanVertexObject*)obj;
222+ return ;
223+ }
165224}
166225
167226void MIPTrackFilterDevice::sendOutput (DataAllocator& output) { output.snapshot (Output{header::gDataOriginTPC , " MIPS" , 0 }, mMIPTracks ); }
@@ -171,44 +230,46 @@ void MIPTrackFilterDevice::endOfStream(EndOfStreamContext& eos)
171230 LOG (info) << " Finalizig MIP Tracks filter" ;
172231}
173232
174- bool MIPTrackFilterDevice::acceptDCA (const TrackTPC& track )
233+ bool MIPTrackFilterDevice::acceptDCA (o2::track::TrackPar propTrack, o2::math_utils::Point3D< float > refPoint, bool useDCAz )
175234{
176235 if (mDCACut < 0 ) {
177236 return true ;
178237 }
179238
180239 auto propagator = o2::base::Propagator::Instance ();
181240 std::array<float , 2 > dca;
182- const o2::math_utils::Point3D<float > refPoint{0 , 0 , 0 };
183- o2::track::TrackPar propTrack (track);
184241 const auto ok = propagator->propagateToDCABxByBz (refPoint, propTrack, 2 ., o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dca);
185242 const auto dcar = std::abs (dca[0 ]);
186243
187- return ok && (dcar < mDCACut );
244+ return ok && (dcar < mDCACut ) && (!useDCAz || ( std::abs (dca[ 1 ]) < mDCAZCut )) ;
188245}
189246
190- DataProcessorSpec getMIPTrackFilterSpec ()
247+ DataProcessorSpec getMIPTrackFilterSpec (GID:: mask_t srcTracks )
191248{
192249 std::vector<OutputSpec> outputs;
193250 outputs.emplace_back (header::gDataOriginTPC , " MIPS" , 0 , Lifetime::Sporadic);
194251
195- std::vector<InputSpec> inputs;
196- inputs.emplace_back (" tracks" , " TPC" , " TRACKS" );
252+ const auto useMC = false ;
253+ auto dataRequest = std::make_shared<DataRequest>();
254+ dataRequest->requestTracks (srcTracks, useMC);
255+ dataRequest->requestPrimaryVertices (useMC);
197256
198257 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false , // orbitResetTime
199258 true , // GRPECS=true
200259 false , // GRPLHCIF
201260 true , // GRPMagField
202261 true , // askMatLUT
203262 o2::base::GRPGeomRequest::Aligned, // geometry
204- inputs,
263+ dataRequest-> inputs ,
205264 true );
206265
266+ dataRequest->inputs .emplace_back (" meanvtx" , " GLO" , " MEANVERTEX" , 0 , Lifetime::Condition, o2::framework::ccdbParamSpec (" GLO/Calib/MeanVertex" , {}, 1 ));
267+
207268 return DataProcessorSpec{
208269 " tpc-miptrack-filter" ,
209- inputs,
270+ dataRequest-> inputs ,
210271 outputs,
211- adaptFromTask<MIPTrackFilterDevice>(ggRequest),
272+ adaptFromTask<MIPTrackFilterDevice>(ggRequest, dataRequest, srcTracks ),
212273 Options{
213274 {" min-momentum" , VariantType::Double, 0.35 , {" minimum momentum cut" }},
214275 {" max-momentum" , VariantType::Double, 0.55 , {" maximum momentum cut" }},
@@ -220,7 +281,8 @@ DataProcessorSpec getMIPTrackFilterSpec()
220281 {" process-first-n-TFs" , VariantType::Int, 1 , {" Number of first TFs which are not sampled" }},
221282 {" send-dummy-data" , VariantType::Bool, false , {" Send empty data in case TF is skipped" }},
222283 {" dont-cut-loopers" , VariantType::Bool, false , {" Do not cut loopers by comparing zout-zin" }},
223- {" dca-cut" , VariantType::Float, 3 .f , {" DCA cut in cm, < 0 to disable" }},
284+ {" dca-cut" , VariantType::Float, 3 .f , {" DCA cut in xy (cm), < 0 to disable cut in xy and z" }},
285+ {" dca-z-cut" , VariantType::Float, 5 .f , {" DCA cut in z (cm)" }},
224286 }};
225287}
226288
0 commit comments