99// granted to it by virtue of its status as an Intergovernmental Organization
1010// or submit itself to any jurisdiction.
1111
12+ // / \file trackPropagationTester.cxx
13+ // / \brief testing ground for track propagation
14+ // / \author ALICE
15+
16+ // ===============================================================
17+ //
18+ // Experimental version of the track propagation task
19+ // this utilizes an analysis task module that can be employed elsewhere
20+ // and allows for the re-utilization of a material LUT
1221//
13- // Task to add a table of track parameters propagated to the primary vertex
22+ // candidate approach for core service approach
1423//
15- // FIXME: THIS IS AN EXPERIMENTAL TASK, MEANT ONLY FOR EXPLORATORY PURPOSES.
16- // FIXME: PLEASE ONLY USE IT WITH EXTREME CARE. IF IN DOUBT, STICK WITH THE DEFAULT
17- // FIXME: TRACKPROPAGATION
24+ // ===============================================================
1825
1926#include " Framework/AnalysisDataModel.h"
2027#include " Framework/AnalysisTask.h"
3037#include " DataFormatsParameters/GRPMagField.h"
3138#include " CCDB/BasicCCDBManager.h"
3239#include " Framework/HistogramRegistry.h"
33- #include " Framework/runDataProcessing.h"
3440#include " DataFormatsCalibration/MeanVertexObject.h"
3541#include " CommonConstants/GeomConstants.h"
36- #include " trackSelectionRequest.h"
42+ #include " Common/Tools/TrackPropagationModule.h"
43+ #include " Common/Tools/StandardCCDBLoader.h"
3744
3845// The Run 3 AO2D stores the tracks at the point of innermost update. For a track with ITS this is the innermost (or second innermost)
3946// ITS layer. For a track without ITS, this is the TPC inner wall or for loopers in the TPC even a radius beyond that.
@@ -48,294 +55,45 @@ using namespace o2::framework;
4855// using namespace o2::framework::expressions;
4956
5057struct TrackPropagationTester {
51- Produces<aod::StoredTracks> tracksParPropagated;
52- Produces<aod::TracksExtension> tracksParExtensionPropagated;
53-
54- Produces<aod::StoredTracksCov> tracksParCovPropagated;
55- Produces<aod::TracksCovExtension> tracksParCovExtensionPropagated;
56-
57- Produces<aod::TracksDCA> tracksDCA;
58+ o2::common::StandardCCDBLoaderConfigurables standardCCDBLoaderConfigurables;
59+ o2::common::TrackPropagationProducts trackPropagationProducts;
60+ o2::common::TrackPropagationConfigurables trackPropagationConfigurables;
5861
62+ // CCDB boilerplate declarations
63+ o2::framework::Configurable<std::string> ccdburl{" ccdburl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
5964 Service<o2::ccdb::BasicCCDBManager> ccdb;
6065
61- HistogramRegistry histos{" Histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
62-
63- bool fillTracksDCA = false ;
64- int runNumber = -1 ;
65-
66- o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT;
67-
68- const o2::dataformats::MeanVertexObject* mVtx = nullptr ;
69- o2::parameters::GRPMagField* grpmag = nullptr ;
70- o2::base::MatLayerCylSet* lut = nullptr ;
66+ o2::common::StandardCCDBLoader ccdbLoader;
67+ o2::common::TrackPropagationModule trackPropagation;
7168
72- // Track selection object in this scope: not necessarily a configurable
73- trackSelectionRequest trackSels;
74- // Configurable based on a struct
75- // Configurable<trackSelectionRequest> trackSels{"trackSels", {}, "track selections"};
76-
77- Configurable<std::string> ccdburl{" ccdb-url" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
78- Configurable<std::string> lutPath{" lutPath" , " GLO/Param/MatLUT" , " Path of the Lut parametrization" };
79- Configurable<std::string> geoPath{" geoPath" , " GLO/Config/GeometryAligned" , " Path of the geometry file" };
80- Configurable<std::string> grpmagPath{" grpmagPath" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object" };
81- Configurable<std::string> mVtxPath {" mVtxPath" , " GLO/Calib/MeanVertex" , " Path of the mean vertex file" };
82- Configurable<float > minPropagationRadius{" minPropagationDistance" , o2::constants::geom::XTPCInnerRef + 0.1 , " Only tracks which are at a smaller radius will be propagated, defaults to TPC inner wall" };
83-
84- // Configurables regarding what to propagate
85- // FIXME: This is dangerous and error prone for general purpose use. It is meant ONLY for testing.
86- Configurable<bool > propagateUnassociated{" propagateUnassociated" , false , " propagate tracks with no collision assoc" };
87- Configurable<bool > propagateTPConly{" propagateTPConly" , false , " propagate tracks with only TPC (no ITS, TRD, TOF)" };
88- Configurable<int > minTPCClusters{" minTPCClusters" , 70 , " min number of TPC clusters to propagate" };
89- Configurable<float > maxPropagStep{" maxPropagStep" , 2.0 , " max propag step" }; // to be checked systematically
90- // use auto-detect configuration
91- Configurable<bool > d_UseAutodetectMode{" d_UseAutodetectMode" , false , " Autodetect requested track criteria" };
92-
93- bool hasEnding (std::string const & fullString, std::string const & ending)
94- {
95- if (fullString.length () >= ending.length ()) {
96- return (0 == fullString.compare (fullString.length () - ending.length (), ending.length (), ending));
97- } else {
98- return false ;
99- }
100- }
69+ HistogramRegistry registry{" registry" };
10170
10271 void init (o2::framework::InitContext& initContext)
10372 {
104- const AxisSpec axisX{(int )4 , 0 .0f , +4 .0f , " Track counter" };
105- histos.add (" hTrackCounter" , " hTrackCounter" , kTH1F , {axisX});
106-
107- if (doprocessCovariance == true && doprocessStandard == true ) {
108- LOGF (fatal, " Cannot enable processStandard and processCovariance at the same time. Please choose one." );
109- }
110-
111- // Checking if the tables are requested in the workflow and enabling them
112- auto & workflows = initContext.services ().get <RunningWorkflowInfo const >();
113- for (DeviceSpec const & device : workflows.devices ) {
114- for (auto const & input : device.inputs ) {
115- if (input.matcher .binding == " TracksDCA" ) {
116- fillTracksDCA = true ;
117- }
118- }
119- }
120-
121- ccdb->setURL (ccdburl);
73+ // CCDB boilerplate init
12274 ccdb->setCaching (true );
12375 ccdb->setLocalObjectValidityChecking ();
76+ ccdb->setURL (ccdburl.value );
12477
125- lut = o2::base::MatLayerCylSet::rectifyPtrFromFile (ccdb->get <o2::base::MatLayerCylSet>(lutPath));
126-
127- if (d_UseAutodetectMode) {
128- LOGF (info, " *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*" );
129- LOGF (info, " Track propagator self-configuration" );
130- LOGF (info, " *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*" );
131- trackSels.SetTightSelections (); // Only loosen from this point forward
132- for (DeviceSpec const & device : workflows.devices ) {
133- // Loop over options to find track selection
134- for (auto const & option : device.options ) {
135- if (hasEnding (option.name , " .requireTPC" )) {
136- bool lVal = option.defaultValue .get <bool >();
137- LOGF (info, " Device %s, request TPC: %i" , device.name , lVal);
138- if (trackSels.getRequireTPC () == false )
139- trackSels.setRequireTPC (lVal);
140- }
141- if (hasEnding (option.name , " .minTPCclusters" )) {
142- int lVal = option.defaultValue .get <int >();
143- LOGF (info, " Device %s, min TPC clusters: %i" , device.name , lVal);
144- if (trackSels.getMinTPCClusters () > lVal)
145- trackSels.setMinTPCClusters (lVal);
146- }
147- if (hasEnding (option.name , " .minTPCcrossedrows" )) {
148- int lVal = option.defaultValue .get <int >();
149- LOGF (info, " Device %s, min TPC crossed rows: %i" , device.name , lVal);
150- if (trackSels.getMinTPCCrossedRows () > lVal)
151- trackSels.setMinTPCCrossedRows (lVal);
152- }
153- if (hasEnding (option.name , " .minTPCcrossedrowsoverfindable" )) {
154- float lVal = option.defaultValue .get <float >();
155- LOGF (info, " Device %s, min TPC crossed rows over findable: %.3f" , device.name , lVal);
156- if (trackSels.getMinTPCCrossedRowsOverFindable () > lVal)
157- trackSels.setMinTPCCrossedRowsOverFindable (lVal);
158- }
159- if (hasEnding (option.name , " .requireITS" )) {
160- bool lVal = option.defaultValue .get <bool >();
161- LOGF (info, " Device %s, request ITS: %i" , device.name , lVal);
162- if (trackSels.getRequireITS () == false )
163- trackSels.setRequireITS (lVal);
164- }
165- if (hasEnding (option.name , " .minITSclusters" )) {
166- int lVal = option.defaultValue .get <int >();
167- LOGF (info, " Device %s, minimum ITS clusters: %i" , device.name , lVal);
168- if (trackSels.getMinITSClusters () > lVal)
169- trackSels.setMinITSClusters (lVal);
170- }
171- if (hasEnding (option.name , " .maxITSChi2percluster" )) {
172- float lVal = option.defaultValue .get <float >();
173- LOGF (info, " Device %s, max ITS chi2/clu: %.3f" , device.name , lVal);
174- if (trackSels.getMaxITSChi2PerCluster () < lVal)
175- trackSels.setMaxITSChi2PerCluster (lVal);
176- }
177- }
178- }
179- LOGF (info, " -+*> Automatic self-config ended. Final settings:" );
180- trackSels.PrintSelections ();
181- }
182- }
183-
184- void initCCDB (aod::BCsWithTimestamps::iterator const & bc)
185- {
186- if (runNumber == bc.runNumber ()) {
187- return ;
188- }
189- grpmag = ccdb->getForTimeStamp <o2::parameters::GRPMagField>(grpmagPath, bc.timestamp ());
190- LOG (info) << " Setting magnetic field to current " << grpmag->getL3Current () << " A for run " << bc.runNumber () << " from its GRPMagField CCDB object" ;
191- o2::base::Propagator::initFieldFromGRP (grpmag);
192- o2::base::Propagator::Instance ()->setMatLUT (lut);
193- if (propagateUnassociated)
194- mVtx = ccdb->getForTimeStamp <o2::dataformats::MeanVertexObject>(mVtxPath , bc.timestamp ());
195- runNumber = bc.runNumber ();
78+ // task-specific
79+ trackPropagation.init (trackPropagationConfigurables, registry, initContext);
19680 }
19781
198- template <typename TTrack, typename TTrackPar>
199- void FillTracksPar (TTrack& track, aod::track::TrackTypeEnum trackType, TTrackPar& trackPar)
82+ void processReal (soa::Join<aod::StoredTracksIU, aod::TracksCovIU, aod::TracksExtra> const & tracks, aod::Collisions const &, aod::BCs const & bcs)
20083 {
201- tracksParPropagated (track.collisionId (), trackType, trackPar.getX (), trackPar.getAlpha (), trackPar.getY (), trackPar.getZ (), trackPar.getSnp (), trackPar.getTgl (), trackPar.getQ2Pt ());
202- tracksParExtensionPropagated (trackPar.getPt (), trackPar.getP (), trackPar.getEta (), trackPar.getPhi ());
84+ // task-specific
85+ ccdbLoader.initCCDBfromBCs (standardCCDBLoaderConfigurables, ccdb, bcs);
86+ trackPropagation.fillTrackTables <false >(trackPropagationConfigurables, ccdbLoader, tracks, trackPropagationProducts, registry);
20387 }
88+ PROCESS_SWITCH (TrackPropagationTester, processReal, " Process Real Data" , true );
20489
205- void processStandard (soa::Join<aod::TracksIU, aod::TracksExtra> const & tracks, aod::Collisions const &, aod::BCsWithTimestamps const & bcs)
90+ // -----------------------
91+ void processMc (soa::Join<aod::StoredTracksIU, aod::McTrackLabels, aod::TracksCovIU, aod::TracksExtra> const & tracks, aod::McParticles const &, aod::Collisions const &, aod::BCs const & bcs)
20692 {
207- if (bcs.size () == 0 ) {
208- return ;
209- }
210- initCCDB (bcs.begin ());
211-
212- std::array<float , 2 > dcaInfo;
213-
214- int lNAll = 0 ;
215- int lNaccTPC = 0 ;
216- int lNaccNotTPCOnly = 0 ;
217- int lNPropagated = 0 ;
218- bool passTPCclu = kFALSE ;
219- bool passNotTPCOnly = kFALSE ;
220-
221- for (auto & track : tracks) {
222- // Selection criteria
223- passTPCclu = kFALSE ;
224- passNotTPCOnly = kFALSE ;
225- lNAll++;
226- if (track.tpcNClsFound () >= minTPCClusters) {
227- passTPCclu = kTRUE ;
228- lNaccTPC++;
229- }
230- if ((track.hasTPC () && !track.hasITS () && !track.hasTRD () && !track.hasTOF ()) || propagateTPConly) {
231- passNotTPCOnly = kTRUE ;
232- lNaccNotTPCOnly++;
233- }
234-
235- dcaInfo[0 ] = 999 ;
236- dcaInfo[1 ] = 999 ;
237- aod::track::TrackTypeEnum trackType = (aod::track::TrackTypeEnum)track.trackType ();
238- auto trackPar = getTrackPar (track);
239- // Only propagate tracks which have passed the innermost wall of the TPC (e.g. skipping loopers etc). Others fill unpropagated.
240- if (track.trackType () == aod::track::TrackIU && track.x () < minPropagationRadius && passTPCclu && passNotTPCOnly) {
241- if (track.has_collision ()) {
242- auto const & collision = track.collision ();
243- o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, trackPar, maxPropagStep, matCorr, &dcaInfo);
244- trackType = aod::track::Track;
245- lNPropagated++;
246- } else {
247- if (propagateUnassociated) {
248- o2::base::Propagator::Instance ()->propagateToDCABxByBz ({mVtx ->getX (), mVtx ->getY (), mVtx ->getZ ()}, trackPar, maxPropagStep, matCorr, &dcaInfo);
249- trackType = aod::track::Track;
250- lNPropagated++;
251- }
252- }
253- }
254- FillTracksPar (track, trackType, trackPar);
255- if (fillTracksDCA) {
256- tracksDCA (dcaInfo[0 ], dcaInfo[1 ]);
257- }
258- }
259- // Fill only per table (not per track). ROOT FindBin is slow
260- histos.fill (HIST (" hTrackCounter" ), 0.5 , lNAll);
261- histos.fill (HIST (" hTrackCounter" ), 1.5 , lNaccTPC);
262- histos.fill (HIST (" hTrackCounter" ), 2.5 , lNaccNotTPCOnly);
263- histos.fill (HIST (" hTrackCounter" ), 3.5 , lNPropagated);
264- }
265- PROCESS_SWITCH (TrackPropagationTester, processStandard, " Process without covariance" , true );
266-
267- void processCovariance (soa::Join<aod::TracksIU, aod::TracksCovIU, aod::TracksExtra> const & tracks, aod::Collisions const &, aod::BCsWithTimestamps const & bcs)
268- {
269- if (bcs.size () == 0 ) {
270- return ;
271- }
272- initCCDB (bcs.begin ());
273-
274- o2::dataformats::DCA dcaInfoCov;
275- o2::dataformats::VertexBase vtx;
276-
277- int lNAll = 0 ;
278- int lNaccTPC = 0 ;
279- int lNaccNotTPCOnly = 0 ;
280- int lNPropagated = 0 ;
281- bool passTPCclu = kFALSE ;
282- bool passNotTPCOnly = kFALSE ;
283-
284- for (auto & track : tracks) {
285- // Selection criteria
286- passTPCclu = kFALSE ;
287- passNotTPCOnly = kFALSE ;
288- lNAll++;
289- if (track.tpcNClsFound () >= minTPCClusters) {
290- passTPCclu = kTRUE ;
291- lNaccTPC++;
292- }
293- if ((track.hasTPC () && !track.hasITS () && !track.hasTRD () && !track.hasTOF ()) || propagateTPConly) {
294- passNotTPCOnly = kTRUE ;
295- lNaccNotTPCOnly++;
296- }
297-
298- dcaInfoCov.set (999 , 999 , 999 , 999 , 999 );
299- auto trackParCov = getTrackParCov (track);
300- aod::track::TrackTypeEnum trackType = (aod::track::TrackTypeEnum)track.trackType ();
301- // Only propagate tracks which have passed the innermost wall of the TPC (e.g. skipping loopers etc). Others fill unpropagated.
302- if (track.trackType () == aod::track::TrackIU && track.x () < minPropagationRadius && passTPCclu && passNotTPCOnly) {
303- if (track.has_collision ()) {
304- auto const & collision = track.collision ();
305- vtx.setPos ({collision.posX (), collision.posY (), collision.posZ ()});
306- vtx.setCov (collision.covXX (), collision.covXY (), collision.covYY (), collision.covXZ (), collision.covYZ (), collision.covZZ ());
307- o2::base::Propagator::Instance ()->propagateToDCABxByBz (vtx, trackParCov, maxPropagStep, matCorr, &dcaInfoCov);
308- trackType = aod::track::Track;
309- lNPropagated++;
310- } else {
311- if (propagateUnassociated) {
312- vtx.setPos ({mVtx ->getX (), mVtx ->getY (), mVtx ->getZ ()});
313- vtx.setCov (mVtx ->getSigmaX () * mVtx ->getSigmaX (), 0 .0f , mVtx ->getSigmaY () * mVtx ->getSigmaY (), 0 .0f , 0 .0f , mVtx ->getSigmaZ () * mVtx ->getSigmaZ ());
314- o2::base::Propagator::Instance ()->propagateToDCABxByBz (vtx, trackParCov, maxPropagStep, matCorr, &dcaInfoCov);
315- trackType = aod::track::Track;
316- lNPropagated++;
317- }
318- }
319- }
320- FillTracksPar (track, trackType, trackParCov);
321- if (fillTracksDCA) {
322- tracksDCA (dcaInfoCov.getY (), dcaInfoCov.getZ ());
323- }
324- // TODO do we keep the rho as 0? Also the sigma's are duplicated information
325- tracksParCovPropagated (std::sqrt (trackParCov.getSigmaY2 ()), std::sqrt (trackParCov.getSigmaZ2 ()), std::sqrt (trackParCov.getSigmaSnp2 ()),
326- std::sqrt (trackParCov.getSigmaTgl2 ()), std::sqrt (trackParCov.getSigma1Pt2 ()), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
327- tracksParCovExtensionPropagated (trackParCov.getSigmaY2 (), trackParCov.getSigmaZY (), trackParCov.getSigmaZ2 (), trackParCov.getSigmaSnpY (),
328- trackParCov.getSigmaSnpZ (), trackParCov.getSigmaSnp2 (), trackParCov.getSigmaTglY (), trackParCov.getSigmaTglZ (), trackParCov.getSigmaTglSnp (),
329- trackParCov.getSigmaTgl2 (), trackParCov.getSigma1PtY (), trackParCov.getSigma1PtZ (), trackParCov.getSigma1PtSnp (), trackParCov.getSigma1PtTgl (),
330- trackParCov.getSigma1Pt2 ());
331- }
332- // Fill only per table (not per track). ROOT FindBin is slow
333- histos.fill (HIST (" hTrackCounter" ), 0.5 , lNAll);
334- histos.fill (HIST (" hTrackCounter" ), 1.5 , lNaccTPC);
335- histos.fill (HIST (" hTrackCounter" ), 2.5 , lNaccNotTPCOnly);
336- histos.fill (HIST (" hTrackCounter" ), 3.5 , lNPropagated);
93+ ccdbLoader.initCCDBfromBCs (standardCCDBLoaderConfigurables, ccdb, bcs);
94+ trackPropagation.fillTrackTables <false >(trackPropagationConfigurables, ccdbLoader, tracks, trackPropagationProducts, registry);
33795 }
338- PROCESS_SWITCH (TrackPropagationTester, processCovariance , " Process with covariance " , false );
96+ PROCESS_SWITCH (TrackPropagationTester, processMc , " Process Monte Carlo " , false );
33997};
34098
34199// ****************************************************************************************
0 commit comments