260 {
261
262 out_x_float.clear();
263 out_edge_index_int64.clear();
264 out_batch_int64.clear();
265 out_counts_int64.clear();
266 out_Ntrk_float.clear();
267
268 auto tryGetVectorFloat = [&](
const std::string& baseName, std::vector<float>&
out)->
bool {
269 std::string withPref =
m_prefix.value() + baseName;
272 return true;
273 }
276 return true;
277 }
278 ATH_MSG_DEBUG(
"Attribute not found: " << withPref <<
" nor " << baseName);
279 return false;
280 };
281
282 auto tryGetVectorInt = [&](
const std::string& baseName, std::vector<int>&
out)->
bool {
283 std::string withPref =
m_prefix.value() + baseName;
286 return true;
287 }
290 return true;
291 }
292 ATH_MSG_DEBUG(
"Attribute not found: " << withPref <<
" nor " << baseName);
293 return false;
294 };
295
296 auto tryGetInt = [&](
const std::string& baseName,
int&
out)->
bool {
297 std::string withPref =
m_prefix.value() + baseName;
300 return true;
301 }
304 return true;
305 }
306 ATH_MSG_DEBUG(
"Attribute not found: " << withPref <<
" nor " << baseName);
307 return false;
308 };
309
310
311 std::vector<float> lnR, lnkT,
z;
312 std::vector<int> idp1, idp2;
313 int nSplits = 0;
314
315 bool ok_lnR = tryGetVectorFloat("LundAllLnR", lnR);
316 bool ok_lnkT = tryGetVectorFloat("LundAllLnKT", lnkT);
317 bool ok_z = tryGetVectorFloat(
"LundAllZ",
z);
318 bool ok_idp1 = tryGetVectorInt("LundAllIDP1", idp1);
319 bool ok_idp2 = tryGetVectorInt("LundAllIDP2", idp2);
320 bool ok_nsp = tryGetInt("nSplits", nSplits);
321
322 if (!(ok_lnR && ok_lnkT && ok_z && ok_idp1 && ok_idp2 && ok_nsp)) {
323 ATH_MSG_DEBUG(
"Missing one or more Lund decorations (lnR/lnkT/z/idp1/idp2/nSplits). Aborting build.");
324 return false;
325 }
326
327 size_t n_nodes = lnR.size();
328 if (n_nodes == 0) {
329 ATH_MSG_DEBUG(
"Lund decorations present but zero-length vectors.");
330 return false;
331 }
332
333
334 float ntrk_f = 0.f;
335 int tmp_ntrk_i = 0;
336 bool gotNtrk = false;
337
338 std::vector<std::string> ntrkCandidates = { "LRJ_Nconst_Charged", "nTrk", "Ntrk", "NTracks" };
339 for (auto &cand : ntrkCandidates) {
340 std::string withPref =
m_prefix.value() + cand;
341 if (jet.
getAttribute(withPref, tmp_ntrk_i)) { ntrk_f =
static_cast<float>(tmp_ntrk_i); gotNtrk =
true;
ATH_MSG_DEBUG(
"Using Ntrk attr: " << withPref);
break; }
342 if (jet.
getAttribute(cand, tmp_ntrk_i)) { ntrk_f =
static_cast<float>(tmp_ntrk_i); gotNtrk =
true;
ATH_MSG_DEBUG(
"Using Ntrk attr: " << cand);
break; }
343 }
344 if (!gotNtrk) {
347 const xAOD::IParticle*
p = *
links[
i];
349 if (fe && fe->
isCharged()) ntrk_f += 1.f;
350 }
351 ATH_MSG_DEBUG(
"Computed Ntrk from constituents: " << ntrk_f);
352 }
353
354
355
357 float ln_kTcut = (kTsel_val > 0.f) ? std::log(std::max(1e-12f, kTsel_val)) : -1e9f;
358
359 std::vector<char>
mask(n_nodes, 0);
360 size_t n_selected = 0;
361 for (
size_t i = 0;
i < n_nodes; ++
i) {
363 if (lnk > ln_kTcut) {
mask[
i] = 1; ++n_selected; }
365 }
366
367 if (n_selected < 1) {
368 ATH_MSG_DEBUG(
"No nodes passed kT selection (n_selected=" << n_selected <<
").");
369 return false;
370 }
371
372
373 out_x_float.reserve(n_selected * 3);
374 for (
size_t i = 0;
i < n_nodes; ++
i) {
375 if (!mask[i]) continue;
376 float f_ln1overdR = lnR[
i];
377 float f_lnkT = lnkT[
i];
378 float zval = std::max(1e-6f,
z[i]);
379 float f_ln1overz = -std::log(zval);
380
384
385 out_x_float.push_back(dr_std);
386 out_x_float.push_back(kt_std);
387 out_x_float.push_back(z_std);
388 }
389
390
391 std::vector<int> old2new(n_nodes, -1);
392 int new_idx = 0;
393 for (
size_t i = 0;
i < n_nodes; ++
i) {
394 if (mask[i]) old2new[
i] = new_idx++;
395 }
396
397
398 for (size_t child = 0; child < n_nodes; ++child) {
399 if (!mask[child]) continue;
400 int p1 = (child < idp1.size()) ? idp1[child] : -1;
401 int p2 = (child < idp2.size()) ? idp2[child] : -1;
402 if (p1 >= 0 && p1 < static_cast<int>(n_nodes) && old2new[p1] >= 0) {
403 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[p1]));
404 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[child]));
405
406 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[child]));
407 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[p1]));
408 }
409 if (p2 >= 0 && p2 < static_cast<int>(n_nodes) && old2new[p2] >= 0) {
410 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[p2]));
411 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[child]));
412 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[child]));
413 out_edge_index_int64.push_back(static_cast<int64_t>(old2new[p2]));
414 }
415 }
416
417
418 for (int64_t i = 0;
i < new_idx; ++
i) out_batch_int64.push_back(0);
419
420
421 out_counts_int64.push_back(static_cast<int64_t>(new_idx));
422
423
425
427 out_Ntrk_float.reserve(batch_size);
429 out_Ntrk_float.push_back(ntrk_std);
430 }
431
432 if (out_x_float.empty() || out_counts_int64.empty()) {
434 return false;
435 }
436
438 << " edges=" << (out_edge_index_int64.size()/2)
439 << " ntrk=" << ntrk_f);
440
441 return true;
442}
Gaudi::Property< float > m_mean_ntrk
Gaudi::Property< float > m_mean_dr
Gaudi::Property< float > m_std_ntrk
Gaudi::Property< float > m_std_kt
Gaudi::Property< float > m_mean_z
Gaudi::Property< float > m_std_z
Gaudi::Property< float > m_std_dr
Gaudi::Property< float > m_kTSelection
Gaudi::Property< int > m_expectedBatchSize
Gaudi::Property< float > m_mean_kt
Gaudi::Property< std::string > m_prefix
size_t numConstituents() const
Number of constituents in this jets (this is valid even when reading a file where the constituents ha...
const std::vector< ElementLink< IParticleContainer > > & constituentLinks() const
Direct access to constituents. WARNING expert use only.
bool getAttribute(AttributeID type, T &value) const
Retrieve attribute moment by enum.
FlowElement_v1 FlowElement
Definition of the current "pfo version".