10 #include <TVirtualPad.h>
16 #include <TBufferJSON.h>
18 #include <TPaveText.h>
21 #include "NBinningDef.h"
22 #include "NDimensionalExecutor.h"
25 #include "NParameters.h"
27 #include "NWsClient.h"
29 #include "NGnNavigator.h"
37 : TNamed(name, title), fObjectTypes(objectTypes)
44 static bool sThStackWarmedUp =
false;
45 if (!sThStackWarmedUp) {
46 THStack _warmup(
"_ndmspc_warmup_stack",
"");
48 sThStackWarmedUp =
true;
65 for (TObject * obj : vec) {
72 std::map<
int, std::vector<int>> ranges, std::map<
int, std::vector<int>> rangesBase)
79 NLogError(
"NGnNavigator::Reshape: Binning definition is null !!!");
82 std::vector<int> axes;
88 NLogError(
"NGnNavigator::Reshape: Binning definition has no variable axes !!!");
92 NLogError(
"NGnNavigator::Reshape: Binning definition has more than 3 variable axes (%zu) !!!", nVarAxes);
96 NLogTrace(
"========== NGnNavigator::Reshape: Levels are empty, using all variable axes...");
98 for (
size_t i = 0; i < nVarAxes; i++) {
99 levels[0].push_back(i);
102 for (
size_t i = 0; i < nVarAxes / 2; i++) {
103 std::swap(levels[0][i], levels[0][nVarAxes - i - 1]);
107 for (
auto & l : levels) {
110 if (std::find(axes.begin(), axes.end(), a) == axes.end()) {
115 NLogTrace(
"============= NGnNavigator::Reshape: Number of axes in levels = %s",
117 std::vector<int> axesSorted = axes;
118 std::sort(axesSorted.begin(), axesSorted.end());
120 std::sort(axesVariavble.begin(), axesVariavble.end());
122 NLogTrace(
"NGnNavigator::Reshape: Axes in levels before removing duplicates: %s",
126 for (
size_t i = 1; i < axesSorted.size(); i++) {
127 if (axesSorted[i] == axesSorted[i - 1]) {
128 axesSorted.erase(axesSorted.begin() + i);
133 if (axesSorted != axesVariavble) {
134 NLogError(
"NGnNavigator::Reshape: Axes in levels '%s' do not match variable axes in binning definition '%s' !!!",
144 NLogError(
"NGnNavigator::Reshape: Number of axes in levels (%d) does not match number of axes in binning "
145 "definition (%d) !!! Available axes indices: %s",
152 NLogInfo(
"NGnNavigator::Reshape: Reshaping navigator for level %d/%zu with binning '%s' ...", level, levels.size(),
153 binningName.c_str());
154 return Reshape(binningDef, levels, level, ranges, rangesBase);
157 std::map<
int, std::vector<int>> ranges, std::map<
int, std::vector<int>> rangesBase,
164 NLogTrace(
"NGnNavigator::Reshape: Reshaping navigator for level=%d levels=%zu", level, levels.size());
165 TH1::AddDirectory(kFALSE);
171 int outputPointStatus = 0;
181 if (current ==
nullptr) {
182 NLogDebug(
"NGnNavigator::Reshape: Creating root navigator %d/%zu...", level, levels.size());
183 current =
new NGnNavigator(TString::Format(
"%s_L%zu", GetName(), level).Data(),
184 TString::Format(
"%s_L%zu", GetTitle(), level).Data());
194 if (level < levels.size()) {
201 std::vector<int> minsBin;
202 std::vector<int> maxsBin;
203 for (
auto & idx : levels[level]) {
204 NLogTrace(
"NGnNavigator::Reshape: [B%d] Axis %d: %s", level, idx,
205 binningDef->
GetContent()->GetAxis(idx)->GetName());
209 minsBin.push_back(1);
210 maxsBin.push_back(binningDef->
GetContent()->GetAxis(idx)->GetNbins());
211 NLogTrace(
"NGnNavigator::Reshape: [B%d] Axis %d: %s bins=[%d,%d]", level, idx,
212 binningDef->
GetContent()->GetAxis(idx)->GetName(), minsBin.back(), maxsBin.back());
216 auto loop_task_bin = [
this, current, binningDef, levels, level, ranges,
217 rangesBase](
const std::vector<int> & coords) {
218 NLogTrace(
"NGnNavigator::Reshape: [B%d] Processing coordinates: coords=%s levels=%s", level,
220 NLogTrace(
"NGnNavigator::Reshape: [L%d] Generating %zuD histogram %s with ranges: %s", level,
223 std::vector<int> axesIds = levels[level];
226 Int_t nDims = axesIds.size();
227 auto dims = std::make_unique<Int_t[]>(nDims);
229 for (
int i = 0; i < nDims; i++) {
230 dims[i] = axesIds[i];
232 THnSparse * hnsIn = binningDef->GetContent();
244 std::string name =
"";
245 std::string title =
"";
246 for (
auto & axisId : axesIds) {
247 TAxis * a = hnsIn->GetAxis(axisId);
248 title += std::string(a->GetName()) +
" vs ";
249 name += TString::Format(
"%s-", a->GetName()).Data();
251 name = name.substr(0, name.size() - 1);
252 if (name.empty()) name =
"hns_proj";
253 title = title.substr(0, title.size() - 4);
254 if (ranges.size() > 0) title +=
" for ranges: ";
255 for (
const auto & [axisId, range] : rangesBase) {
257 TAxis * a = hnsIn->GetAxis(axisId);
258 if (a->IsAlphanumeric()) {
259 title += TString::Format(
"%s[%s]", a->GetName(), a->GetBinLabel(range[0]));
263 TString::Format(
"%s[%.2f,%.2f]", a->GetName(), a->GetBinLowEdge(range[0]), a->GetBinUpEdge(range[1]));
279 int indexInProj = -1;
280 TH1 * hProj =
nullptr;
283 hProj = hnsIn->Projection(axesIds[0]);
284 hProj->SetDirectory(
nullptr);
286 TAxis * axisIn0 = hnsIn->GetAxis(axesIds[0]);
287 TAxis * axisProjX = hProj->GetXaxis();
288 axisProjX->SetName(axisIn0->GetName());
290 if (axisIn0->IsAlphanumeric()) {
291 for (
int b = 1; b <= hProj->GetNbinsX(); b++) {
292 axisProjX->SetBinLabel(b, axisIn0->GetBinLabel(b));
295 indexInProj = hProj->FindFixBin(axisProjX->GetBinCenter(coords[0]));
297 else if (nDims == 2) {
299 hProj = hnsIn->Projection(axesIds[1], axesIds[0]);
300 hProj->SetDirectory(
nullptr);
301 TAxis * axisIn1 = hnsIn->GetAxis(axesIds[0]);
302 TAxis * axisIn0 = hnsIn->GetAxis(axesIds[1]);
303 TAxis * axisProjX = hProj->GetXaxis();
304 TAxis * axisProjY = hProj->GetYaxis();
305 axisProjX->SetName(axisIn1->GetName());
306 axisProjY->SetName(axisIn0->GetName());
308 if (axisIn1->IsAlphanumeric()) {
309 for (
int b = 1; b <= hProj->GetNbinsX(); b++) {
310 axisProjX->SetBinLabel(b, axisIn1->GetBinLabel(b));
314 if (axisIn0->IsAlphanumeric()) {
315 for (
int b = 1; b <= hProj->GetNbinsY(); b++) {
316 axisProjY->SetBinLabel(b, axisIn0->GetBinLabel(b));
319 indexInProj = hProj->FindFixBin(axisProjX->GetBinCenter(coords[0]), axisProjY->GetBinCenter(coords[1]));
321 else if (nDims == 3) {
322 hProj = hnsIn->Projection(axesIds[0], axesIds[1], axesIds[2]);
323 hProj->SetDirectory(
nullptr);
324 TAxis * axisIn0 = hnsIn->GetAxis(axesIds[0]);
325 TAxis * axisIn1 = hnsIn->GetAxis(axesIds[1]);
326 TAxis * axisIn2 = hnsIn->GetAxis(axesIds[2]);
327 TAxis * axisProjX = hProj->GetXaxis();
328 TAxis * axisProjY = hProj->GetYaxis();
329 TAxis * axisProjZ = hProj->GetZaxis();
330 axisProjX->SetName(axisIn0->GetName());
331 axisProjY->SetName(axisIn1->GetName());
332 axisProjZ->SetName(axisIn2->GetName());
334 if (axisIn0->IsAlphanumeric()) {
335 for (
int b = 1; b <= hProj->GetNbinsX(); b++) {
336 axisProjX->SetBinLabel(b, axisIn0->GetBinLabel(b));
340 if (axisIn1->IsAlphanumeric()) {
341 for (
int b = 1; b <= hProj->GetNbinsY(); b++) {
342 axisProjY->SetBinLabel(b, axisIn1->GetBinLabel(b));
345 if (axisIn2->IsAlphanumeric()) {
346 for (
int b = 1; b <= hProj->GetNbinsZ(); b++) {
347 axisProjZ->SetBinLabel(b, axisIn2->GetBinLabel(b));
350 indexInProj = hProj->FindFixBin(axisProjX->GetBinCenter(coords[0]), axisProjY->GetBinCenter(coords[1]),
351 axisProjZ->GetBinCenter(coords[2]));
354 NLogError(
"NGnNavigator::Reshape: Cannot project THnSparse with %d dimensions", nDims);
358 NLogError(
"NGnNavigator::Reshape: Projection failed for level %d !!!", level);
362 hProj->SetName(name.c_str());
363 hProj->SetTitle(title.c_str());
366 int dim = hProj->GetDimension();
368 for (
int x = 1; x <= hProj->GetNbinsX(); ++x) {
369 content = hProj->GetBinContent(x);
371 hProj->SetBinContent(x, content + 1.0);
376 for (
int x = 1; x <= hProj->GetNbinsX(); ++x) {
377 for (
int y = 1; y <= hProj->GetNbinsY(); ++y) {
378 content = hProj->GetBinContent(x, y);
380 hProj->SetBinContent(x, y, content + 1.0);
386 for (
int x = 1; x <= hProj->GetNbinsX(); ++x) {
387 for (
int y = 1; y <= hProj->GetNbinsY(); ++y) {
388 for (
int z = 1; z <= hProj->GetNbinsZ(); ++z) {
389 content = hProj->GetBinContent(x, y, z);
391 hProj->SetBinContent(x, y, z, content + 1.0);
401 Int_t nd = hnsIn->GetNdimensions();
402 Int_t * firstCoord =
new Int_t[nd];
404 content = hnsIn->GetBinContent(0, firstCoord);
409 int bx = firstCoord[axesIds[0]];
410 if (content < 0.5 && bx >= 1 && bx <= hProj->GetNbinsX())
411 hProj->SetBinContent(bx, hProj->GetBinContent(bx) + 1.0);
413 else if (nDims == 2) {
414 int bx = firstCoord[axesIds[0]];
415 int by = firstCoord[axesIds[1]];
416 if (content < 0.5 && bx >= 1 && bx <= hProj->GetNbinsX() && by >= 1 && by <= hProj->GetNbinsY())
417 hProj->SetBinContent(bx, by, hProj->GetBinContent(bx, by) + 1.0);
419 else if (nDims == 3) {
420 int bx = firstCoord[axesIds[0]];
421 int by = firstCoord[axesIds[1]];
422 int bz = firstCoord[axesIds[2]];
423 if (content < 0.5 && bx >= 1 && bx <= hProj->GetNbinsX() && by >= 1 && by <= hProj->GetNbinsY() &&
424 bz >= 1 && bz <= hProj->GetNbinsZ())
425 hProj->SetBinContent(bx, by, bz, hProj->GetBinContent(bx, by, bz) + 1.0);
431 NLogTrace(
"NGnNavigator::Reshape: [L%d] Projection histogram '%s' for coords=%s index=%d", level,
455 std::map<int, std::vector<int>> rangesTmp = ranges;
456 std::map<int, std::vector<int>> rangesBaseTmp = rangesBase;
457 for (
auto & kv : rangesBaseTmp) {
458 std::vector<int> range = rangesTmp[kv.first];
459 NLogTrace(
"NGnNavigator::Reshape: [L%d] Axis %d[%s]: rangeBase=%s range=%s", level, kv.first,
463 int minBase = 0, maxBase = 0;
465 for (
auto & c : coords) {
469 NLogTrace(
"NGnNavigator::Reshape: Axis %d: minBase=%d maxBase=%d", axesIds[i], minBase, maxBase);
470 rangesTmp[axesIds[i]] = {c, c};
471 rangesBaseTmp[axesIds[i]] = {minBase, maxBase};
475 if (hProj ==
nullptr) {
476 NLogError(
"NGnNavigator::Reshape: Projection histogram is null for level %d !!!", level);
480 size_t nCells = hProj->GetNcells();
484 if (currentChild ==
nullptr) {
485 NLogTrace(
"NGnNavigator::Reshape: [L%d] Creating new child for index %d nCells=%d ...", level, indexInProj,
487 std::string childName = TString::Format(
"%s_L%zu_C%d", GetName(), level + 1, indexInProj).Data();
488 currentChild =
new NGnNavigator(childName.c_str(), childName.c_str());
503 NLogError(
"NGnNavigator::Reshape: [L%d] Using existing child for index %d [NOT OK] ...", level, indexInProj);
509 if (level == levels.size() - 1) {
510 NLogTrace(
"NGnNavigator::Reshape: [L%d] Filling projections from all branches %s for ranges:", level,
512 for (
auto & kv : rangesBaseTmp) {
513 std::vector<int> range = rangesTmp[kv.first];
514 NLogTrace(
"NGnNavigator::Reshape: [L%d] Axis %d ['%s']: rangeBase=%s range=%s", level, kv.first,
526 std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{hnsIn->CreateIter(
true )};
527 std::vector<int> linBins;
531 while ((linBin = iter->Next()) >= 0) {
532 NLogTrace(
"NGnNavigator::Reshape: [L%d] Found bin %lld [%lld]", level, linBin, binningDef->GetId(linBin));
533 linBins.push_back(binningDef->GetId(linBin));
535 if (linBins.empty()) {
536 NLogTrace(
"NGnNavigator::Reshape: [L%d] No bins found for the given ranges, skipping ...", level);
541 NLogTrace(
"NGnNavigator::Reshape: Branch object Point coordinates: %s",
545 for (
int lb : linBins) {
548 if (val.GetBranchStatus() == 0) {
549 NLogTrace(
"NGnNavigator::Reshape: [L%d] Branch '%s' is disabled, skipping ...", level, key.c_str());
552 NLogTrace(
"NGnNavigator::Reshape: [L%d] Processing branch '%s' with %zu objects to loop ...", level,
553 key.c_str(), linBins.size());
565 TString className = val.GetObjectClassName();
566 if (className.BeginsWith(
"THnSparse")) {
614 else if (className.BeginsWith(
"TList")) {
615 NLogTrace(
"[L%d] Branch '%s' is a TList, getting object at index %d ...", level, key.c_str(),
617 TList * list =
dynamic_cast<TList *
>(val.GetObject());
620 std::vector<std::string> objNames;
621 for (
int i = 0; i < list->GetEntries(); i++) {
622 TObject * o = list->At(i);
623 objNames.push_back(o->GetName());
628 NLogTrace(
"[L%d] Branch '%s' TList contains %d objects: %s", level, key.c_str(), list->GetEntries(),
635 for (
auto & name : objNames) {
636 TH1 * hProjTmp =
dynamic_cast<TH1 *
>(list->FindObject(name.c_str()));
637 if (hProjTmp ==
nullptr) {
638 NLogTrace(
"NGnNavigator::Reshape::Warning Branch '%s' TList does not contain '%s' as TH1 !!!",
639 key.c_str(), name.c_str());
644 if (TMath::IsNaN(hProjTmp->GetEntries()) || TMath::IsNaN(hProjTmp->GetSumOfWeights())) {
645 NLogWarning(
"NGnNavigator::Reshape: Branch '%s' '%s' histogram is nan !!!", key.c_str(),
652 "[L%d] Histogram name='%s' title='%s' for branch '%s' storing with indexInProj=%d, entries=%.0f",
653 level, name.c_str(), hProjTmp->GetTitle(), key.c_str(), indexInProj, hProjTmp->GetEntries());
665 TH1 * hClone = (TH1 *)hProjTmp->Clone();
666 hClone->SetDirectory(
nullptr);
667 current->
SetObject(name, hClone, indexInProj);
669 if (isValid ==
false) {
670 NLogTrace(
"NGnNavigator::Reshape::Warning: Branch '%s' TList does not contain any valid histograms !!!",
675 else if (className.BeginsWith(
"Ndmspc::NParameters")) {
679 TH1 * hParams = parameters->
GetHisto();
682 NLogTrace(
"[L%d] Branch '%s' Point contains '_params' histogram with %.0f entries ...", level,
683 key.c_str(), hParams->GetEntries());
685 for (
int b = 1; b <= hParams->GetNbinsX(); b++) {
687 std::string binLabel = hParams->GetXaxis()->GetBinLabel(b);
688 double binValue = hParams->GetBinContent(b);
689 double binError = hParams->GetBinError(b);
690 NLogTrace(
"[L%d] Bin %d[%s] = %e indexInProj=%d", level, b, binLabel.c_str(), binValue,
704 NLogTrace(
"[L%d] Stored parameter '%s' = %e +/- %e at indexInProj=%d", level, binLabel.c_str(),
705 binValue, binError, indexInProj);
710 NLogWarning(
"NGnNavigator::Reshape: Branch '%s' Point parameters object is null !!!", key.c_str());
714 NLogWarning(
"NGnNavigator::Reshape: Branch '%s' has unsupported class '%s' !!! Skipping ...", key.c_str(),
724 current->
SetChild(currentChild, indexInProj);
726 Reshape(binningDef, levels, level + 1, rangesTmp, rangesBaseTmp, currentChild);
728 executorBin.
Execute(loop_task_bin);
731 NLogTrace(
"NGnNavigator::Reshape: Reached the end of levels, level=%d", level);
732 std::vector<std::vector<int>> rangesEmpty;
738 NLogTrace(
"NGnNavigator::Reshape: =========== Reshaping navigator for level %d DONE ================", level);
741 NLogInfo(
"NGnNavigator::Reshape: Reshaping navigator DONE.");
743 for (
size_t l = 0; l < levels.size(); l++) {
744 std::string axesStr =
"";
745 for (
auto & a : levels[l]) {
746 TAxis * axis = binningDef->
GetContent()->GetAxis(a);
747 axesStr += TString::Format(
"%d('%s') ", a, axis->GetName()).Data();
749 NLogInfo(
" Level %zu axes: %s", l, axesStr.c_str());
760 void NGnNavigator::Export(
const std::string & filename, std::vector<std::string> objectNames,
const std::string & wsUrl,
766 NLogInfo(
"Exporting NGnNavigator to file: %s", filename.c_str());
771 if (filename.size() > 5 && filename.substr(filename.size() - 5) ==
".root") {
772 NLogInfo(
"Exporting NGnNavigator to ROOT file: %s", filename.c_str());
773 TFile * file = TFile::Open(filename.c_str(),
"RECREATE");
774 if (!file || file->IsZombie()) {
775 NLogError(
"Failed to open file: %s", filename.c_str());
783 else if (filename.size() > 5 && filename.substr(filename.size() - 5) ==
".json") {
784 NLogInfo(
"Exporting NGnNavigator to JSON file: %s", filename.c_str());
790 NLogError(
"Failed to save JSON file: %s", filename.c_str());
793 NLogInfo(
"Exported NGnNavigator to file: %s", filename.c_str());
795 else if (filename.empty()) {
796 NLogInfo(
"No filename provided, export to JSON only ...");
799 std::cout << objJson.dump() << std::endl;
802 NLogError(
"Unsupported file format for export: %s", filename.c_str());
805 if (!wsUrl.empty()) {
806 NLogInfo(
"Uploading exported file to web socket: %s", wsUrl.c_str());
809 std::string message = objJson.dump();
811 if (!message.empty()) {
812 NLogInfo(
"Connecting to web socket: %s", wsUrl.c_str());
814 NLogError(
"Failed to connect to '%s' !!!", wsUrl.c_str());
818 if (!client.
Send(objJson.dump())) {
819 NLogError(
"Failed to send message `%s`", message.c_str());
822 NLogInfo(
"Successfully sent message to '%s'", wsUrl.c_str());
826 NLogInfo(
"Waiting %d ms before disconnecting ...", timeoutMs);
827 gSystem->Sleep(timeoutMs);
829 NLogInfo(
"Disconnecting from '%s' ...", wsUrl.c_str());
833 NLogInfo(
"Sent: %s", message.c_str());
843 if (obj ==
nullptr) {
844 NLogError(
"NGnNavigator::ExportJson: Object is nullptr !!!");
854 NLogError(
"NGnNavigator::ExportJson: Projection is nullptr !!!");
865 TString hJsonStr = TBufferJSON::ConvertToJSON(h);
866 j = json::parse(hJsonStr.Data());
868 double entries = 0.0;
870 if (objectNames.empty()) {
873 bool isValid =
false;
876 for (
size_t i = 0; i < val.size(); i++) {
877 TObject * objContent = val[i];
881 std::string className = objContent ? objContent->ClassName() :
"";
882 if (className.empty()) {
883 NLogWarning(
"NGnNavigator::ExportJson: Object %s has empty class name", key.c_str());
887 className = className.substr(0, 3);
899 if (isValid) objectNames.push_back(key);
903 NLogDebug(
"NGnNavigator::ExportJson: Exporting selected objects: %s",
NUtils::GetCoordsString(objectNames).c_str());
907 for (
const auto & name : objectNames) {
908 NLogTrace(
"NGnNavigator::ExportJson: Included object name: '%s'", name.c_str());
913 NLogTrace(
"NGnNavigator::ExportJson: Processing object '%s' with %zu entries ...", key.c_str(), val.size());
915 if (std::find(objectNames.begin(), objectNames.end(), key) == objectNames.end()) {
916 NLogDebug(
"NGnNavigator::ExportJson: Skipping object '%s' ...", key.c_str());
920 double min = std::numeric_limits<double>::max();
921 double max = -std::numeric_limits<double>::max();
924 for (
size_t i = 0; i < val.size(); i++) {
925 TObject * objContent = val[i];
929 TH1 * hist =
dynamic_cast<TH1 *
>(objContent);
932 TString histJsonStr = TBufferJSON::ConvertToJSON(hist);
933 json objJson = json::parse(histJsonStr.Data());
934 double objMin, objMax;
936 min = TMath::Min(min, objMin);
937 max = TMath::Max(max, objMax);
938 entries = hist->GetEntries();
939 j[
"fArray"][i] = entries;
941 j[
"children"][key].push_back(objJson);
944 j[
"children"][key].push_back(
nullptr);
948 NLogWarning(
"NGnNavigator::ExportJson: Object %s at index %zu is not a TH1, skipping.", key.c_str(), i);
950 j[
"children"][key].push_back(
nullptr);
955 j[
"children"][key].push_back(
nullptr);
961 double min = std::numeric_limits<double>::max();
962 double max = -std::numeric_limits<double>::max();
965 for (
size_t i = 0; i < val.size(); i++) {
966 double param = val[i];
967 double paramError = 0.0;
969 if (i < val.size()) {
974 NLogWarning(
"NGnNavigator::ExportJson: Exception in GetParameterError for key %s index %zu", key.c_str(), i);
978 if (!std::isnan(param) && std::fabs(param) > 1e-12) {
979 min = TMath::Min(min, param);
980 max = TMath::Max(max, param);
981 j[
"fArrays"][key][
"values"][i] = param;
982 j[
"fArrays"][key][
"errors"][i] = TMath::Power(paramError, 2);
985 j[
"fArrays"][key][
"values"][i] = 0.0;
986 j[
"fArrays"][key][
"errors"][i] = 0.0;
990 if (key.compare(
"mass") == 0) {
998 double margin = 0.05 * (max - min);
1001 j[
"fArrays"][key][
"min"] = min;
1002 j[
"fArrays"][key][
"max"] = max;
1008 double min = std::numeric_limits<double>::max();
1009 double max = -std::numeric_limits<double>::max();
1010 std::vector<double> tmpContent;
1012 std::map<std::string, double> paramMinGlobal;
1013 std::map<std::string, double> paramMaxGlobal;
1014 bool firstChild =
true;
1017 if (child !=
nullptr) {
1022 NLogWarning(
"NGnNavigator::ExportJson: Exception in recursive ExportToJson for child.");
1026 if (childJson.contains(
"fArrays")) {
1027 for (
auto & [param, arr] : childJson[
"fArrays"].items()) {
1028 if (arr.contains(
"min") && arr.contains(
"max")) {
1029 double cmin = arr[
"min"].get<
double>();
1030 double cmax = arr[
"max"].get<
double>();
1031 if (firstChild || paramMinGlobal.find(param) == paramMinGlobal.end()) {
1032 paramMinGlobal[param] = cmin;
1033 paramMaxGlobal[param] = cmax;
1036 paramMinGlobal[param] = std::min(paramMinGlobal[param], cmin);
1037 paramMaxGlobal[param] = std::max(paramMaxGlobal[param], cmax);
1044 j[
"children"][
"content"].push_back(childJson);
1048 if (!paramMinGlobal.empty()) {
1049 for (
const auto & [param, minVal] : paramMinGlobal) {
1050 j[
"fArrays"][param][
"min"] = minVal;
1051 j[
"fArrays"][param][
"max"] = paramMaxGlobal[param];
1055 bool hasContent =
false;
1056 for (
auto & c : j[
"children"][
"content"]) {
1064 j[
"children"].erase(
"content");
1072 j[
"ndmspc"][
"content"][
"fMinimum"] = min;
1073 j[
"ndmspc"][
"content"][
"fMaximum"] = max;
1079 for (
const auto & child : j[
"children"][
"content"]) {
1081 if (child ==
nullptr || child.is_null()) {
1087 if (child.contains(
"ndmspc")) {
1090 double max = -std::numeric_limits<double>::max();
1092 for (
auto & [key, value] : child[
"ndmspc"].items()) {
1093 if (value.is_object()) {
1096 max = TMath::Max(max, value[
"fMaximum"].get<double>());
1099 j[
"fArray"][i] = max;
1105 if (j[
"children"][
"content"].is_null()) j[
"children"].erase(
"content");
1114 TString opt = option;
1119 NLogInfo(
"NGnNavigator: name='%s' title='%s' level=%d levels=%d projection='%s' title='%s'", GetName(), GetTitle(),
1124 NLogInfo(
"NGnNavigator: name='%s' title='%s' level=%d levels=%d projection=nullptr", GetName(), GetTitle(),
fLevel,
1128 NLogInfo(
"NGnNavigator: This is the root navigator.");
1131 for (
size_t l = 0; l <
fLevels.size(); l++) {
1132 std::string axesStr =
"";
1134 TAxis * axis = binningDef->
GetContent()->GetAxis(a);
1135 axesStr += TString::Format(
"%d('%s') ", a, axis->GetName()).Data();
1137 NLogInfo(
" Level %zu axes: %s", l, axesStr.c_str());
1146 std::vector<int> childIndices;
1147 for (
size_t i = 0; i <
fChildren.size(); i++) {
1150 childIndices.push_back(i);
1155 NLogTrace(
"NGnNavigator: %zu children with indices: %s", childIndices.size(),
1157 for (
size_t i = 0; i <
fChildren.size(); i++) {
1159 if (child && child->
GetChildren().empty() ==
false) {
1160 child->
Print(option);
1171 j[
"name"] = GetName();
1172 j[
"title"] = GetTitle();
1192 for (
size_t level = 0; level <
fNLevels; level++) {
1193 NLogDebug(
"NGnNavigator::Draw: Level %d/%d", level + 1,
fNLevels);
1195 NLogWarning(
"NGnNavigator::Draw: Level %d has projection with dimension %d > 2, which is not supported for "
1208 TString opt = option;
1210 if (opt.Contains(
"HOVER")) {
1213 if (opt.Contains(
"CLICK")) {
1218 if (gPad) SafeDelete(gPad);
1221 gROOT->MakeDefCanvas();
1225 Int_t cx = TMath::Ceil(
fNLevels / (Double_t)cy);
1226 gPad->Divide(cy, cx);
1229 TVirtualPad * originalPad = gPad;
1232 NLogDebug(
"NGnNavigator::Draw: Drawing level %d", level);
1233 TVirtualPad * pad = originalPad->cd(level + 1);
1235 NLogDebug(
"NGnNavigator::Draw: Clearing pad %d", level + 1);
1240 NLogDebug(
"NGnNavigator::Draw: Using current object at level %d: %s", level, obj->GetName());
1245 for (
size_t i = 0; i < obj->
GetChildren().size(); i++) {
1248 NLogDebug(
"NGnNavigator::Draw: Found child at level %d: %s", level, child->
GetProjection()->GetTitle());
1253 NLogDebug(
"NGnNavigator::Draw: Using child object at level %d: %s", level, obj ? obj->GetName() :
"nullptr");
1255 if (obj ==
nullptr) {
1256 NLogError(
"NGnNavigator::Draw: Child object at level %d is nullptr !!!", level);
1261 NLogDebug(
"NGnNavigator::Draw: Drawing projection at level %d: %s", level, projection->GetTitle());
1262 projection->SetMinimum(0);
1263 projection->SetStats(kFALSE);
1267 obj->AppendPad(option);
1270 NLogError(
"NGnNavigator::Draw: Projection at level %d is nullptr !!!", level);
1274 NLogError(
"NGnNavigator::Draw: Pad %d is nullptr !!!", level + 1);
1285 NLogInfo(
"NGnNavigator::Paint: Painting object ...");
1287 NLogDebug(
"NGnNavigator::Paint: Painting to pad=%d projection name=%s title=%s ...",
fLevel + 1,
1322 Double_t x_pad = gPad->AbsPixeltoX(px);
1323 Double_t y_pad = gPad->AbsPixeltoY(py);
1326 Double_t x_user = gPad->PadtoX(x_pad);
1327 Double_t y_user = gPad->PadtoY(y_pad);
1329 size_t bin =
fProjection->FindBin(x_user, y_user);
1331 TVirtualPad * originalPad = gPad;
1334 bool isActionTriggered = (
event ==
fTrigger);
1337 isActionTriggered = isActionTriggered && (isBinChanged ||
event == kButton1Down);
1339 if (isActionTriggered) {
1340 Int_t binx, biny, binz;
1342 Double_t content =
fProjection->GetBinContent(bin);
1343 NLogDebug(
"NGnNavigator::ExecuteEvent: [%s] Mouse trigger on bin=[%d, %d] at px=[%f, %f] with content: %f "
1344 "level=%d nLevels=%d",
1345 gPad->GetName(), binx, biny, x_user, y_user, content,
fLevel,
fNLevels);
1351 if (nDimensions == 1) {
1355 NLogTrace(
"NGnNavigator::ExecuteEvent: Index in histogram: %d level=%d", index,
fLevel);
1357 TCanvas * cObject = (TCanvas *)gROOT->GetListOfCanvases()->FindObject(
"cObject");
1359 NLogTrace(
"NGnNavigator::ExecuteEvent: [%s]Child object '%p' found at index %d", gPad->GetName(),
1362 gPad = originalPad->GetMother();
1363 TVirtualPad * pad = gPad->cd(
fLevel + 1 + 1);
1368 hProj->SetStats(kFALSE);
1369 hProj->SetMinimum(0);
1370 hProj->Draw(
"text colz");
1380 latex.SetTextAlign(22);
1381 latex.SetTextSize(0.05);
1382 latex.DrawLatex(0.5, 0.5,
"Select bottom pad to see projection");
1390 NLogTrace(
"NGnNavigator::ExecuteEvent: No child object found at index %d", index);
1392 TH1 * hProj = (TH1 *)
GetObject(objName, index);
1393 if (hProj ==
nullptr) {
1394 NLogError(
"NGnNavigator::ExecuteEvent: No histogram found for index %d", index);
1398 if (cObject ==
nullptr) {
1399 cObject =
new TCanvas(
"cObject",
"cObject", 800, 600);
1404 if (hProj->GetXaxis()->IsAlphanumeric()) {
1405 TPaveText * pt =
new TPaveText(0.15, 0.15, 0.85, 0.85);
1406 for (Int_t binx = 1; binx <= hProj->GetNbinsX(); ++binx) {
1407 std::string name = hProj->GetXaxis()->GetBinLabel(binx);
1408 std::string value = TString::Format(
"%.3f", hProj->GetBinContent(binx)).Data();
1409 std::string t = TString::Format(
"%s: %s", name.c_str(), value.c_str()).Data();
1411 pt->AddText(t.c_str());
1421 gPad->ModifiedUpdate();
1424 if (event == kMouseMotion) {
1428 Int_t binx, biny, binz;
1430 NLogTrace(
"[%s] Mouse hover on bin[%d, %d] at px[%f, %f] level=%d nLevels=%d", gPad->GetName(), binx, biny,
1434 NLogTrace(
"[%s] Setting point for level %d %s", gPad->GetName(),
fLevel,
fProjection->GetTitle());
1445 NLogTrace(
"NGnNavigator::GetChild: index=%d, size=%zu", index,
fChildren.size());
1469 THnSparse * hnsObjContent = binningDef->
GetContent();
1471 std::vector<std::vector<int>> ranges;
1476 NLogDebug(
"NGnNavigator::GetChild: Setting axis ranges for level=%d",
fLevel);
1478 for (
size_t i = 0; i < levels.size(); i++) {
1479 int coords_i = (int)coords[i][
fLevel];
1480 ranges.push_back({levels[i], coords_i, coords_i});
1481 NLogDebug(
"NGnNavigator::GetChild: level=%d axis=%d coord=%d",
fLevel, levels[i], coords_i);
1485 coords[0].resize(3, 0);
1487 size_t bin =
fProjection->GetBin(coords[0][0], coords[0][1], coords[0][2]);
1491 if (!next)
return nullptr;
1545 return it->second[index];
1559 NLogTrace(
"NGnNavigator::SetObject: name=%s, obj=%p, index=%d", name.c_str(), obj, index,
1597 return it->second[index];
1599 return TMath::QuietNaN();
1607 if (!std::isnan(value)) {
1609 NLogTrace(
"NGnNavigator::SetParameter: Resizing parameter content map for '%s' to %d", name.c_str(),
fNCells);
1612 NLogTrace(
"NGnNavigator::SetParameter: name=%s, value=%f, index=%d", name.c_str(), value, index,
1644 return it->second[index];
1646 return TMath::QuietNaN();
1654 if (!std::isnan(value)) {
1657 NLogTrace(
"NGnNavigator::SetParameter: Resizing parameter content map for '%s' to %d", name.c_str(),
fNCells);
1660 NLogTrace(
"NGnNavigator::SetParameter: name=%s, value=%f, index=%d", name.c_str(), value, index,
1677 const std::string & minmaxMode, Option_t * option)
const
1682 std::vector<int> projIds;
1683 return DrawSpectra(parameterName, projIds, minmax, minmaxMode, option);
1687 std::vector<double> minmax,
const std::string & minmaxMode,
1688 Option_t * option)
const
1694 std::vector<int> projIds;
1696 for (
const auto & axisName : projAxes) {
1697 TAxis * axis =
nullptr;
1698 for (
int i = 0; i <
fProjection->GetDimension(); i++) {
1706 if (axis && axis->GetName() == axisName) {
1707 projIds.push_back(i);
1712 if (projIds.empty()) {
1713 NLogError(
"NGnNavigator::DrawSpectra: No projection axes found for names: %s",
1718 if (projIds.size() > 3) {
1719 NLogError(
"NGnNavigator::DrawSpectra: Too many projection dimensions: %zu (max 3)", projIds.size());
1723 if (projIds.size() != projAxes.size()) {
1724 NLogError(
"NGnNavigator::DrawSpectra: Not all projection axes found: %s",
1729 return DrawSpectra(parameterName, projIds, minmax, minmaxMode, option);
1733 const std::string & minmaxMode, Option_t * option)
const
1739 if (parameterName.empty()) {
1740 NLogError(
"NGnNavigator::DrawSpectra: Parameter name is empty");
1746 NLogError(
"NGnNavigator::DrawSpectra: Parameter name '%s' not found in fParameterContentMap",
1747 parameterName.c_str());
1750 Int_t screenWidth = gClient->GetDisplayWidth();
1751 Int_t screenHeight = gClient->GetDisplayHeight();
1754 TCanvas * c =
nullptr;
1756 constexpr
double canvasScale = 0.2;
1757 Int_t canvasWidth =
static_cast<Int_t
>(screenWidth * canvasScale);
1758 Int_t canvasHeight =
static_cast<Int_t
>(screenHeight * canvasScale);
1760 if (canvasWidth < 800) canvasWidth = 800;
1761 if (canvasHeight < 600) canvasHeight = 600;
1763 NLogTrace(
"Screen size: %dx%d", screenWidth, screenHeight);
1766 THnSparse * hnsObjContent = binningDef->
GetContent();
1767 hnsObjContent->Print(
"all");
1768 std::vector<std::vector<int>> projections;
1769 if (projIds.empty()) {
1771 std::iota(projIds.begin(), projIds.end(), 0);
1775 projections.push_back(projIds);
1778 if (projections.empty()) {
1779 NLogError(
"NGnNavigator::DrawSpectra: No projections found");
1782 if (projections[0].size() > 3) {
1783 NLogError(
"NGnNavigator::DrawSpectra: Too many projection dimensions: %zu (max 3)", projections[0].size());
1787 TList * outputList =
new TList();
1788 for (
const auto & proj : projections) {
1793 TH1 * hParameterProjection = (TH1 *)
fProjection->Clone(
"hParameterProjection");
1795 hParameterProjection->SetDirectory(
nullptr);
1799 hParameterProjection->SetContent(
GetParameters(parameterName).data());
1809 THnSparse * hsParam = THnSparse::CreateSparse(parameterName.c_str(), parameterName.c_str(), hParameterProjection);
1812 int nDimensions = hParameterProjection->GetDimension();
1813 for (
int i = 0; i < nDimensions; i++) {
1814 TAxis * axis =
nullptr;
1816 axis = hParameterProjection->GetXaxis();
1818 axis = hParameterProjection->GetYaxis();
1820 axis = hParameterProjection->GetZaxis();
1822 hsParam->GetAxis(i)->SetName(axis->GetName());
1823 hsParam->GetAxis(i)->SetTitle(axis->GetTitle());
1824 if (axis->IsVariableBinSize()) {
1825 hsParam->GetAxis(i)->Set(axis->GetNbins(), axis->GetXbins()->GetArray());
1827 if (axis->IsAlphanumeric()) {
1828 for (
int j = 1; j <= axis->GetNbins(); j++) {
1829 const char * label = axis->GetBinLabel(j);
1830 hsParam->GetAxis(i)->SetBinLabel(j, label);
1835 delete hParameterProjection;
1837 std::vector<int> dims;
1841 for (
auto &
id : proj) {
1842 dims.push_back(currentLevels[
id]);
1845 if (dims.size() > 3) {
1846 NLogError(
"NGnNavigator::DrawSpectra: Too many projection dimensions: %zu (max 3)", dims.size());
1857 std::vector<std::set<int>> dimsResults(3);
1859 std::vector<std::vector<int>> ranges;
1861 Int_t * p =
new Int_t[hsParam->GetNdimensions()];
1862 Long64_t linBin = 0;
1863 std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{hsParam->CreateIter(
true )};
1864 while ((linBin = iter->Next()) >= 0) {
1867 hsParam->GetBinContent(linBin, p);
1877 dimsResults[0].insert(p[proj[0]]);
1878 if (dims.size() > 1) dimsResults[1].insert(p[proj[1]]);
1879 if (dims.size() > 2) dimsResults[2].insert(p[proj[2]]);
1890 if (!gROOT->IsBatch()) {
1901 int nPads = dims.size() > 2 ? dimsResults[2].size() : 1;
1903 std::vector<std::string> projNames;
1905 NLogTrace(
"Projection dims: %d %d %d", dims[0], dims.size() > 1 ? dims[1] : -1, dims.size() > 2 ? dims[2] : -1);
1906 projNames.push_back(hnsObjContent->GetAxis(dims[0])->GetName());
1907 if (dims.size() > 1) projNames.push_back(hnsObjContent->GetAxis(dims[1])->GetName());
1908 if (dims.size() > 2) projNames.push_back(hnsObjContent->GetAxis(dims[2])->GetName());
1914 std::string canvasName = Form(
"c_%s", posfix.c_str());
1915 NLogTrace(
"Creating canvas '%s' with size %dx%d", canvasName.c_str(), canvasWidth, canvasHeight);
1918 TCanvas * existingCanvas = (TCanvas *)gROOT->GetListOfCanvases()->FindObject(canvasName.c_str());
1919 if (existingCanvas) {
1920 NLogTrace(
"Deleting existing canvas '%s'", canvasName.c_str());
1921 delete existingCanvas;
1924 c =
new TCanvas(canvasName.c_str(), canvasName.c_str(), canvasWidth, canvasHeight);
1925 c->SetBit(kMustCleanup, kFALSE);
1929 TList * stackList =
new TList();
1931 for (
int iPad = 0; iPad < nPads; iPad++) {
1934 std::string stackName = Form(
"hStack_%s_%d", posfix.c_str(), iPad);
1935 std::string stackTitle = parameterName +
" : ";
1936 stackTitle += projNames[0];
1937 stackTitle += projNames.size() > 1 ?
" vs " + projNames[1] :
"";
1938 if (proj.size() > 2) {
1942 auto it = std::next(dimsResults[2].begin(), iPad);
1943 if (it != dimsResults[2].end()) {
1952 TAxis * aPad = hsParam->GetAxis(proj[2]);
1953 if (aPad->IsAlphanumeric()) {
1954 stackTitle += projNames.size() > 2 ?
" for " + projNames[2] +
" [" + aPad->GetBinLabel(p[proj[2]]) +
"]" :
"";
1957 double binLowEdge = aPad->GetBinLowEdge(p[proj[2]]);
1958 double binUpEdge = aPad->GetBinUpEdge(p[proj[2]]);
1960 projNames.size() > 2 ?
" for " + projNames[2] +
" " + Form(
" [%.3f,%.3f]", binLowEdge, binUpEdge) :
"";
1963 NLogTrace(
"Creating stack '%s' with title '%s'", stackName.c_str(), stackTitle.c_str());
1971 THStack * hStack =
new THStack(stackName.c_str(), stackTitle.c_str());
1972 hStack->SetBit(kMustCleanup, kFALSE);
1974 int nStacks = proj.size() > 1 ? dimsResults[1].size() : 1;
1975 double stackMin = std::numeric_limits<double>::max();
1976 double stackMax = std::numeric_limits<double>::lowest();
1978 std::string mode = (minmaxMode ==
"VE" || minmaxMode ==
"V" || minmaxMode ==
"D") ? minmaxMode :
"V";
1979 for (
int iStack = 0; iStack < nStacks; iStack++) {
1981 if (proj.size() > 1) {
1982 auto it = std::next(dimsResults[1].begin(), iStack);
1983 if (it != dimsResults[1].end()) {
1989 std::vector<std::vector<int>> rangesTmp;
1990 if (proj.size() > 2) rangesTmp.push_back({proj[2], p[proj[2]], p[proj[2]]});
1991 if (proj.size() > 1) rangesTmp.push_back({proj[1], p[proj[1]], p[proj[1]]});
1994 if (!hProj || hProj->GetEntries() == 0) {
1995 NLogError(
"Failed to project THnSparse for stack %d with projection IDs: %s", iStack,
2000 if (proj.size() > 1) {
2001 TAxis * aStack = hsParam->GetAxis(proj[1]);
2002 if (aStack->IsAlphanumeric()) {
2003 std::string label = aStack->GetBinLabel(p[proj[1]]);
2004 hProj->SetName(Form(
"%s_%s", aStack->GetName(), label.c_str()));
2005 hProj->SetTitle(Form(
"%s [%s]", aStack->GetName(), label.c_str()));
2008 double binLowEdge = aStack->GetBinLowEdge(p[proj[1]]);
2009 double binUpEdge = aStack->GetBinUpEdge(p[proj[1]]);
2010 hProj->SetName(Form(
"%s_%.3f_%.3f", aStack->GetName(), binLowEdge, binUpEdge));
2011 hProj->SetTitle(Form(
"%s [%.3f,%.3f]", aStack->GetName(), binLowEdge, binUpEdge));
2016 for (
int bin = 1; bin <= hProj->GetNbinsX(); ++bin) {
2017 double val = hProj->GetBinContent(bin);
2018 double err = hProj->GetBinError(bin);
2020 if (stackMin > val - err) stackMin = val - err;
2021 if (stackMax < val + err) stackMax = val + err;
2023 else if (mode ==
"V") {
2024 if (stackMin > val) stackMin = val;
2025 if (stackMax < val) stackMax = val;
2029 hProj->SetMarkerStyle(20);
2030 hProj->SetMarkerColor(iStack + 1);
2032 TH1 * hProjClone = (TH1 *)hProj->Clone();
2035 hProjClone->SetDirectory(
nullptr);
2036 hStack->Add(hProjClone);
2042 hStack->SetMinimum(-1111);
2043 hStack->SetMaximum(-1111);
2047 if (minmax.size() > 0) {
2048 if (minmax.size() == 2) {
2049 stackMin = minmax[0];
2050 stackMax = minmax[1];
2052 else if (minmax.size() == 1) {
2054 double percent = minmax[0];
2055 double center = 0.5 * (stackMax + stackMin);
2056 double halfRange = 0.5 * (stackMax - stackMin);
2057 double margin = percent * halfRange;
2058 stackMin = center - (halfRange + margin);
2059 stackMax = center + (halfRange + margin);
2064 if (stackMin == stackMax) {
2065 if (stackMin == 0.0) {
2074 hStack->SetMinimum(stackMin);
2075 hStack->SetMaximum(stackMax);
2078 if (hStack->GetNhists() == 0) {
2079 NLogError(
"No histograms were added to the stack for pad %d with projection IDs: %s", iPad,
2092 stackList->Add(hStack);
2099 if (stackList->GetEntries() > 0) {
2100 nPads = stackList->GetEntries();
2101 c->DivideSquare(nPads);
2102 for (
int iPad = 0; iPad < nPads; iPad++) {
2104 THStack * hStack = (THStack *)stackList->At(iPad);
2106 hStack->Draw(
"nostack E");
2107 NLogTrace(
"Drawing stack with option: %s in pad %d %d",
"nostack E", iPad + 1, hStack->GetNhists());
2108 hStack->GetHistogram()->GetXaxis()->SetTitle(projNames[0].c_str());
2109 hStack->GetHistogram()->GetYaxis()->SetTitle(parameterName.c_str());
2110 if (dims.size() > 1) gPad->BuildLegend(0.75, 0.75, 0.95, 0.95,
"");
2111 c->ModifiedUpdate();
2135 while (current->
GetParent() !=
nullptr) {
Defines binning mapping and content for NDMSPC histograms.
THnSparse * GetContent() const
Get the template content histogram.
std::vector< int > GetVariableAxes() const
Get list of variable axes indices.
NBinningDef * GetDefinition(const std::string &name="")
Get binning definition by name.
Executes a function over all points in an N-dimensional space, optionally in parallel.
void Execute(const std::function< void(const std::vector< int > &coords)> &func)
Execute a function over all coordinates in the N-dimensional space.
Navigator object for managing hierarchical data structures and projections.
void SetLevel(size_t l)
Set current level in hierarchy.
std::vector< TObject * > GetObjects(const std::string &name) const
Get objects by name.
void SetChild(NGnNavigator *child, int index=-1)
Set child navigator at index.
void ResizeParameterContentMap(const std::string &name, int n)
Resize parameter content map for a given name.
std::vector< std::string > GetParameterNames() const
Get parameter names managed by navigator.
void SetObject(const std::string &name, TObject *obj, int index=-1)
Set object by name and index.
void SetLevels(const std::vector< std::vector< int >> &levels)
Set the levels using a vector of vectors of integers.
void SetChildrenSize(size_t n)
Set number of children.
virtual TList * DrawSpectraByName(std::string parameterName, std::vector< std::string > projAxes, std::vector< double > minmax={0.05}, const std::string &minmaxMode="V", Option_t *option="") const
Draws spectra for the given parameter and projection axes.
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Handle execution of events (e.g., mouse, keyboard).
virtual void Print(Option_t *option="") const override
Print navigator information.
NGnNavigator * GetParent() const
Get parent navigator.
double GetParameterError(const std::string &name, int index=0) const
Retrieves a specific error value for a parameter.
void SetProjection(TH1 *h)
Set projection histogram.
NGnNavigator * fParent
Parent object.
virtual ~NGnNavigator()
Destructor.
std::vector< std::string > fParameterNames
Parameter names.
TH1 * GetProjection() const
Get projection histogram.
size_t fNLevels
Number of levels in the hierarchy.
virtual void Paint(Option_t *option="") override
Paint navigator objects.
void ResizeParameterErrorContentMap(const std::string &name, int n)
Resizes the error vector for a given parameter name.
virtual TList * DrawSpectra(std::string parameterName, std::vector< int > projIds, std::vector< double > minmax={0.05}, const std::string &minmaxMode="V", Option_t *option="") const
Draw spectra for a parameter.
virtual void Draw(Option_t *option="") override
Draw navigator objects.
std::map< std::string, std::vector< TObject * > > GetObjectContentMap() const
Get object content map.
void SetParameterError(const std::string &name, double value, int index=-1)
Sets a specific error value for a parameter.
std::vector< std::vector< int > > fLevels
Levels definition.
void SetLastIndexSelected(size_t idx)
Set last selected index.
TObject * GetObject(const std::string &name, int index=0) const
Get object by name and index.
std::vector< std::string > GetObjectNames() const
Get object names managed by navigator.
NGnNavigator * GetChild(size_t index) const
Get child navigator at index.
size_t fNCells
Number of cells in the projection histogram.
void Export(const std::string &filename, std::vector< std::string > objectNames, const std::string &wsUrl="", int timeoutMs=1000)
Export navigator data to file.
NGnNavigator(const char *name="GnNavigator", const char *title="Gn Navigator", std::vector< std::string > objectTypes={"TH1"})
Constructor.
NGnNavigator * Reshape(std::string binningName, std::vector< std::vector< int >> levels, size_t level=0, std::map< int, std::vector< int >> ranges={}, std::map< int, std::vector< int >> rangesBase={})
Reshape navigator using binning name and levels.
std::vector< std::string > fObjectTypes
Object types.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Calculate distance to primitive for graphical selection.
void SetGnTree(NGnTree *tree)
Set NGnTree object pointer.
size_t fLastHoverBin
To avoid spamming the console on hover.
json GetInfoJson() const
Retrieves information about the navigator in JSON format.
NGnTree * fGnTree
! Pointer to the NGnTree
size_t GetLastIndexSelected() const
Get last selected index.
std::map< std::string, std::vector< double > > fParameterContentMap
Parameter content map.
virtual TList * DrawSpectraAll(std::string parameterName, std::vector< double > minmax={0.05}, const std::string &minmaxMode="V", Option_t *option="") const
Draws all spectra for the given parameter.
size_t fLevel
Level of the object in the hierarchy.
void ExportToJson(json &j, NGnNavigator *obj, std::vector< std::string > objectNames)
Export navigator data to JSON.
std::vector< NGnNavigator * > fChildren
Children objects.
void SetNLevels(size_t n)
Set number of levels in hierarchy.
void SetNCells(size_t n)
Set number of cells in projection histogram.
std::map< std::string, std::vector< double > > fParameterErrorContentMap
Parameter error content map.
Int_t fTrigger
last triggered event
void SetParent(NGnNavigator *parent)
Set parent navigator.
std::vector< std::string > fObjectNames
Object names.
void ResizeObjectContentMap(const std::string &name, size_t n)
Resize object content map for a given name.
void SetParameter(const std::string &name, double value, int index=-1)
Set parameter value by name and index.
double GetParameter(const std::string &name, int index=0) const
Get parameter value by name and index.
std::vector< double > GetParameters(const std::string &name) const
Get parameters by name.
std::map< std::string, std::vector< double > > GetParameterContentMap() const
Get parameter content map.
std::vector< std::vector< int > > GetLevels() const
Get the current levels as a vector of vectors of integers.
std::vector< NGnNavigator * > GetChildren() const
Get vector of child navigators.
std::map< std::string, std::vector< TObject * > > fObjectContentMap
Object content map.
NGnNavigator * GetRoot() const
Returns the root parent of this NGnNavigator.
TH1 * fProjection
Projection histogram.
std::vector< double > GetParameterErrors(const std::string &name) const
Retrieves the error vector for a given parameter name.
NBinning * GetBinning() const
Get pointer to binning object.
Int_t GetEntry(Long64_t entry, bool checkBinningDef=true)
Get entry by index.
virtual void Print(Option_t *option="") const override
Print tree information.
NStorageTree * GetStorageTree() const
Get pointer to storage tree object.
TH1D * GetHisto() const
Returns the associated histogram.
NTreeBranch * GetBranch(const std::string &name)
Get pointer to NTreeBranch by name.
std::map< std::string, NTreeBranch > GetBranchesMap() const
Get map of branch names to NTreeBranch objects.
NDMSPC tree branch object for managing ROOT TBranch and associated data.
int GetBranchStatus() const
Get branch status.
void SetBranchStatus(int status)
Set branch status.
static void GetTrueHistogramMinMax(const TH1 *h, double &min_val, double &max_val, bool include_overflow_underflow=false)
Get minimum and maximum value of histogram bins.
static bool SetAxisRanges(THnSparse *sparse, std::vector< std::vector< int >> ranges={}, bool withOverflow=false, bool modifyTitle=false, bool reset=true)
Set axis ranges for THnSparse using vector of ranges.
static TH1 * ProjectTHnSparse(THnSparse *hns, const std::vector< int > &axes, Option_t *option="")
Project a THnSparse histogram onto specified axes.
static bool SaveRawFile(std::string filename, std::string content)
Save content to a raw file.
static bool GetAxisRangeInBase(TAxis *a, int rebin, int rebin_start, int bin, int &min, int &max)
Get axis range in base for rebinned axis.
static std::string Join(const std::vector< std::string > &values, const char delim=',')
Join vector of strings into a single string with delimiter.
static std::string GetCoordsString(const std::vector< int > &coords, int index=-1, int width=0)
Get string representation of coordinates.
static std::vector< std::vector< int > > Permutations(const std::vector< int > &v)
Generate all permutations of a vector.
WebSocket client for asynchronous communication using libwebsockets.
bool Connect(const std::string &uriString)
Connect to a WebSocket server.
void Disconnect()
Disconnect from the WebSocket server.
bool Send(const std::string &message)
Send a message to the server.