Skip to content

Commit ebca42c

Browse files
Aimeric Landouaimeric-landou
authored andcommitted
add custom track selection for cut variation for systematics
1 parent 764ec40 commit ebca42c

File tree

1 file changed

+128
-22
lines changed

1 file changed

+128
-22
lines changed

PWGJE/Tasks/trackEfficiency.cxx

Lines changed: 128 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
/// \author Aimeric Landou <aimeric.landou@cern.ch>
1414
/// \brief task that creates the histograms necessary for computation of efficiency and purity functions in offline postprocess macros; also can make mcparticle and track QC histograms
1515

16+
17+
#include "Common/Core/TrackSelection.h"
18+
#include "Common/Core/TrackSelectionDefaults.h"
19+
1620
#include "PWGJE/Core/JetDerivedDataUtilities.h"
1721
#include "PWGJE/DataModel/Jet.h"
1822
#include "PWGJE/DataModel/JetReducedData.h"
@@ -84,6 +88,17 @@ struct TrackEfficiency {
8488
Configurable<bool> getPtHatFromHepMCXSection{"getPtHatFromHepMCXSection", true, "test configurable, configurable should be removed once well tested"};
8589
Configurable<bool> useTrueTrackWeight{"useTrueTrackWeight", true, "test configurable, should be set to 1 then config removed once well tested"};
8690

91+
// systematics variation
92+
TrackSelection customTrackSelection;
93+
Configurable<bool> useCustomTrackSelection{"useCustomTrackSelection", false, "whether to use the custom cuts (used for cut variation for tracking efficiency systematics)"};
94+
Configurable<float> effSystMinNCrossedRowsTPC{"effSystMinNCrossedRowsTPC", 70, "min number of crossed rows TPC"};
95+
Configurable<float> effSystMinNCrossedRowsOverFindableClustersTPC{"effSystMinNCrossedRowsOverFindableClustersTPC", 0.8, "min ratio of crossed rows over findable clusters TPC"};
96+
Configurable<float> effSystMaxChi2PerClusterTPC{"effSystMaxChi2PerClusterTPC", 4.0, "max chi2 per cluster TPC"};
97+
Configurable<float> effSystMaxChi2PerClusterITS{"effSystMaxChi2PerClusterITS", 36.0, "max chi2 per cluster ITS "};
98+
// Configurable<float> effSystMaxDcaXY{"effSystMaxDcaXY", 0.0105 * 0.035 / pT^1.1 ????, "max DCA to vertex xy"};
99+
Configurable<float> effSystMaxDcaZ{"effSystMaxDcaZ", 2.0, "max DCA to vertex z"};
100+
Configurable<float> effSystMinNrequiredHits{"effSystMinNrequiredHits", 1, "minimum number of hits among the 3 innermost layers of the ITS"};
101+
87102
std::vector<int> eventSelectionBits;
88103
int trackSelection = -1;
89104

@@ -92,6 +107,21 @@ struct TrackEfficiency {
92107
SplitOkCheckAnyAssocColl, // 1
93108
SplitOkCheckFirstAssocCollOnly // 2
94109
};
110+
111+
template <typename TJetTrack>
112+
bool isAcceptedTrack(TJetTrack const& jetTrack) {
113+
if (!useCustomTrackSelection) {
114+
if (jetderiveddatautilities::selectTrack(jetTrack, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(jetTrack, trackDcaZmax)) { // if track selection is uniformTrack, dcaZ cuts need to be added as they aren't in the selection so that they can be studied here
115+
return true;
116+
}
117+
} else {
118+
const auto& aodTrack = jetTrack.template track_as<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA>>(); // might need the aodTracks to have the TracksExtra table as well; should check; check what is needed for the track selection
119+
if (customTrackSelection.IsSelected(aodTrack)) {
120+
return true;
121+
}
122+
}
123+
return false;
124+
}
95125

96126
bool isChargedParticle(int code)
97127
{
@@ -104,11 +134,11 @@ struct TrackEfficiency {
104134
return std::abs(charge) >= chargeUnit;
105135
}
106136

107-
template <typename TCollision, typename TTracks>
108-
void fillTrackHistograms(TCollision const& collision, TTracks const& tracks, float weight = 1.0)
137+
template <typename TCollision, typename TJetTracks>
138+
void fillTrackHistograms(TCollision const& collision, TJetTracks const& jetTracks, float weight = 1.0)
109139
{
110-
for (auto const& track : tracks) {
111-
if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) {
140+
for (auto const& track : jetTracks) {
141+
if (!isAcceptedTrack(track)) {
112142
continue;
113143
}
114144

@@ -155,6 +185,44 @@ struct TrackEfficiency {
155185
eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast<std::string>(eventSelections));
156186
trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast<std::string>(trackSelections));
157187

188+
if (useCustomTrackSelection) {
189+
// Custom track cuts
190+
LOGP(info, "Using custom track selection from values:");
191+
LOGP(info, "\tminNCrossedRowsTPC= %f", effSystMinNCrossedRowsTPC.value);
192+
LOGP(info, "\tminNCrossedRowsOverFindableClustersTPC= %f", effSystMinNCrossedRowsOverFindableClustersTPC.value);
193+
LOGP(info, "\tmaxChi2PerClusterTPC= %f", effSystMaxChi2PerClusterTPC.value);
194+
LOGP(info, "\tmaxChi2PerClusterITS= %f", effSystMaxChi2PerClusterITS.value);
195+
// LOGP(info, "\tmaxDcaXY= %f", effSystMaxDcaXY.value);
196+
LOGP(info, "\tmaxDcaZ= %f", effSystMaxDcaZ.value);
197+
LOGP(info, "\tRequireHitsInITSLayers= %i", effSystMinNrequiredHits.value);
198+
199+
LOGP(info, "\trequireITS= true");
200+
LOGP(info, "\trequireTPC= true");
201+
202+
// customTrackSelection = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); does this need to be setup?
203+
LOGP(info, "Customizing track selection:");
204+
int dcaSetup = 0; //default dca setup
205+
customTrackSelection = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, dcaSetup); // takes global tracks configuration, then edit some cuts
206+
customTrackSelection.SetEtaRange(-999, 999);
207+
customTrackSelection.SetPtRange(0, 1e10f);
208+
209+
customTrackSelection.SetMinNCrossedRowsTPC(effSystMinNCrossedRowsTPC.value);
210+
customTrackSelection.SetMinNCrossedRowsOverFindableClustersTPC(effSystMinNCrossedRowsOverFindableClustersTPC.value);
211+
customTrackSelection.SetMaxChi2PerClusterTPC(effSystMaxChi2PerClusterTPC.value);
212+
customTrackSelection.SetMaxChi2PerClusterITS(effSystMaxChi2PerClusterITS.value);
213+
// customTrackSelection.SetMaxDcaXY(effSystMaxDcaXY.value);
214+
customTrackSelection.SetMaxDcaZ(effSystMaxDcaZ.value);
215+
customTrackSelection.SetRequireHitsInITSLayers(effSystMinNrequiredHits.value, {0, 1, 2}); // one hit in any SPD layer (#hits, {layer0, layer1,...})
216+
217+
// customTrackSelection.SetRequireITSRefit(true); already set by default
218+
// customTrackSelection.SetRequireTPCRefit(true); already set by default
219+
// customTrackSelection.SetRequireGoldenChi2(requireGoldenChi2.value); already set by default
220+
221+
customTrackSelection.print();
222+
} else {
223+
LOGP(info, "Using standard track selection: %s", trackSelections.value);
224+
}
225+
158226
if (doprocessEFficiencyPurity || doprocessEFficiencyPurityWeighted) {
159227

160228
registry.add("hMcCollCutsCounts", "McColl cuts count checks", {HistType::kTH1F, {{10, 0., 10.}}});
@@ -279,6 +347,22 @@ struct TrackEfficiency {
279347
registry.add("h2_centrality_mccollisions_weighted", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}});
280348
registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}});
281349
}
350+
351+
if (doprocessTrackSelectionHistograms) {
352+
registry.add("h_trackselplot_tpccrossedrows", "track selection variable: number of tpc crossed rows", {HistType::kTH1F, {{165, -0.5, 164.5}}});
353+
registry.add("h_trackselplot_tpccrossedrowsoverfindable", "track selection variable: ratio of of tpc crossed rows over number of findable clusters", {HistType::kTH1F, {{120, 0.0, 1.2}}});
354+
registry.add("h_trackselplot_chi2ncls_tpc", "track selection variable: Chi2 / cluster for the TPC track segment", {HistType::kTH1F, {{100, 0.0, 10.0}}});
355+
registry.add("h_trackselplot_chi2ncls_its", "track selection variable: Chi2 / cluster for the ITS track segment", {HistType::kTH1F, {{200, 0.0, 40.0}}});
356+
registry.add("h_trackselplot_dcaxy", "track selection variable: dca XY", {HistType::kTH1F, {{1000, -1.0, 1.0}}});
357+
registry.add("h_trackselplot_dcaz", "track selection variable: dca Z", {HistType::kTH1F, {{1000, -1.0, 1.0}}});
358+
359+
registry.add("h2_trackselplot_pt_tpccrossedrows", "track selection variable: pt vs number of tpc crossed rows", {HistType::kTH2F, {{200, 0., 200.},{165, -0.5, 164.5}}});
360+
registry.add("h2_trackselplot_pt_tpccrossedrowsoverfindable", "track selection variable: pt vs ratio of of tpc crossed rows over number of findable clusters", {HistType::kTH2F, {{200, 0., 200.}, {120, 0.0, 1.2}}});
361+
registry.add("h2_trackselplot_pt_chi2ncls_tpc", "track selection variable: pt vs Chi2 / cluster for the TPC track segment", {HistType::kTH2F, {{200, 0., 200.}, {100, 0.0, 10.0}}});
362+
registry.add("h2_trackselplot_pt_chi2ncls_its", "track selection variable: pt vs Chi2 / cluster for the ITS track segment", {HistType::kTH2F, {{200, 0., 200.}, {200, 0.0, 40.0}}});
363+
registry.add("h2_trackselplot_pt_dcaxy", "track selection variable: pt vs dca XY", {HistType::kTH2F, {{200, 0., 200.}, {1000, -1.0, 1.0}}});
364+
registry.add("h2_trackselplot_pt_dcaz", "track selection variable: pt vs dca Z", {HistType::kTH2F, {{200, 0., 200.}, {1000, -1.0, 1.0}}});
365+
}
282366
}
283367

