@@ -55,6 +55,8 @@ struct lambdakzeromcbuilder {
5555 Configurable<bool > addGeneratedAntiLambda{" addGeneratedAntiLambda" , false , " add V0MCCore entry for generated, not-recoed AntiLambda" };
5656 Configurable<bool > addGeneratedGamma{" addGeneratedGamma" , false , " add V0MCCore entry for generated, not-recoed Gamma" };
5757
58+ Configurable<bool > treatPiToMuDecays{" treatPiToMuDecays" , true , " if true, will correctly capture pi -> mu and V0 label will still point to originating V0 decay in those cases. Nota bene: prong info will still be for the muon!" };
59+
5860 Configurable<float > rapidityWindow{" rapidityWindow" , 0.5 , " rapidity window to save non-recoed candidates" };
5961
6062 HistogramRegistry histos{" Histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
@@ -111,15 +113,38 @@ struct lambdakzeromcbuilder {
111113 std::array<float , 3 > posP;
112114 std::array<float , 3 > negP;
113115 std::array<float , 3 > momentum;
114- uint64_t packedMcParticleIndices;
115116 };
116117 mcV0info thisInfo;
117118 // *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*
118119
119- // prong index combiner
120- uint64_t combineProngIndices (uint32_t low, uint32_t high)
120+ // kink handling
121+ template <typename mcpart>
122+ int getOriginatingParticle (mcpart const & part, int & indexForPositionOfDecay)
121123 {
122- return (((uint64_t )high) << 32 ) | ((uint64_t )low);
124+ int returnValue = -1 ;
125+ if (part.has_mothers ()) {
126+ auto const & motherList = part.template mothers_as <aod::McParticles>();
127+ if (motherList.size () == 1 ) {
128+ for (const auto & mother : motherList) {
129+ if (std::abs (part.pdgCode ()) == 13 && treatPiToMuDecays) {
130+ // muon decay, de-ref mother twice
131+ if (mother.has_mothers ()) {
132+ auto grandMotherList = mother.template mothers_as <aod::McParticles>();
133+ if (grandMotherList.size () == 1 ) {
134+ for (const auto & grandMother : grandMotherList) {
135+ returnValue = grandMother.globalIndex ();
136+ indexForPositionOfDecay = mother.globalIndex (); // for V0 decay position: grab muon
137+ }
138+ }
139+ }
140+ } else {
141+ returnValue = mother.globalIndex ();
142+ indexForPositionOfDecay = part.globalIndex ();
143+ }
144+ }
145+ }
146+ }
147+ return returnValue;
123148 }
124149
125150 // *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*
@@ -131,7 +156,6 @@ struct lambdakzeromcbuilder {
131156 std::vector<bool > mcParticleIsReco (mcParticles.size (), false ); // mc Particle not recoed by V0s
132157
133158 for (auto & v0 : v0table) {
134- thisInfo.packedMcParticleIndices = 0 ; // not de-referenced properly yet
135159 thisInfo.label = -1 ;
136160 thisInfo.motherLabel = -1 ;
137161 thisInfo.pdgCode = 0 ;
@@ -152,7 +176,6 @@ struct lambdakzeromcbuilder {
152176 auto lMCNegTrack = lNegTrack.mcParticle_as <aod::McParticles>();
153177 auto lMCPosTrack = lPosTrack.mcParticle_as <aod::McParticles>();
154178
155- thisInfo.packedMcParticleIndices = combineProngIndices (lPosTrack.mcParticleId (), lNegTrack.mcParticleId ());
156179 thisInfo.pdgCodePositive = lMCPosTrack.pdgCode ();
157180 thisInfo.pdgCodeNegative = lMCNegTrack.pdgCode ();
158181 thisInfo.processPositive = lMCPosTrack.getProcess ();
@@ -163,65 +186,71 @@ struct lambdakzeromcbuilder {
163186 thisInfo.negP [0 ] = lMCNegTrack.px ();
164187 thisInfo.negP [1 ] = lMCNegTrack.py ();
165188 thisInfo.negP [2 ] = lMCNegTrack.pz ();
166- if (lMCNegTrack.has_mothers () && lMCPosTrack.has_mothers ()) {
167- for (auto & lNegMother : lMCNegTrack.mothers_as <aod::McParticles>()) {
168- for (auto & lPosMother : lMCPosTrack.mothers_as <aod::McParticles>()) {
169- if (lNegMother.globalIndex () == lPosMother.globalIndex ()) {
170- thisInfo.label = lNegMother.globalIndex ();
171- thisInfo.xyz [0 ] = lMCPosTrack.vx ();
172- thisInfo.xyz [1 ] = lMCPosTrack.vy ();
173- thisInfo.xyz [2 ] = lMCPosTrack.vz ();
174-
175- // MC pos. and neg. daughters are the same! Looking for replacement...
176- if (lMCPosTrack.globalIndex () == lMCNegTrack.globalIndex ()) {
177- auto const & daughters = lNegMother.daughters_as <aod::McParticles>();
178- for (auto & ldau : daughters) {
179- // check if the candidate originate from a decay
180- // if not, this is not a suitable candidate for one of the decay daughters
181- if (ldau.getProcess () != 4 ) // see TMCProcess.h
182- continue ;
183-
184- if (lMCPosTrack.pdgCode () < 0 && ldau.pdgCode () > 0 ) { // the positive track needs to be changed
185- thisInfo.pdgCodePositive = ldau.pdgCode ();
186- thisInfo.processPositive = ldau.getProcess ();
187- thisInfo.posP [0 ] = ldau.px ();
188- thisInfo.posP [1 ] = ldau.py ();
189- thisInfo.posP [2 ] = ldau.pz ();
190- thisInfo.xyz [0 ] = ldau.vx ();
191- thisInfo.xyz [1 ] = ldau.vy ();
192- thisInfo.xyz [2 ] = ldau.vz ();
193- }
194- if (lMCNegTrack.pdgCode () > 0 && ldau.pdgCode () < 0 ) { // the negative track needs to be changed
195- thisInfo.pdgCodeNegative = ldau.pdgCode ();
196- thisInfo.processNegative = ldau.getProcess ();
197- thisInfo.negP [0 ] = ldau.px ();
198- thisInfo.negP [1 ] = ldau.py ();
199- thisInfo.negP [2 ] = ldau.pz ();
200- }
201- }
202- }
203189
204- if (lNegMother.has_mcCollision ()) {
205- thisInfo.mcCollision = lNegMother.mcCollisionId (); // save this reference, please
206- }
190+ // check for pi -> mu + antineutrino decay
191+ // if present, de-reference original V0 correctly and provide label to original object
192+ // NOTA BENE: the prong info will still correspond to a muon, treat carefully!
193+ int negOriginating = -1 , posOriginating = -1 , particleForDecayPositionIdx = -1 ;
194+ negOriginating = getOriginatingParticle (lMCNegTrack, particleForDecayPositionIdx);
195+ posOriginating = getOriginatingParticle (lMCPosTrack, particleForDecayPositionIdx);
196+
197+ if (negOriginating > -1 && negOriginating == posOriginating) {
198+ auto originatingV0 = mcParticles.rawIteratorAt (negOriginating);
199+ auto particleForDecayPosition = mcParticles.rawIteratorAt (particleForDecayPositionIdx);
200+
201+ thisInfo.label = originatingV0.globalIndex ();
202+ thisInfo.xyz [0 ] = particleForDecayPosition.vx ();
203+ thisInfo.xyz [1 ] = particleForDecayPosition.vy ();
204+ thisInfo.xyz [2 ] = particleForDecayPosition.vz ();
205+
206+ // MC pos. and neg. daughters are the same! Looking for replacement...
207+ // if (lMCPosTrack.globalIndex() == lMCNegTrack.globalIndex()) {
208+ // auto const& daughters = lNegMother.daughters_as<aod::McParticles>();
209+ // for (auto& ldau : daughters) {
210+ // // check if the candidate originates from a decay
211+ // // if not, this is not a suitable candidate for one of the decay daughters
212+ // if (ldau.getProcess() != 4) // see TMCProcess.h
213+ // continue;
214+
215+ // if (lMCPosTrack.pdgCode() < 0 && ldau.pdgCode() > 0) { // the positive track needs to be changed
216+ // thisInfo.pdgCodePositive = ldau.pdgCode();
217+ // thisInfo.processPositive = ldau.getProcess();
218+ // thisInfo.posP[0] = ldau.px();
219+ // thisInfo.posP[1] = ldau.py();
220+ // thisInfo.posP[2] = ldau.pz();
221+ // thisInfo.xyz[0] = ldau.vx();
222+ // thisInfo.xyz[1] = ldau.vy();
223+ // thisInfo.xyz[2] = ldau.vz();
224+ // }
225+ // if (lMCNegTrack.pdgCode() > 0 && ldau.pdgCode() < 0) { // the negative track needs to be changed
226+ // thisInfo.pdgCodeNegative = ldau.pdgCode();
227+ // thisInfo.processNegative = ldau.getProcess();
228+ // thisInfo.negP[0] = ldau.px();
229+ // thisInfo.negP[1] = ldau.py();
230+ // thisInfo.negP[2] = ldau.pz();
231+ // }
232+ // }
233+ // }
234+
235+ if (originatingV0.has_mcCollision ()) {
236+ thisInfo.mcCollision = originatingV0.mcCollisionId (); // save this reference, please
237+ }
207238
208- // acquire information
209- thisInfo.pdgCode = lNegMother.pdgCode ();
210- thisInfo.isPhysicalPrimary = lNegMother.isPhysicalPrimary ();
211- thisInfo.momentum [0 ] = lNegMother.px ();
212- thisInfo.momentum [1 ] = lNegMother.py ();
213- thisInfo.momentum [2 ] = lNegMother.pz ();
214-
215- if (lNegMother.has_mothers ()) {
216- for (auto & lNegGrandMother : lNegMother.mothers_as <aod::McParticles>()) {
217- thisInfo.pdgCodeMother = lNegGrandMother.pdgCode ();
218- thisInfo.motherLabel = lNegGrandMother.globalIndex ();
219- }
220- }
221- }
239+ // acquire information
240+ thisInfo.pdgCode = originatingV0.pdgCode ();
241+ thisInfo.isPhysicalPrimary = originatingV0.isPhysicalPrimary ();
242+ thisInfo.momentum [0 ] = originatingV0.px ();
243+ thisInfo.momentum [1 ] = originatingV0.py ();
244+ thisInfo.momentum [2 ] = originatingV0.pz ();
245+
246+ if (originatingV0.has_mothers ()) {
247+ for (auto & lV0Mother : originatingV0.mothers_as <aod::McParticles>()) {
248+ thisInfo.pdgCodeMother = lV0Mother.pdgCode ();
249+ thisInfo.motherLabel = lV0Mother.globalIndex ();
222250 }
223251 }
224252 }
253+
225254 } // end association check
226255 // Construct label table (note: this will be joinable with V0Datas!)
227256 v0labels (
@@ -308,7 +337,6 @@ struct lambdakzeromcbuilder {
308337 if (populateV0MCCoresAsymmetric) {
309338 // first step: add any un-recoed v0mmcores that were requested
310339 for (auto & mcParticle : mcParticles) {
311- thisInfo.packedMcParticleIndices = 0 ;
312340 thisInfo.label = -1 ;
313341 thisInfo.motherLabel = -1 ;
314342 thisInfo.pdgCode = 0 ;
0 commit comments