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,60 @@ 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 ();
133+ o2::globaltracking::RecoContainer recoData;
134+ recoData.collectData (pc, *mDataRequest );
135+ const auto tracksTPC = recoData.getTPCTracks ();
136+ const auto nTracks = tracksTPC.size ();
137+
138+ // indices to good tracks
139+ std::vector<size_t > indices;
140+ indices.reserve (nTracks);
141+
142+ const auto useGlobalTracks = mTrackSourcesMask [GID::ITSTPC];
143+ o2::math_utils::Point3D<float > vertex = mVtx .getXYZ ();
144+
145+ if (useGlobalTracks) {
146+ auto trackIndex = recoData.getPrimaryVertexMatchedTracks (); // Global ID's for associated tracks
147+ auto vtxRefs = recoData.getPrimaryVertexMatchedTrackRefs (); // references from vertex to these track IDs
148+ std::vector<GID::Source> selSrc{GID::ITSTPC, GID::ITSTPCTRD, GID::ITSTPCTRDTOF}; // for Instance
149+ // LOGP(info, "Number of vertex tracks: {}", vtxRefs.size());
150+ 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
151+
152+ for (int iv = 0 ; iv < nv; iv++) {
153+ const auto & vtref = vtxRefs[iv];
154+ // LOGP(info, "Processing vertex {} with {} tracks", iv, vtref.getEntries());
155+ vertex = recoData.getPrimaryVertex (iv).getXYZ ();
156+ // LOGP(info, "Vertex position: x={} y={} z={}", vertex.x(), vertex.y(), vertex.z());
157+
158+ for (auto src : selSrc) {
159+ int idMin = vtxRefs[iv].getFirstEntryOfSource (src), idMax = idMin + vtxRefs[iv].getEntriesOfSource (src);
160+ // LOGP(info, "Source {}: idMin={} idMax={}", GID::getSourceName(src), idMin, idMax);
161+
162+ for (int i = idMin; i < idMax; i++) {
163+ auto vid = trackIndex[i];
164+ const auto & track = recoData.getTrackParam (vid); // this is a COPY of the track param which we will modify during DCA calculation
165+ auto gidTPC = recoData.getTPCContributorGID (vid);
166+ if (gidTPC.isSourceSet ()) {
167+ const auto idxTPC = gidTPC.getIndex ();
168+ if (mCuts .goodTrack (tracksTPC[idxTPC]) && acceptDCA (tracksTPC[idxTPC], vertex, true )) {
169+ indices.emplace_back (idxTPC);
170+ }
171+ }
172+ }
173+ }
174+ }
122175
123- if ((mMaxTracksPerTF != -1 ) && (nTracks > mMaxTracksPerTF )) {
124- // indices to good tracks
125- std::vector<size_t > indices;
126- indices.reserve (nTracks);
176+ } else {
127177 for (size_t i = 0 ; i < nTracks; ++i) {
128- if (mCuts .goodTrack (tracks [i]) && acceptDCA (tracks [i])) {
178+ if (mCuts .goodTrack (tracksTPC [i]) && acceptDCA (tracksTPC [i], vertex )) {
129179 indices.emplace_back (i);
130180 }
131181 }
182+ }
183+
184+ size_t nTracksSel = indices.size ();
132185
186+ if ((mMaxTracksPerTF != -1 ) && (nTracksSel > mMaxTracksPerTF )) {
133187 // in case no good tracks have been found
134188 if (indices.empty ()) {
135189 mMIPTracks .clear ();
@@ -144,15 +198,14 @@ void MIPTrackFilterDevice::run(ProcessingContext& pc)
144198 std::shuffle (indices.begin (), indices.end (), rng);
145199
146200 // 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); });
201+ nTracksSel = (mMaxTracksPerTF > indices.size ()) ? indices.size () : mMaxTracksPerTF ;
202+ }
203+
204+ for (int i = 0 ; i < nTracksSel; ++i) {
205+ mMIPTracks .emplace_back (tracksTPC[indices[i]]);
153206 }
154207
155- LOGP (info, " Filtered {} MIP tracks out of {} total tpc tracks" , mMIPTracks .size (), tracks .size ());
208+ LOGP (info, " Filtered {} / {} MIP tracks out of {} total tpc tracks, using {} " , mMIPTracks .size (), indices .size (), tracksTPC. size (), useGlobalTracks ? " global tracks " : " TPC only tracks " );
156209 sendOutput (pc.outputs ());
157210 mMIPTracks .clear ();
158211}
@@ -162,6 +215,11 @@ void MIPTrackFilterDevice::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
162215 if (o2::base::GRPGeomHelper::instance ().finaliseCCDB (matcher, obj)) {
163216 return ;
164217 }
218+ if (matcher == ConcreteDataMatcher (" GLO" , " MEANVERTEX" , 0 )) {
219+ LOG (info) << " Setting new MeanVertex: " << ((const o2::dataformats::MeanVertexObject*)obj)->asString ();
220+ mVtx = *(const o2::dataformats::MeanVertexObject*)obj;
221+ return ;
222+ }
165223}
166224
167225void MIPTrackFilterDevice::sendOutput (DataAllocator& output) { output.snapshot (Output{header::gDataOriginTPC , " MIPS" , 0 }, mMIPTracks ); }
@@ -171,44 +229,46 @@ void MIPTrackFilterDevice::endOfStream(EndOfStreamContext& eos)
171229 LOG (info) << " Finalizig MIP Tracks filter" ;
172230}
173231
174- bool MIPTrackFilterDevice::acceptDCA (const TrackTPC& track )
232+ bool MIPTrackFilterDevice::acceptDCA (o2::track::TrackPar propTrack, o2::math_utils::Point3D< float > refPoint, bool useDCAz )
175233{
176234 if (mDCACut < 0 ) {
177235 return true ;
178236 }
179237
180238 auto propagator = o2::base::Propagator::Instance ();
181239 std::array<float , 2 > dca;
182- const o2::math_utils::Point3D<float > refPoint{0 , 0 , 0 };
183- o2::track::TrackPar propTrack (track);
184240 const auto ok = propagator->propagateToDCABxByBz (refPoint, propTrack, 2 ., o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dca);
185241 const auto dcar = std::abs (dca[0 ]);
186242
187- return ok && (dcar < mDCACut );
243+ return ok && (dcar < mDCACut ) && (!useDCAz || ( std::abs (dca[ 1 ]) < mDCAZCut )) ;
188244}
189245
190- DataProcessorSpec getMIPTrackFilterSpec ()
246+ DataProcessorSpec getMIPTrackFilterSpec (GID:: mask_t srcTracks )
191247{
192248 std::vector<OutputSpec> outputs;
193249 outputs.emplace_back (header::gDataOriginTPC , " MIPS" , 0 , Lifetime::Sporadic);
194250
195- std::vector<InputSpec> inputs;
196- inputs.emplace_back (" tracks" , " TPC" , " TRACKS" );
251+ const auto useMC = false ;
252+ auto dataRequest = std::make_shared<DataRequest>();
253+ dataRequest->requestTracks (srcTracks, useMC);
254+ dataRequest->requestPrimaryVertices (useMC);
197255
198256 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false , // orbitResetTime
199257 true , // GRPECS=true
200258 false , // GRPLHCIF
201259 true , // GRPMagField
202260 true , // askMatLUT
203261 o2::base::GRPGeomRequest::Aligned, // geometry
204- inputs,
262+ dataRequest-> inputs ,
205263 true );
206264
265+ dataRequest->inputs .emplace_back (" meanvtx" , " GLO" , " MEANVERTEX" , 0 , Lifetime::Condition, o2::framework::ccdbParamSpec (" GLO/Calib/MeanVertex" , {}, 1 ));
266+
207267 return DataProcessorSpec{
208268 " tpc-miptrack-filter" ,
209- inputs,
269+ dataRequest-> inputs ,
210270 outputs,
211- adaptFromTask<MIPTrackFilterDevice>(ggRequest),
271+ adaptFromTask<MIPTrackFilterDevice>(ggRequest, dataRequest, srcTracks ),
212272 Options{
213273 {" min-momentum" , VariantType::Double, 0.35 , {" minimum momentum cut" }},
214274 {" max-momentum" , VariantType::Double, 0.55 , {" maximum momentum cut" }},
@@ -220,7 +280,8 @@ DataProcessorSpec getMIPTrackFilterSpec()
220280 {" process-first-n-TFs" , VariantType::Int, 1 , {" Number of first TFs which are not sampled" }},
221281 {" send-dummy-data" , VariantType::Bool, false , {" Send empty data in case TF is skipped" }},
222282 {" 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" }},
283+ {" dca-cut" , VariantType::Float, 3 .f , {" DCA cut in xy (cm), < 0 to disable cut in xy and z" }},
284+ {" dca-z-cut" , VariantType::Float, 5 .f , {" DCA cut in z (cm)" }},
224285 }};
225286}
226287
0 commit comments