284368
Preslice<aod::JetTracksMCD> tracksPerJCollision = o2::aod::jtrack::collisionId;
@@ -291,7 +375,8 @@ struct TrackEfficiency {
291375
void processEFficiencyPurity(soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs>::iterator const& mcCollision,
292376
soa::Join<aod::McCollisions, aod::HepMCXSections> const&,
293377
soa::SmallGroups<aod::JetCollisionsMCD> const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd
294-
soa::Join<aod::JetTracksMCD, aod::JTrackExtras> const& jetTracks,
378+
soa::Join<aod::JetTracksMCD, aod::JTrackExtras, aod::JTrackPIs> const& jetTracks,
379+
soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA> const&,
295380
JetParticlesWithOriginal const& jMcParticles)
296381
{
297382
// missing:
@@ -407,7 +492,7 @@ struct TrackEfficiency {
407492
for (auto const& track : collTracks) {
408493
registry.fill(HIST("hTrackCutsCounts"), 0.5);
409494

410-
if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { // if track selection is uniformTrack, dcaZ cuts need to be added as they aren't in the selection so that they can be studied here
495+
if (!isAcceptedTrack(track)) {
411496
continue;
412497
}
413498
registry.fill(HIST("hTrackCutsCounts"), 1.5);
@@ -472,7 +557,8 @@ struct TrackEfficiency {
472557
void processEFficiencyPurityWeighted(soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs>::iterator const& mcCollision,
473558
soa::Join<aod::McCollisions, aod::HepMCXSections> const&,
474559
soa::SmallGroups<aod::JetCollisionsMCD> const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd
475-
soa::Join<aod::JetTracksMCD, aod::JTrackExtras> const& jetTracks,
560+
soa::Join<aod::JetTracksMCD, aod::JTrackExtras, aod::JTrackPIs> const& jetTracks,
561+
soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA> const&,
476562
JetParticlesWithOriginal const& jMcParticles)
477563
{
478564
// missing:
@@ -576,7 +662,7 @@ struct TrackEfficiency {
576662
for (auto const& track : collTracks) {
577663
registry.fill(HIST("hTrackCutsCounts"), 0.5, mcCollision.weight());
578664

579-
if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { // if track selection is uniformTrack, dcaZ cuts need to be added as they aren't in the selection so that they can be studied here
665+
if (!isAcceptedTrack(track)) {
580666
continue;
581667
}
582668
registry.fill(HIST("hTrackCutsCounts"), 1.5, mcCollision.weight());
@@ -595,8 +681,8 @@ struct TrackEfficiency {
595681
registry.fill(HIST("hTrackCutsCounts"), 3.5, mcCollision.weight());
596682

597683
auto mcParticle = track.mcParticle_as<JetParticlesWithOriginal>();
598-
auto trueTrackMcCollision = mcParticle.mcCollision_as<aod::JetMcCollisions>();
599-
float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight; // test1
684+
auto trueTrackMcCollision = mcParticle.mcCollision_as<soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs>>();
685+
float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight;
600686

601687
auto jMcParticleFromTrack = track.mcParticle_as<JetParticlesWithOriginal>();
602688
if (!jMcParticleFromTrack.isPhysicalPrimary()) {
@@ -648,7 +734,8 @@ struct TrackEfficiency {
648734
PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurityWeighted, "Histograms for efficiency and purity quantities for weighted simulations", false);
649735

650736
void processTracksFromData(soa::Filtered<aod::JetCollisions>::iterator const& collision,
651-
soa::Filtered<soa::Join<aod::JetTracks, aod::JTrackExtras>> const& tracks)
737+
soa::Filtered<soa::Join<aod::JetTracks, aod::JTrackExtras, aod::JTrackPIs>> const& jetTracks,
738+
soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA> const&)
652739
{
653740
if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) {
654741
return;
@@ -657,14 +744,15 @@ struct TrackEfficiency {
657744
return;
658745
}
659746

660-
fillTrackHistograms(collision, tracks);
747+
fillTrackHistograms(collision, jetTracks);
661748
}
662749
PROCESS_SWITCH(TrackEfficiency, processTracksFromData, "QA for charged tracks in data", false);
663750

664-
void processTracksFromMc(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision,
751+
void processTracksFromMc(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision, // a filter should probably be added here to stay consistent with processTracksFromData
665752
soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs> const&,
666753
soa::Join<aod::McCollisions, aod::HepMCXSections> const&,
667-
soa::Filtered<soa::Join<aod::JetTracks, aod::JTrackExtras>> const& tracks)
754+
soa::Filtered<soa::Join<aod::JetTracks, aod::JTrackExtras, aod::JTrackPIs>> const& jetTracks,
755+
soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA> const&)
668756
{
669757
if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called
670758
return;
@@ -681,19 +769,20 @@ struct TrackEfficiency {
681769
return;
682770
}
683771

684-
fillTrackHistograms(collision, tracks);
772+
fillTrackHistograms(collision, jetTracks);
685773
}
686774
PROCESS_SWITCH(TrackEfficiency, processTracksFromMc, "QA for charged tracks in MC without weights", false);
687775

688-
void processTracksFromMcWeighted(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision,
776+
void processTracksFromMcWeighted(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision, // a filter should probably be added here to stay consistent with processTracksFromData
689777
soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs> const&,
690778
soa::Join<aod::McCollisions, aod::HepMCXSections> const&,
691-
soa::Filtered<soa::Join<aod::JetTracks, aod::JTrackExtras>> const& tracks)
779+
soa::Filtered<soa::Join<aod::JetTracks, aod::JTrackExtras, aod::JTrackPIs>> const& jetTracks,
780+
soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA> const&)
692781
{
693782
if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called
694783
return;
695784
}
696-
float eventWeight = collision.mcCollision().weight();
785+
float eventWeight = collision.mcCollision_as<soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs>>().weight();
697786
if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) {
698787
return;
699788
}
@@ -706,7 +795,7 @@ struct TrackEfficiency {
706795
return;
707796
}
708797

709-
fillTrackHistograms(collision, tracks, eventWeight);
798+
fillTrackHistograms(collision, jetTracks, eventWeight);
710799
}
711800
PROCESS_SWITCH(TrackEfficiency, processTracksFromMcWeighted, "QA for charged tracks in weighted MC", false);
712801

@@ -836,7 +925,7 @@ struct TrackEfficiency {
836925
}
837926
PROCESS_SWITCH(TrackEfficiency, processCollisionsFromData, "QA for reconstructed collisions in data", false);
838927

839-
void processCollisionsFromMc(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision,
928+
void processCollisionsFromMc(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision, // a filter should probably be added here to stay consistent with processTracksFromData
840929
soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs> const&,
841930
soa::Join<aod::McCollisions, aod::HepMCXSections> const&)
842931
{
@@ -866,15 +955,15 @@ struct TrackEfficiency {
866955
}
867956
PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMc, "QA for reconstructed collisions in MC without weights", false);
868957

869-
void processCollisionsFromMcWeighted(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision,
958+
void processCollisionsFromMcWeighted(soa::Join<aod::JetCollisions, aod::JMcCollisionLbs>::iterator const& collision, // a filter should probably be added here to stay consistent with processTracksFromData
870959
soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs> const&,
871960
soa::Join<aod::McCollisions, aod::HepMCXSections> const&)
872961
{
873962
if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called
874963
registry.fill(HIST("h_fakecollisions"), 0.5);
875964
return;
876965
}
877-
float eventWeight = collision.mcCollision().weight();
966+
float eventWeight = collision.mcCollision_as<soa::Join<aod::JetMcCollisions, aod::JMcCollisionPIs>>().weight();
878967
registry.fill(HIST("h_collisions"), 0.5);
879968
registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight);
880969
if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) {
@@ -1015,6 +1104,23 @@ struct TrackEfficiency {
10151104
registry.fill(HIST("h_mccollisions_weighted"), 2.5, eventWeight);
10161105
}
10171106
PROCESS_SWITCH(TrackEfficiency, processMcCollisionsWeighted, "QA for McCollisions in weighted MC", false);
1107+
1108+
void processTrackSelectionHistograms(soa::Join<aod::Tracks, aod::TracksExtra, o2::aod::TracksDCA>::iterator const& track) { // should probably select collisions
1109+
registry.fill(HIST("h_trackselplot_tpccrossedrows"), track.tpcNClsCrossedRows());
1110+
registry.fill(HIST("h_trackselplot_tpccrossedrowsoverfindable"), track.tpcCrossedRowsOverFindableCls());
1111+
registry.fill(HIST("h_trackselplot_chi2ncls_tpc"), track.tpcChi2NCl ());
1112+
registry.fill(HIST("h_trackselplot_chi2ncls_its"), track.itsChi2NCl ());
1113+
registry.fill(HIST("h_trackselplot_dcaxy"), track.dcaXY());
1114+
registry.fill(HIST("h_trackselplot_dcaz"), track.dcaZ());
1115+
1116+
registry.fill(HIST("h2_trackselplot_pt_tpccrossedrows"), track.pt(), track.tpcNClsCrossedRows());
1117+
registry.fill(HIST("h2_trackselplot_pt_tpccrossedrowsoverfindable"), track.pt(), track.tpcCrossedRowsOverFindableCls());
1118+
registry.fill(HIST("h2_trackselplot_pt_chi2ncls_tpc"), track.pt(), track.tpcChi2NCl());
1119+
registry.fill(HIST("h2_trackselplot_pt_chi2ncls_its"), track.pt(), track.itsChi2NCl());
1120+
registry.fill(HIST("h2_trackselplot_pt_dcaxy"), track.pt(), track.dcaXY());
1121+
registry.fill(HIST("h2_trackselplot_pt_dcaz"), track.pt(), track.dcaZ());
1122+
}
1123+
PROCESS_SWITCH(TrackEfficiency, processTrackSelectionHistograms, "plots distributions of variables that are cut on during track selection", false);
10181124
};
10191125

10201126
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)

0 commit comments

Comments
 (0)