1313// / \note Extended from HFCandidateCreator2Prong, HFCandidateCreator3Prong, HFCandidateCreatorX
1414// /
1515// / \author Gian Michele Innocenti <gian.michele.innocenti@cern.ch>, CERN
16+ // / \author Luigi Dello Stritto <luigi.dello.stritto@cern.ch >, SALERNO
17+ // / \author Mattia Faggin <mattia.faggin@cern.ch>, University and INFN PADOVA
1618
1719#include " Framework/AnalysisTask.h"
1820#include " DetectorsVertexing/DCAFitterN.h"
2527using namespace o2 ;
2628using namespace o2 ::framework;
2729using namespace o2 ::aod::hf_cand;
28- using namespace o2 ::aod::hf_cand_prong2;
29- using namespace o2 ::aod::hf_cand_prong3;
3030using namespace o2 ::aod::hf_cand_xicc;
3131using namespace o2 ::framework::expressions; // FIXME not sure if this is needed
3232
@@ -53,11 +53,12 @@ struct HFCandidateCreatorXicc {
5353 OutputObj<TH1F> hmassXic{TH1F (" hmassXic" , " xic candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries" , 500 , 1.6 , 2.6 )};
5454 OutputObj<TH1F> hCovPVXX{TH1F (" hCovPVXX" , " 3-prong candidates;XX element of cov. matrix of prim. vtx position (cm^{2});entries" , 100 , 0 ., 1 .e -4 )};
5555 OutputObj<TH1F> hCovSVXX{TH1F (" hCovSVXX" , " 3-prong candidates;XX element of cov. matrix of sec. vtx position (cm^{2});entries" , 100 , 0 ., 0.2 )};
56- OutputObj<TH1F> hmassXicc{TH1F (" hmassXicc" , " xicc candidates;inv. mass (#Xi_{c } #pi) (GeV/#it{c}^{2});entries" , 400 , 2.5 , 4 .5 )};
56+ OutputObj<TH1F> hmassXicc{TH1F (" hmassXicc" , " xicc candidates;inv. mass (#Xi_{cc } #pi) (GeV/#it{c}^{2});entries" , 400 , 2.5 , 6 .5 )};
5757
5858 double massPi = RecoDecay::getMassPDG(kPiPlus );
5959 double massK = RecoDecay::getMassPDG(kKPlus );
60- double massPiKPi{0 .};
60+ double massXic = RecoDecay::getMassPDG(4232 );
61+ double massXicc{0 .};
6162
6263 Configurable<int > d_selectionFlagXic{" d_selectionFlagXic" , 1 , " Selection Flag for Xic" };
6364 Configurable<double > cutYCandMax{" cutYCandMax" , -1 ., " max. cand. rapidity" };
@@ -88,59 +89,101 @@ struct HFCandidateCreatorXicc {
8889 df2.setUseAbsDCA (true );
8990
9091 for (auto & xicCand : xicCands) {
91- if (!(xicCand.hfflag () & 1 << XicToPKPi)) {
92+ if (!(xicCand.hfflag () & 1 << o2::aod::hf_cand_prong3:: XicToPKPi)) {
9293 continue ;
94+ }
95+ if (xicCand.isSelXicToPKPi () >= d_selectionFlagXic) {
96+ hmassXic->Fill (InvMassXicToPKPi (xicCand), xicCand.pt ());
97+ }
98+ if (xicCand.isSelXicToPiKP () >= d_selectionFlagXic) {
99+ hmassXic->Fill (InvMassXicToPiKP (xicCand), xicCand.pt ());
100+ }
101+ auto track0 = xicCand.index0_as <aod::BigTracks>();
102+ auto track1 = xicCand.index1_as <aod::BigTracks>();
103+ auto track2 = xicCand.index2_as <aod::BigTracks>();
104+ auto trackParVar0 = getTrackParCov (track0);
105+ auto trackParVar1 = getTrackParCov (track1);
106+ auto trackParVar2 = getTrackParCov (track2);
107+ auto collision = track0.collision (); // FIXME: not sure we need it.
93108
94- if (xicCand.isSelXicToPKPi () >= d_selectionFlagXic) {
95- hmassXic->Fill (InvMassXicToPKPi (xicCand), xicCand.pt ());
109+ // reconstruct the 3-prong secondary vertex
110+ if (df3.process (trackParVar0, trackParVar1, trackParVar2) == 0 ) {
111+ continue ;
112+ }
113+ const auto & secondaryVertex = df3.getPCACandidate ();
114+ trackParVar0.propagateTo (secondaryVertex[0 ], magneticField);
115+ trackParVar1.propagateTo (secondaryVertex[0 ], magneticField);
116+ trackParVar2.propagateTo (secondaryVertex[0 ], magneticField);
117+
118+ array<float , 3 > pvecpK = {track0.px () + track1.px (), track0.py () + track1.py (), track0.pz () + track1.pz ()};
119+ array<float , 3 > pvecxic = {pvecpK[0 ] + track2.px (), pvecpK[1 ] + track2.py (), pvecpK[2 ] + track2.pz ()};
120+ auto trackpK = o2::dataformats::V0 (df3.getPCACandidatePos (), pvecpK, df3.calcPCACovMatrixFlat (),
121+ trackParVar0, trackParVar1, {0 , 0 }, {0 , 0 });
122+ auto trackxic = o2::dataformats::V0 (df3.getPCACandidatePos (), pvecxic, df3.calcPCACovMatrixFlat (),
123+ trackpK, trackParVar2, {0 , 0 }, {0 , 0 });
124+
125+ int index0Xic = track0.globalIndex ();
126+ int index1Xic = track1.globalIndex ();
127+ int index2Xic = track2.globalIndex ();
128+ int charge = track0.sign () + track1.sign () + track2.sign ();
129+
130+ for (auto & trackpion : tracks) {
131+ if (trackpion.pt () < 1.0 ) {
132+ continue ;
96133 }
97- if (xicCand. isSelXicToPiKP () >= d_selectionFlagXic ) {
98- hmassXic-> Fill ( InvMassXicToPiKP (xicCand), xicCand. pt ()) ;
134+ if (trackpion. sign () * charge < 0 ) {
135+ continue ;
99136 }
100- auto track0 = xicCand.index0_as <aod::BigTracks>();
101- auto track1 = xicCand.index1_as <aod::BigTracks>();
102- auto track2 = xicCand.index2_as <aod::BigTracks>();
103- auto trackParVar0 = getTrackParCov (track0);
104- auto trackParVar1 = getTrackParCov (track1);
105- auto trackParVar2 = getTrackParCov (track2);
106- auto collision = track0.collision (); // FIXME: not sure we need it.
107-
108- // reconstruct the 3-prong secondary vertex
109- if (df3.process (trackParVar0, trackParVar1, trackParVar2) == 0 ) {
137+ if (trackpion.globalIndex () == index0Xic || trackpion.globalIndex () == index1Xic || trackpion.globalIndex () == index2Xic) {
110138 continue ;
111139 }
112- const auto & secondaryVertex = df3.getPCACandidate ();
113- trackParVar0.propagateTo (secondaryVertex[0 ], magneticField);
114- trackParVar1.propagateTo (secondaryVertex[0 ], magneticField);
115- trackParVar2.propagateTo (secondaryVertex[0 ], magneticField);
116-
117- array<float , 3 > pvecpK = {track0.px () + track1.px (), track0.py () + track1.py (), track0.pz () + track1.pz ()};
118- array<float , 3 > pvecxic = {pvecpK[0 ] + track2.px (), pvecpK[1 ] + track2.py (), pvecpK[2 ] + track2.pz ()};
119- auto trackpK = o2::dataformats::V0 (df3.getPCACandidatePos (), pvecpK, df3.calcPCACovMatrixFlat (),
120- trackParVar0, trackParVar1, {0 , 0 }, {0 , 0 });
121- auto trackxic = o2::dataformats::V0 (df3.getPCACandidatePos (), pvecxic, df3.calcPCACovMatrixFlat (),
122- trackpK, trackParVar2, {0 , 0 }, {0 , 0 });
123-
124- int index0Xic = track0.globalIndex ();
125- int index1Xic = track1.globalIndex ();
126- int index2Xic = track2.globalIndex ();
127- for (auto & trackPos : tracks) {
128- if (trackPos.sign () < 0 ) { // select only positive tracks - use partitions?
129- continue ;
130- }
131-
132- rowCandidateBase (collision.globalIndex (),
133- collision.posX (), collision.posY (), collision.posZ (),
134- secondaryVertex[0 ], secondaryVertex[1 ], secondaryVertex[2 ],
135- 0 ., 0 .,
136- 0 .,
137- 1 ., 0 ., 0 .,
138- 0 ., 0 ., 0 .,
139- 0 ., 0 .,
140- 0 ., 0 .,
141- 0 , 0 ,
142- 1 );
140+ array<float , 3 > pvecpion;
141+ auto trackParVarPi = getTrackParCov (trackpion);
142+
143+ // reconstruct the 3-prong X vertex
144+ if (df2.process (trackxic, trackParVarPi) == 0 ) {
145+ continue ;
143146 }
147+
148+ // calculate relevant properties
149+ const auto & secondaryVertexXicc = df2.getPCACandidate ();
150+ auto chi2PCA = df2.getChi2AtPCACandidate ();
151+ auto covMatrixPCA = df2.calcPCACovMatrix ().Array ();
152+
153+ df2.propagateTracksToVertex ();
154+ df2.getTrack (0 ).getPxPyPzGlo (pvecxic);
155+ df2.getTrack (1 ).getPxPyPzGlo (pvecpion);
156+
157+ auto primaryVertex = getPrimaryVertex (collision);
158+ auto covMatrixPV = primaryVertex.getCov ();
159+ o2::dataformats::DCA impactParameter0;
160+ o2::dataformats::DCA impactParameter1;
161+ trackxic.propagateToDCA (primaryVertex, magneticField, &impactParameter0);
162+ trackParVarPi.propagateToDCA (primaryVertex, magneticField, &impactParameter1);
163+
164+ // get uncertainty of the decay length
165+ double phi, theta;
166+ getPointDirection (array{collision.posX (), collision.posY (), collision.posZ ()}, secondaryVertexXicc, phi, theta);
167+ auto errorDecayLength = std::sqrt (getRotatedCovMatrixXX (covMatrixPV, phi, theta) + getRotatedCovMatrixXX (covMatrixPCA, phi, theta));
168+ auto errorDecayLengthXY = std::sqrt (getRotatedCovMatrixXX (covMatrixPV, phi, 0 .) + getRotatedCovMatrixXX (covMatrixPCA, phi, 0 .));
169+
170+ int hfFlag = 1 << DecayType::XiccToXicPi;
171+
172+ rowCandidateBase (collision.globalIndex (),
173+ collision.posX (), collision.posY (), collision.posZ (),
174+ secondaryVertexXicc[0 ], secondaryVertexXicc[1 ], secondaryVertexXicc[2 ],
175+ errorDecayLength, errorDecayLengthXY,
176+ chi2PCA,
177+ pvecxic[0 ], pvecxic[1 ], pvecxic[2 ],
178+ pvecpion[0 ], pvecpion[1 ], pvecpion[2 ],
179+ impactParameter0.getY (), impactParameter1.getY (),
180+ std::sqrt (impactParameter0.getSigmaY2 ()), std::sqrt (impactParameter1.getSigmaY2 ()),
181+ xicCand.globalIndex (), trackpion.globalIndex (),
182+ hfFlag);
183+ // calculate invariant mass
184+ auto arrayMomenta = array{pvecxic, pvecpion};
185+ massXicc = RecoDecay::M (std::move (arrayMomenta), array{massXic, massPi});
186+ hmassXicc->Fill (massXicc);
144187 } // if on selected Xicc
145188 } // loop over candidates
146189 } // end of process
@@ -178,10 +221,26 @@ struct HFCandidateCreatorXiccMC {
178221
179222 // Match generated particles.
180223 for (auto & particle : particlesMC) {
224+
181225 // Printf("New gen. candidate");
182226 flag = 1 ;
183227 origin = 0 ;
184228 channel = 0 ;
229+ // Xicc → Xic + π+
230+ if (RecoDecay::isMatchedMCGen (particlesMC, particle, 4422 , array{4232 , +kPiPlus }, true )) {
231+ // Match Xic -> pKπ
232+ std::vector<int > arrDaughter;
233+ RecoDecay::getDaughters (particlesMC, particle, &arrDaughter, array{4232 }, 1 );
234+ auto XicCandMC = particlesMC.iteratorAt (arrDaughter[0 ]);
235+ // Printf("Checking Ξc± → p± K∓ π±");
236+ if (RecoDecay::isMatchedMCGen (particlesMC, particle, pdg::Code::kXiCPlus , array{+kProton , -kKPlus , +kPiPlus }, true , &sign)) {
237+ flag = sign * (1 << XiccToXicPi);
238+ }
239+ }
240+ // Check whether the particle is non-prompt (from a b quark).
241+ if (flag != 0 ) {
242+ origin = (RecoDecay::getMother (particlesMC, particle, 5 , true ) > -1 ? NonPrompt : Prompt);
243+ }
185244 rowMCMatchGen (flag, origin, channel);
186245 }
187246 }
0 commit comments