Skip to content

Commit 5e187fe

Browse files
EloviyoShirajum Monira
andauthored
[PWGCF] FemtoUniverse cascade task -- refined cascade pile up check (#11136)
Co-authored-by: Shirajum Monira <shirajum.monira@cernch>
1 parent 41d1ebe commit 5e187fe

File tree

1 file changed

+82
-62
lines changed

1 file changed

+82
-62
lines changed

PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx

Lines changed: 82 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
/// \author Shirajum Monira, WUT Warsaw, shirajum.monira@cern.ch
1616

1717
#include <vector>
18+
#include <set>
1819
#include "Framework/AnalysisTask.h"
1920
#include "Framework/runDataProcessing.h"
2021
#include "Framework/HistogramRegistry.h"
@@ -47,56 +48,56 @@ struct femtoUniversePairTaskTrackCascadeExtended {
4748
using FemtoRecoParticles = soa::Join<aod::FDCascParticles, aod::FDExtParticles, aod::FDMCLabels>;
4849
Preslice<FemtoRecoParticles> perColReco = aod::femtouniverseparticle::fdCollisionId;
4950

50-
ConfigurableAxis confChildTempFitVarpTBins{"ConfChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"};
51-
ConfigurableAxis confChildTempFitVarBins{"ConfChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"};
52-
Configurable<float> confCascInvMassLowLimit{"ConfCascInvMassLowLimit", 1.315, "Lower limit of the Casc invariant mass"};
53-
Configurable<float> confCascInvMassUpLimit{"ConfCascInvMassUpLimit", 1.325, "Upper limit of the Casc invariant mass"};
54-
Configurable<float> confCascTranRad{"ConfCascTranRad", 0.5, "Cascade transverse radius"};
51+
ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"};
52+
ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"};
53+
Configurable<float> confCascInvMassLowLimit{"confCascInvMassLowLimit", 1.315, "Lower limit of the Casc invariant mass"};
54+
Configurable<float> confCascInvMassUpLimit{"confCascInvMassUpLimit", 1.325, "Upper limit of the Casc invariant mass"};
55+
Configurable<float> confCascTranRad{"confCascTranRad", 0.5, "Cascade transverse radius"};
5556

56-
Configurable<float> confNSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"};
57-
Configurable<float> confNSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"};
57+
Configurable<float> confNSigmaTPCPion{"confNSigmaTPCPion", 4, "NSigmaTPCPion"};
58+
Configurable<float> confNSigmaTPCProton{"confNSigmaTPCProton", 4, "NSigmaTPCProton"};
5859

5960
/// applying narrow cut
60-
Configurable<float> confZVertexCut{"ConfZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"};
61-
Configurable<float> confEta{"ConfEta", 0.8, "Eta cut for the global track"};
61+
Configurable<float> confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"};
62+
Configurable<float> confEta{"confEta", 0.8, "Eta cut for the global track"};
6263

6364
// configurations for correlation part
64-
Configurable<int> confTrackChoicePartOne{"ConfTrackChoicePartOne", 0, "0:Proton, 1:Pion, 2:Kaon"};
65-
Configurable<int> confTrkPDGCodePartOne{"ConfTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"};
66-
Configurable<int> confCascType1{"ConfCascType1", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"};
67-
Configurable<int> confCascType2{"ConfCascType2", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"};
68-
Configurable<bool> confIsCPR{"ConfIsCPR", false, "Close Pair Rejection"};
69-
Configurable<float> confCPRdeltaPhiCutMax{"ConfCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"};
70-
Configurable<float> confCPRdeltaPhiCutMin{"ConfCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"};
71-
Configurable<float> confCPRdeltaEtaCutMax{"ConfCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"};
72-
Configurable<float> confCPRdeltaEtaCutMin{"ConfCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"};
73-
Configurable<bool> confCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"};
74-
Configurable<float> confCPRChosenRadii{"ConfCPRChosenRadii", 0.0, "Delta Eta cut for Close Pair Rejection"};
75-
Configurable<int> confChargePart1{"ConfChargePart1", 1, "sign of particle 1"};
76-
Configurable<float> confHPtPart1{"ConfHPtPart1", 4.0f, "higher limit for pt of particle 1"};
77-
Configurable<float> confLPtPart1{"ConfLPtPart1", 0.5f, "lower limit for pt of particle 1"};
78-
Configurable<float> confHPtPart2{"ConfHPtPart2", 4.0f, "higher limit for pt of particle 2"};
79-
Configurable<float> confLPtPart2{"ConfLPtPart2", 0.3f, "lower limit for pt of particle 2"};
80-
Configurable<float> confmom{"Confmom", 0.75, "momentum threshold for particle identification using TOF"};
81-
Configurable<float> confNsigmaTPCParticle{"ConfNsigmaTPCParticle", 3.0, "TPC Sigma for particle (track) momentum < Confmom"};
82-
Configurable<float> confNsigmaCombinedParticle{"ConfNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle (track) momentum > Confmom"};
83-
Configurable<float> confNsigmaTPCParticleChild{"ConfNsigmaTPCParticleChild", 3.0, "TPC Sigma for particle (daugh & bach) momentum < Confmom"};
84-
Configurable<float> confNsigmaTOFParticleChild{"ConfNsigmaTOFParticleChild", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"};
85-
86-
ConfigurableAxis confkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"};
87-
ConfigurableAxis confMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"};
88-
ConfigurableAxis confkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"};
89-
ConfigurableAxis confmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"};
90-
ConfigurableAxis confmultBins3D{"ConfMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <<confUse3D>> to true in order to use)"};
91-
ConfigurableAxis confmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <<confUse3D>> to true in order to use)"};
92-
Configurable<int> confEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"};
93-
Configurable<int> confPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"};
94-
Configurable<bool> confIsMC{"ConfIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"};
95-
Configurable<bool> confUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"};
65+
Configurable<int> confTrackChoicePartOne{"confTrackChoicePartOne", 0, "0:Proton, 1:Pion, 2:Kaon"};
66+
Configurable<int> confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"};
67+
Configurable<int> confCascType1{"confCascType1", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"};
68+
Configurable<int> confCascType2{"confCascType2", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"};
69+
Configurable<bool> confIsCPR{"confIsCPR", false, "Close Pair Rejection"};
70+
Configurable<float> confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"};
71+
Configurable<float> confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"};
72+
Configurable<float> confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"};
73+
Configurable<float> confCPRdeltaEtaCutMin{"confCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"};
74+
Configurable<bool> confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"};
75+
Configurable<float> confCPRChosenRadii{"confCPRChosenRadii", 0.0, "Delta Eta cut for Close Pair Rejection"};
76+
Configurable<int> confChargePart1{"confChargePart1", 1, "sign of particle 1"};
77+
Configurable<float> confHPtPart1{"confHPtPart1", 4.0f, "higher limit for pt of particle 1"};
78+
Configurable<float> confLPtPart1{"confLPtPart1", 0.5f, "lower limit for pt of particle 1"};
79+
Configurable<float> confHPtPart2{"confHPtPart2", 4.0f, "higher limit for pt of particle 2"};
80+
Configurable<float> confLPtPart2{"confLPtPart2", 0.3f, "lower limit for pt of particle 2"};
81+
Configurable<float> confmom{"confmom", 0.75, "momentum threshold for particle identification using TOF"};
82+
Configurable<float> confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle (track) momentum < Confmom"};
83+
Configurable<float> confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle (track) momentum > Confmom"};
84+
Configurable<float> confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for particle (daugh & bach) momentum < Confmom"};
85+
Configurable<float> confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"};
86+
87+
ConfigurableAxis confkstarBins{"confkstarBins", {1500, 0., 6.}, "binning kstar"};
88+
ConfigurableAxis confMultBins{"confMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"};
89+
ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"};
90+
ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"};
91+
ConfigurableAxis confMultBins3D{"confMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <<confUse3D>> to true in order to use)"};
92+
ConfigurableAxis confmTBins3D{"confmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <<confUse3D>> to true in order to use)"};
93+
Configurable<int> confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"};
94+
Configurable<int> confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"};
95+
Configurable<bool> confIsMC{"confIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"};
96+
Configurable<bool> confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"};
9697
Configurable<bool> confUseCent{"confUseCent", false, "Use centrality in place of multiplicity"};
97-
ConfigurableAxis confVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"};
98-
ConfigurableAxis confTrkTempFitVarpTBins{"ConfTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"};
99-
ConfigurableAxis confTrkTempFitVarBins{"ConfTrkDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"};
98+
ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"};
99+
ConfigurableAxis confTrkTempFitVarpTBins{"confTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"};
100+
ConfigurableAxis confTrkTempFitVarBins{"confTrkTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"};
100101

101102
Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut);
102103
using FilteredFDCollisions = soa::Filtered<o2::aod::FdCollisions>;
@@ -140,16 +141,15 @@ struct femtoUniversePairTaskTrackCascadeExtended {
140141
HistogramRegistry registryMCgen{"MCgenHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true};
141142
HistogramRegistry registryMCreco{"MCrecoHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true};
142143

144+
std::set<int> cascDuplicates;
145+
143146
// Table to select cascade daughters
144147
// Charges: = +--, +--, +-+, +-+
145148
static constexpr unsigned int CascChildTable[][3] = {{0, 1, 2}, {0, 1, 1}, {1, 0, 2}, {1, 0, 1}};
146149

147-
bool invMCascade(float invMassCascade, float invMassAntiCascade)
150+
bool invMCascade(float invMassXi, float invMassOmega, int cascType)
148151
{
149-
if ((invMassCascade < confCascInvMassLowLimit || invMassCascade > confCascInvMassUpLimit) && (invMassAntiCascade < confCascInvMassLowLimit || invMassAntiCascade > confCascInvMassUpLimit)) {
150-
return false;
151-
}
152-
return true;
152+
return (((cascType == 1 || cascType == 3) && (invMassXi > confCascInvMassLowLimit && invMassXi < confCascInvMassUpLimit)) || ((cascType == 0 || cascType == 2) && (invMassOmega > confCascInvMassLowLimit && invMassOmega < confCascInvMassUpLimit)));
153153
}
154154

155155
bool isNSigmaTPC(float nsigmaTPCParticle)
@@ -278,8 +278,8 @@ struct femtoUniversePairTaskTrackCascadeExtended {
278278
bachHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "hBachelor");
279279
cascQAHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true);
280280

281-
sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D);
282-
mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D);
281+
sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D);
282+
mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D);
283283
pairCleaner.init(&qaRegistry);
284284
if (confIsCPR.value) {
285285
pairCloseRejection.init(&resultRegistry, &qaRegistry, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value);
@@ -359,7 +359,7 @@ struct femtoUniversePairTaskTrackCascadeExtended {
359359
const int multCol = confUseCent ? col.multV0M() : col.multNtr();
360360

361361
for (const auto& part : groupPartsTwo) {
362-
if (!invMCascade(part.mLambda(), part.mAntiLambda()))
362+
if (!invMCascade(part.mLambda(), part.mAntiLambda(), confCascType1))
363363
continue;
364364

365365
cascQAHistos.fillQA<false, true>(part);
@@ -400,7 +400,7 @@ struct femtoUniversePairTaskTrackCascadeExtended {
400400

401401
for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) {
402402
// Cascade invariant mass cut
403-
if (!invMCascade(p2.mLambda(), p2.mAntiLambda()))
403+
if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType1))
404404
continue;
405405
// PID
406406
if (!isParticleCombined(p1, confTrackChoicePartOne))
@@ -434,7 +434,7 @@ struct femtoUniversePairTaskTrackCascadeExtended {
434434
const int multCol = confUseCent ? col.multV0M() : col.multNtr();
435435

436436
for (const auto& part : groupPartsTwo) {
437-
if (!invMCascade(part.mLambda(), part.mAntiLambda()))
437+
if (!invMCascade(part.mLambda(), part.mAntiLambda(), confCascType1))
438438
continue;
439439

440440
cascQAHistos.fillQA<false, true>(part);
@@ -454,17 +454,30 @@ struct femtoUniversePairTaskTrackCascadeExtended {
454454
}*/
455455
}
456456

457-
auto pairProcessFunc = [&](auto& p1, auto& p2) -> void {
457+
auto pairDuplicateCheckFunc = [&](auto& p1, auto& p2) -> void {
458458
// Cascade invariant mass cut for p1
459-
if (!invMCascade(p1.mLambda(), p1.mAntiLambda()))
459+
if (!invMCascade(p1.mLambda(), p1.mAntiLambda(), confCascType1))
460460
return;
461461
// Cascade invariant mass cut for p2
462-
if (!invMCascade(p2.mLambda(), p2.mAntiLambda()))
462+
if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType2))
463463
return;
464-
// track cleaning
464+
// track cleaning & checking for duplicate pairs
465465
if (!pairCleanerCasc.isCleanPair(p1, p2, parts)) {
466-
return;
466+
// mark for rejection the cascades that share a daughter with other cascades
467+
cascDuplicates.insert(p1.globalIndex());
468+
cascDuplicates.insert(p2.globalIndex());
467469
}
470+
};
471+
472+
auto pairProcessFunc = [&](auto& p1, auto& p2) -> void {
473+
if (cascDuplicates.contains(p1.globalIndex()) || cascDuplicates.contains(p2.globalIndex()))
474+
return;
475+
// Cascade invariant mass cut for p1
476+
if (!invMCascade(p1.mLambda(), p1.mAntiLambda(), confCascType1))
477+
return;
478+
// Cascade invariant mass cut for p2
479+
if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType2))
480+
return;
468481
if (confIsCPR.value) {
469482
if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) {
470483
return;
@@ -485,12 +498,19 @@ struct femtoUniversePairTaskTrackCascadeExtended {
485498

486499
sameEventCont.setPair<false>(p1, p2, multCol, confUse3D, 1.0f);
487500
};
501+
cascDuplicates.clear();
488502
if (confCascType1 == confCascType2) {
503+
for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) {
504+
pairDuplicateCheckFunc(p1, p2);
505+
}
489506
/// Now build the combinations for identical cascades
490507
for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) {
491508
pairProcessFunc(p1, p2);
492509
}
493510
} else {
511+
for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) {
512+
pairDuplicateCheckFunc(p1, p2);
513+
}
494514
/// Now build the combinations for non-identical cascades
495515
for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) {
496516
pairProcessFunc(p1, p2);
@@ -517,7 +537,7 @@ struct femtoUniversePairTaskTrackCascadeExtended {
517537
}
518538
for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) {
519539
// Cascade invariant mass cut
520-
if (!invMCascade(p2.mLambda(), p2.mAntiLambda()))
540+
if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType1))
521541
continue;
522542
// PID
523543
if (!isParticleCombined(p1, confTrackChoicePartOne))
@@ -561,10 +581,10 @@ struct femtoUniversePairTaskTrackCascadeExtended {
561581
}
562582
for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) {
563583
// Cascade invariant mass cut for p1
564-
if (!invMCascade(p1.mLambda(), p1.mAntiLambda()))
584+
if (!invMCascade(p1.mLambda(), p1.mAntiLambda(), confCascType1))
565585
continue;
566586
// Cascade invariant mass cut for p2
567-
if (!invMCascade(p2.mLambda(), p2.mAntiLambda()))
587+
if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType2))
568588
continue;
569589

570590
const auto& posChild1 = parts.iteratorAt(p1.index() - 3);

0 commit comments

Comments
 (0)