148 ATH_MSG_WARNING(
"No valid features for transformer input. Skipping inference.");
149 return StatusCode::SUCCESS;
152 if (msgLvl(MSG::DEBUG)) {
154 ATH_MSG_DEBUG(
"=== DEBUGGING: Transformer input features for first 10 nodes ===");
155 const int64_t debugNodes = std::min(S,
static_cast<int64_t
>(10));
156 for (int64_t nodeIdx = 0; nodeIdx < debugNodes; ++nodeIdx) {
159 <<
"x=" << featuresFlat[baseIdx + 0] <<
", "
160 <<
"y=" << featuresFlat[baseIdx + 1] <<
", "
161 <<
"z=" << featuresFlat[baseIdx + 2] <<
", "
162 <<
"layers=" << featuresFlat[baseIdx + 3] <<
", "
163 <<
"nSp=" << featuresFlat[baseIdx + 4] <<
", "
164 <<
"bucketSize=" << featuresFlat[baseIdx + 5]);
170 graphData.
graph.reset();
171 graphData.
graph = std::make_unique<InferenceGraph>();
172 graphData.
graph->dataTensor.reserve(2);
174 Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
179 graphData.
graph->dataTensor.emplace_back(
180 Ort::Value::CreateTensor<float>(memInfo,
187 Ort::AllocatorWithDefaultOptions allocator;
188 std::vector<int64_t> mShape{1, S};
189 Ort::Value padVal = Ort::Value::CreateTensor(allocator,
192 ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL);
193 bool* maskPtr = padVal.GetTensorMutableData<
bool>();
194 for (int64_t i = 0; i < S; ++i) maskPtr[i] =
false;
195 graphData.
graph->dataTensor.emplace_back(std::move(padVal));
197 return StatusCode::SUCCESS;
203 graphData.
graph.reset();
209 graphData.
graph = std::make_unique<InferenceGraph>();
210 graphData.
graph->dataTensor.reserve(2);
218 std::vector<BucketGraphUtils::NodeAux> nodes;
224 const int64_t numNodes =
static_cast<int64_t
>(nodes.size());
226 <<
" -> nodes (size>0): " << numNodes
230 ATH_MSG_WARNING(
"No valid buckets found (all have size 0.0). Skipping graph building.");
231 return StatusCode::SUCCESS;
235 if (numNodes * nFeatPerNode !=
static_cast<int64_t
>(graphData.
featureLeaves.size())) {
236 ATH_MSG_ERROR(
"Feature size mismatch: expected " << (numNodes * nFeatPerNode)
238 return StatusCode::FAILURE;
241 Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
242 std::vector<int64_t> featShape{numNodes, nFeatPerNode};
243 graphData.
graph->dataTensor.emplace_back(
244 Ort::Value::CreateTensor<float>(memInfo,
260 for (
size_t k = 0; k < graphData.
srcEdges.size(); ++k) {
261 const int64_t u = graphData.
srcEdges[k];
262 const int64_t v = graphData.
desEdges[k];
263 const bool okU = (u >= 0 && u < numNodes);
264 const bool okV = (v >= 0 && v < numNodes);
271 ATH_MSG_DEBUG(
"Drop invalid edge " << k <<
": (" << u <<
"->" << v
272 <<
"), valid node range [0," << (numNodes-1) <<
"]");
283 const size_t E = graphData.
srcEdges.size();
285 if (msgLvl(MSG::DEBUG)) {
289 for (
size_t k = 0; k < dumpE; ++k) {
295 std::vector<int> nodeConnections(numNodes, 0);
296 for (
size_t k = 0; k < graphData.
srcEdges.size(); ++k) {
297 const int64_t u = graphData.
srcEdges[k];
298 const int64_t v = graphData.
desEdges[k];
299 if (u >= 0 && u < numNodes) nodeConnections[u]++;
300 if (v >= 0 && v < numNodes) nodeConnections[v]++;
303 ATH_MSG_DEBUG(
"=== DEBUGGING: Node Connections (first 10 nodes) ===");
304 const int64_t debugNodeCount = std::min(numNodes,
static_cast<int64_t
>(10));
305 for (int64_t i = 0; i < debugNodeCount; ++i) {
306 ATH_MSG_DEBUG(
"Node[" << i <<
"] connections: " << nodeConnections[i]);
310 ATH_MSG_DEBUG(
"=== DEBUGGING: Detailed Edge Connections (first 10 nodes) ===");
311 for (int64_t nodeIdx = 0; nodeIdx < debugNodeCount; ++nodeIdx) {
312 std::stringstream connections;
313 connections <<
"Node[" << nodeIdx <<
"] connected to: ";
314 bool foundAny =
false;
316 for (
size_t k = 0; k < graphData.
srcEdges.size(); ++k) {
317 const int64_t u = graphData.
srcEdges[k];
318 const int64_t v = graphData.
desEdges[k];
321 if (foundAny) connections <<
", ";
324 }
else if (v == nodeIdx) {
325 if (foundAny) connections <<
", ";
331 if (!foundAny) connections <<
"none";
347 std::vector<int64_t> edgeShape{2,
static_cast<int64_t
>(Efinal)};
348 graphData.
graph->dataTensor.emplace_back(
349 Ort::Value::CreateTensor<int64_t>(memInfo,
355 ATH_MSG_DEBUG(
"Built sparse bucket graph: N=" << numNodes <<
", E=" << Efinal);
356 return StatusCode::SUCCESS;
361 const std::vector<const char*>& inputNames,
362 const std::vector<const char*>& outputNames)
const
364 if (!graphData.
graph) {
366 return StatusCode::FAILURE;
368 if (graphData.
graph->dataTensor.empty()) {
370 return StatusCode::FAILURE;
375 graphData.
graph->dataTensor.reserve(inputNames.size() + outputNames.size());
376 if (graphData.
graph->dataTensor.size() < inputNames.size()) {
378 <<
" tensors but inference expects " << inputNames.size() <<
" inputs.");
379 return StatusCode::FAILURE;
382 if (msgLvl(MSG::DEBUG)) {
386 if (!graphData.
graph->dataTensor.empty()) {
387 const auto& featureTensor = graphData.
graph->dataTensor[0];
388 auto featShape = featureTensor.GetTensorTypeAndShapeInfo().GetShape();
390 << (featShape.size()>1 ? (
"," + std::to_string(featShape[1])) :
"")
391 << (featShape.size()>2 ? (
"," + std::to_string(featShape[2])) :
"") <<
"]");
393 float* featData =
const_cast<Ort::Value&
>(featureTensor).GetTensorMutableData<float>();
394 const size_t totalElements = featureTensor.GetTensorTypeAndShapeInfo().GetElementCount();
395 ATH_MSG_DEBUG(
"Features tensor total elements: " << totalElements);
398 const size_t nFeat = (featShape.size() > 1 && featShape[1] > 0) ?
static_cast<size_t>(featShape[1]) : 1;
399 const size_t nNodes = totalElements / nFeat;
400 const size_t debugNodes = std::min(nNodes,
static_cast<size_t>(10));
404 std::vector<std::string> featNames;
406 Ort::AllocatorWithDefaultOptions allocator;
407 Ort::ModelMetadata
meta =
model().GetModelMetadata();
408 auto keys =
meta.GetCustomMetadataMapKeysAllocated(allocator);
409 std::vector<std::string> keyNames;
410 keyNames.reserve(keys.size());
411 for (
const auto& k : keys) keyNames.emplace_back(k.get());
412 const std::array<std::string, 4> candidates{
413 "x_feature_names",
"node_feature_names",
"feature_names",
"input_feature_names"};
414 for (
const std::string& key : candidates) {
415 if (std::find(keyNames.begin(), keyNames.end(), key) != keyNames.end()) {
416 std::string val =
meta.LookupCustomMetadataMapAllocated(key.c_str(), allocator).get();
421 if (featNames.empty()) {
422 ATH_MSG_DEBUG(
"No usable feature-name metadata key found in model; using generic fN labels.");
425 auto featLabel = [&](
size_t f) -> std::string {
426 if (f < featNames.size())
return featNames[f];
427 return "f" + std::to_string(f);
432 std::ostringstream legend;
433 legend <<
"Node feature legend (" << nFeat <<
" features):";
434 for (
size_t f = 0; f < nFeat; ++f) {
435 legend <<
" f" << f <<
"=" << featLabel(f);
436 if (f + 1 < nFeat) legend <<
",";
441 for (
size_t n = 0; n < debugNodes; ++n) {
442 std::ostringstream row;
443 row <<
"ONNXNode[" << n <<
"]:";
444 for (
size_t f = 0; f < nFeat; ++f) {
445 row <<
" f" << f <<
"=" << featData[n * nFeat + f];
446 if (f + 1 < nFeat) row <<
",";
454 Ort::RunOptions run_options;
455 run_options.SetRunLogSeverityLevel(ORT_LOGGING_LEVEL_ERROR);
459 Ort::IoBinding binding(
model());
460 for (std::size_t i = 0; i < inputNames.size(); ++i) {
461 binding.BindInput(inputNames[i], graphData.
graph->dataTensor[i]);
464 Ort::MemoryInfo cpuOut = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
465 for (
const char* outName : outputNames) {
466 binding.BindOutput(outName, cpuOut);
469 model().Run(run_options, binding);
470 binding.SynchronizeOutputs();
472 std::vector<Ort::Value> outputs = binding.GetOutputValues();
473 if (outputs.empty()) {
475 return StatusCode::FAILURE;
478 float* outData = outputs[0].GetTensorMutableData<
float>();
479 const size_t outSize = outputs[0].GetTensorTypeAndShapeInfo().GetElementCount();
480 ATH_MSG_DEBUG(
"ONNX (IoBinding) raw output elementCount = " << outSize);
483 std::span<float> preds(outData, outData + outSize);
484 for (
size_t i = 0; i < outSize; ++i) {
485 if (!std::isfinite(preds[i])) {
486 ATH_MSG_WARNING(
"Non-finite prediction detected at " << i <<
" -> set to -100.");
492 for (
auto& v : outputs) {
493 graphData.
graph->dataTensor.emplace_back(std::move(v));
495 return StatusCode::SUCCESS;
499 std::vector<Ort::Value> outputs =
500 model().Run(run_options,
502 graphData.
graph->dataTensor.data(),
507 if (outputs.empty()) {
509 return StatusCode::FAILURE;
512 float* outData = outputs[0].GetTensorMutableData<
float>();
513 const size_t outSize = outputs[0].GetTensorTypeAndShapeInfo().GetElementCount();
517 std::span<float> preds(outData, outData + outSize);
518 for (
size_t i = 0; i < outSize; ++i) {
519 if (!std::isfinite(preds[i])) {
520 ATH_MSG_WARNING(
"Non-finite prediction detected at " << i <<
" -> set to -100.");
526 for (
auto& v : outputs) {
527 graphData.
graph->dataTensor.emplace_back(std::move(v));
529 return StatusCode::SUCCESS;