|
28 | 28 | #include "TROOT.h" // IsImplicitMTEnabled, GetThreadPoolSize
|
29 | 29 | #include "TTree.h"
|
30 | 30 |
|
| 31 | +#include <fstream> |
| 32 | +#include <nlohmann/json.hpp> // nlohmann::json::parse |
31 | 33 | #include <stdexcept>
|
32 | 34 | #include <string>
|
33 | 35 | #include <cstring>
|
@@ -460,6 +462,84 @@ auto RStringCache::Insert(const std::string &string) -> decltype(fStrings)::cons
|
460 | 462 |
|
461 | 463 | return fStrings.insert(string).first;
|
462 | 464 | }
|
| 465 | + |
| 466 | +ROOT::RDF::Experimental::RDatasetSpec RetrieveSpecFromJson(const std::string &jsonFile) |
| 467 | +{ |
| 468 | + const nlohmann::ordered_json fullData = nlohmann::ordered_json::parse(std::ifstream(jsonFile)); |
| 469 | + if (!fullData.contains("samples") || fullData["samples"].empty()) { |
| 470 | + throw std::runtime_error( |
| 471 | + R"(The input specification does not contain any samples. Please provide the samples in the specification like: |
| 472 | +{ |
| 473 | + "samples": { |
| 474 | + "sampleA": { |
| 475 | + "trees": ["tree1", "tree2"], |
| 476 | + "files": ["file1.root", "file2.root"], |
| 477 | + "metadata": {"lumi": 1.0, } |
| 478 | + }, |
| 479 | + "sampleB": { |
| 480 | + "trees": ["tree3", "tree4"], |
| 481 | + "files": ["file3.root", "file4.root"], |
| 482 | + "metadata": {"lumi": 0.5, } |
| 483 | + }, |
| 484 | + ... |
| 485 | + }, |
| 486 | +})"); |
| 487 | + } |
| 488 | + |
| 489 | + ROOT::RDF::Experimental::RDatasetSpec spec; |
| 490 | + for (const auto &keyValue : fullData["samples"].items()) { |
| 491 | + const std::string &sampleName = keyValue.key(); |
| 492 | + const auto &sample = keyValue.value(); |
| 493 | + // TODO: if requested in https://github.com/root-project/root/issues/11624 |
| 494 | + // allow union-like types for trees and files, see: https://github.com/nlohmann/json/discussions/3815 |
| 495 | + if (!sample.contains("trees")) { |
| 496 | + throw std::runtime_error("A list of tree names must be provided for sample " + sampleName + "."); |
| 497 | + } |
| 498 | + std::vector<std::string> trees = sample["trees"]; |
| 499 | + if (!sample.contains("files")) { |
| 500 | + throw std::runtime_error("A list of files must be provided for sample " + sampleName + "."); |
| 501 | + } |
| 502 | + std::vector<std::string> files = sample["files"]; |
| 503 | + if (!sample.contains("metadata")) { |
| 504 | + spec.AddSample( ROOT::RDF::Experimental::RSample{sampleName, trees, files}); |
| 505 | + } else { |
| 506 | + ROOT::RDF::Experimental::RMetaData m; |
| 507 | + for (const auto &metadata : sample["metadata"].items()) { |
| 508 | + const auto &val = metadata.value(); |
| 509 | + if (val.is_string()) |
| 510 | + m.Add(metadata.key(), val.get<std::string>()); |
| 511 | + else if (val.is_number_integer()) |
| 512 | + m.Add(metadata.key(), val.get<int>()); |
| 513 | + else if (val.is_number_float()) |
| 514 | + m.Add(metadata.key(), val.get<double>()); |
| 515 | + else |
| 516 | + throw std::logic_error("The metadata keys can only be of type [string|int|double]."); |
| 517 | + } |
| 518 | + spec.AddSample( ROOT::RDF::Experimental::RSample{sampleName, trees, files, m}); |
| 519 | + } |
| 520 | + } |
| 521 | + if (fullData.contains("friends")) { |
| 522 | + for (const auto &friends : fullData["friends"].items()) { |
| 523 | + std::string alias = friends.key(); |
| 524 | + std::vector<std::string> trees = friends.value()["trees"]; |
| 525 | + std::vector<std::string> files = friends.value()["files"]; |
| 526 | + if (files.size() != trees.size() && trees.size() > 1) |
| 527 | + throw std::runtime_error("Mismatch between trees and files in a friend."); |
| 528 | + spec.WithGlobalFriends(trees, files, alias); |
| 529 | + } |
| 530 | + } |
| 531 | + |
| 532 | + if (fullData.contains("range")) { |
| 533 | + std::vector<int> range = fullData["range"]; |
| 534 | + |
| 535 | + if (range.size() == 1) |
| 536 | + spec.WithGlobalRange({range[0]}); |
| 537 | + else if (range.size() == 2) |
| 538 | + spec.WithGlobalRange({range[0], range[1]}); |
| 539 | + } |
| 540 | + return spec; |
| 541 | +}; |
| 542 | + |
463 | 543 | } // end NS RDF
|
464 | 544 | } // end NS Internal
|
465 | 545 | } // end NS ROOT
|
|
0 commit comments