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);
402 Int_t nd = hnsIn->GetNdimensions();
403 Int_t *firstCoord =
new Int_t[nd];
405 hnsIn->GetBinContent(0, firstCoord);
410 int bx = firstCoord[axesIds[0]];
411 if (bx >= 1 && bx <= hProj->GetNbinsX())
412 hProj->SetBinContent(bx, hProj->GetBinContent(bx) + 1.0);
414 else if (nDims == 2) {
415 int bx = firstCoord[axesIds[0]];
416 int by = firstCoord[axesIds[1]];
417 if (bx >= 1 && bx <= hProj->GetNbinsX() && by >= 1 && by <= hProj->GetNbinsY())
418 hProj->SetBinContent(bx, by, hProj->GetBinContent(bx, by) + 1.0);
420 else if (nDims == 3) {
421 int bx = firstCoord[axesIds[0]];
422 int by = firstCoord[axesIds[1]];
423 int bz = firstCoord[axesIds[2]];
424 if (bx >= 1 && bx <= hProj->GetNbinsX() && by >= 1 && by <= hProj->GetNbinsY() &&
425 bz >= 1 && bz <= hProj->GetNbinsZ())
426 hProj->SetBinContent(bx, by, bz, hProj->GetBinContent(bx, by, bz) + 1.0);
432 NLogTrace(
"NGnNavigator::Reshape: [L%d] Projection histogram '%s' for coords=%s index=%d", level,
456 std::map<int, std::vector<int>> rangesTmp = ranges;
457 std::map<int, std::vector<int>> rangesBaseTmp = rangesBase;
458 for (
auto & kv : rangesBaseTmp) {
459 std::vector<int> range = rangesTmp[kv.first];
460 NLogTrace(
"NGnNavigator::Reshape: [L%d] Axis %d[%s]: rangeBase=%s range=%s", level, kv.first,
464 int minBase = 0, maxBase = 0;
466 for (
auto & c : coords) {
470 NLogTrace(
"NGnNavigator::Reshape: Axis %d: minBase=%d maxBase=%d", axesIds[i], minBase, maxBase);
471 rangesTmp[axesIds[i]] = {c, c};
472 rangesBaseTmp[axesIds[i]] = {minBase, maxBase};
476 if (hProj ==
nullptr) {
477 NLogError(
"NGnNavigator::Reshape: Projection histogram is null for level %d !!!", level);
481 size_t nCells = hProj->GetNcells();
485 if (currentChild ==
nullptr) {
486 NLogTrace(
"NGnNavigator::Reshape: [L%d] Creating new child for index %d nCells=%d ...", level, indexInProj,
488 std::string childName = TString::Format(
"%s_L%zu_C%d", GetName(), level + 1, indexInProj).Data();
489 currentChild =
new NGnNavigator(childName.c_str(), childName.c_str());
504 NLogError(
"NGnNavigator::Reshape: [L%d] Using existing child for index %d [NOT OK] ...", level, indexInProj);
510 if (level == levels.size() - 1) {
511 NLogTrace(
"NGnNavigator::Reshape: [L%d] Filling projections from all branches %s for ranges:", level,
513 for (
auto & kv : rangesBaseTmp) {
514 std::vector<int> range = rangesTmp[kv.first];
515 NLogTrace(
"NGnNavigator::Reshape: [L%d] Axis %d ['%s']: rangeBase=%s range=%s", level, kv.first,
527 std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{hnsIn->CreateIter(
true )};
528 std::vector<int> linBins;
532 while ((linBin = iter->Next()) >= 0) {
533 NLogTrace(
"NGnNavigator::Reshape: [L%d] Found bin %lld", level, linBin);
534 linBins.push_back(linBin);
536 if (linBins.empty()) {
537 NLogTrace(
"NGnNavigator::Reshape: [L%d] No bins found for the given ranges, skipping ...", level);
542 NLogTrace(
"NGnNavigator::Reshape: Branch object Point coordinates: %s",
546 for (
int lb : linBins) {
549 if (val.GetBranchStatus() == 0) {
550 NLogTrace(
"NGnNavigator::Reshape: [L%d] Branch '%s' is disabled, skipping ...", level, key.c_str());
553 NLogTrace(
"NGnNavigator::Reshape: [L%d] Processing branch '%s' with %zu objects to loop ...", level,
554 key.c_str(), linBins.size());
566 TString className = val.GetObjectClassName();
567 if (className.BeginsWith(
"THnSparse")) {
615 else if (className.BeginsWith(
"TList")) {
616 NLogTrace(
"[L%d] Branch '%s' is a TList, getting object at index %d ...", level, key.c_str(),
618 TList * list =
dynamic_cast<TList *
>(val.GetObject());
621 std::vector<std::string> objNames;
622 for (
int i = 0; i < list->GetEntries(); i++) {
623 TObject * o = list->At(i);
624 objNames.push_back(o->GetName());
629 NLogTrace(
"[L%d] Branch '%s' TList contains %d objects: %s", level, key.c_str(), list->GetEntries(),
636 for (
auto & name : objNames) {
637 TH1 * hProjTmp =
dynamic_cast<TH1 *
>(list->FindObject(name.c_str()));
638 if (hProjTmp ==
nullptr) {
639 NLogTrace(
"NGnNavigator::Reshape::Warning Branch '%s' TList does not contain '%s' as TH1 !!!",
640 key.c_str(), name.c_str());
645 if (TMath::IsNaN(hProjTmp->GetEntries()) || TMath::IsNaN(hProjTmp->GetSumOfWeights())) {
646 NLogWarning(
"NGnNavigator::Reshape: Branch '%s' '%s' histogram is nan !!!", key.c_str(),
653 "[L%d] Histogram name='%s' title='%s' for branch '%s' storing with indexInProj=%d, entries=%.0f",
654 level, name.c_str(), hProjTmp->GetTitle(), key.c_str(), indexInProj, hProjTmp->GetEntries());
666 TH1 * hClone = (TH1 *)hProjTmp->Clone();
667 hClone->SetDirectory(
nullptr);
668 current->
SetObject(name, hClone, indexInProj);
670 if (isValid ==
false) {
671 NLogTrace(
"NGnNavigator::Reshape::Warning: Branch '%s' TList does not contain any valid histograms !!!",
676 else if (className.BeginsWith(
"Ndmspc::NParameters")) {
680 TH1 * hParams = parameters->
GetHisto();
683 NLogTrace(
"[L%d] Branch '%s' Point contains '_params' histogram with %.0f entries ...", level,
684 key.c_str(), hParams->GetEntries());
686 for (
int b = 1; b <= hParams->GetNbinsX(); b++) {
688 std::string binLabel = hParams->GetXaxis()->GetBinLabel(b);
689 double binValue = hParams->GetBinContent(b);
690 double binError = hParams->GetBinError(b);
691 NLogTrace(
"[L%d] Bin %d[%s] = %e indexInProj=%d", level, b, binLabel.c_str(), binValue,
705 NLogTrace(
"[L%d] Stored parameter '%s' = %e +/- %e at indexInProj=%d", level, binLabel.c_str(),
706 binValue, binError, indexInProj);
711 NLogWarning(
"NGnNavigator::Reshape: Branch '%s' Point parameters object is null !!!", key.c_str());
715 NLogWarning(
"NGnNavigator::Reshape: Branch '%s' has unsupported class '%s' !!! Skipping ...", key.c_str(),
725 current->
SetChild(currentChild, indexInProj);
727 Reshape(binningDef, levels, level + 1, rangesTmp, rangesBaseTmp, currentChild);
729 executorBin.
Execute(loop_task_bin);
732 NLogTrace(
"NGnNavigator::Reshape: Reached the end of levels, level=%d", level);
733 std::vector<std::vector<int>> rangesEmpty;
739 NLogTrace(
"NGnNavigator::Reshape: =========== Reshaping navigator for level %d DONE ================", level);
742 NLogInfo(
"NGnNavigator::Reshape: Reshaping navigator DONE.");
744 for (
size_t l = 0; l < levels.size(); l++) {
745 std::string axesStr =
"";
746 for (
auto & a : levels[l]) {
747 TAxis * axis = binningDef->
GetContent()->GetAxis(a);
748 axesStr += TString::Format(
"%d('%s') ", a, axis->GetName()).Data();
750 NLogInfo(
" Level %zu axes: %s", l, axesStr.c_str());
761 void NGnNavigator::Export(
const std::string & filename, std::vector<std::string> objectNames,
const std::string & wsUrl,
767 NLogInfo(
"Exporting NGnNavigator to file: %s", filename.c_str());
772 if (filename.size() > 5 && filename.substr(filename.size() - 5) ==
".root") {
773 NLogInfo(
"Exporting NGnNavigator to ROOT file: %s", filename.c_str());
774 TFile * file = TFile::Open(filename.c_str(),
"RECREATE");
775 if (!file || file->IsZombie()) {
776 NLogError(
"Failed to open file: %s", filename.c_str());
784 else if (filename.size() > 5 && filename.substr(filename.size() - 5) ==
".json") {
785 NLogInfo(
"Exporting NGnNavigator to JSON file: %s", filename.c_str());
791 NLogError(
"Failed to save JSON file: %s", filename.c_str());
794 NLogInfo(
"Exported NGnNavigator to file: %s", filename.c_str());
796 else if (filename.empty()) {
797 NLogInfo(
"No filename provided, export to JSON only ...");
800 std::cout << objJson.dump() << std::endl;
803 NLogError(
"Unsupported file format for export: %s", filename.c_str());
806 if (!wsUrl.empty()) {
807 NLogInfo(
"Uploading exported file to web socket: %s", wsUrl.c_str());
810 std::string message = objJson.dump();
812 if (!message.empty()) {
813 NLogInfo(
"Connecting to web socket: %s", wsUrl.c_str());
815 NLogError(
"Failed to connect to '%s' !!!", wsUrl.c_str());
819 if (!client.
Send(objJson.dump())) {
820 NLogError(
"Failed to send message `%s`", message.c_str());
823 NLogInfo(
"Successfully sent message to '%s'", wsUrl.c_str());
827 NLogInfo(
"Waiting %d ms before disconnecting ...", timeoutMs);
828 gSystem->Sleep(timeoutMs);
830 NLogInfo(
"Disconnecting from '%s' ...", wsUrl.c_str());
834 NLogInfo(
"Sent: %s", message.c_str());
844 if (obj ==
nullptr) {
845 NLogError(
"NGnNavigator::ExportJson: Object is nullptr !!!");
855 NLogError(
"NGnNavigator::ExportJson: Projection is nullptr !!!");
866 TString hJsonStr = TBufferJSON::ConvertToJSON(h);
867 j = json::parse(hJsonStr.Data());
869 double entries = 0.0;
871 if (objectNames.empty()) {
874 bool isValid =
false;
877 for (
size_t i = 0; i < val.size(); i++) {
878 TObject * objContent = val[i];
882 std::string className = objContent ? objContent->ClassName() :
"";
883 if (className.empty()) {
884 NLogWarning(
"NGnNavigator::ExportJson: Object %s has empty class name", key.c_str());
888 className = className.substr(0, 3);
900 if (isValid) objectNames.push_back(key);
904 NLogDebug(
"NGnNavigator::ExportJson: Exporting selected objects: %s",
NUtils::GetCoordsString(objectNames).c_str());
908 for (
const auto & name : objectNames) {
909 NLogTrace(
"NGnNavigator::ExportJson: Included object name: '%s'", name.c_str());
914 NLogTrace(
"NGnNavigator::ExportJson: Processing object '%s' with %zu entries ...", key.c_str(), val.size());
916 if (std::find(objectNames.begin(), objectNames.end(), key) == objectNames.end()) {
917 NLogDebug(
"NGnNavigator::ExportJson: Skipping object '%s' ...", key.c_str());
921 double min = std::numeric_limits<double>::max();
922 double max = -std::numeric_limits<double>::max();
925 for (
size_t i = 0; i < val.size(); i++) {
926 TObject * objContent = val[i];
930 TH1 * hist =
dynamic_cast<TH1 *
>(objContent);
933 TString histJsonStr = TBufferJSON::ConvertToJSON(hist);
934 json objJson = json::parse(histJsonStr.Data());
935 double objMin, objMax;
937 min = TMath::Min(min, objMin);
938 max = TMath::Max(max, objMax);
939 entries = hist->GetEntries();
940 j[
"fArray"][i] = entries;
942 j[
"children"][key].push_back(objJson);
945 j[
"children"][key].push_back(
nullptr);
949 NLogWarning(
"NGnNavigator::ExportJson: Object %s at index %zu is not a TH1, skipping.", key.c_str(), i);
951 j[
"children"][key].push_back(
nullptr);
956 j[
"children"][key].push_back(
nullptr);
962 double min = std::numeric_limits<double>::max();
963 double max = -std::numeric_limits<double>::max();
966 for (
size_t i = 0; i < val.size(); i++) {
967 double param = val[i];
968 double paramError = 0.0;
970 if (i < val.size()) {
975 NLogWarning(
"NGnNavigator::ExportJson: Exception in GetParameterError for key %s index %zu", key.c_str(), i);
979 if (!std::isnan(param) && std::fabs(param) > 1e-12) {
980 min = TMath::Min(min, param);
981 max = TMath::Max(max, param);
982 j[
"fArrays"][key][
"values"][i] = param;
983 j[
"fArrays"][key][
"errors"][i] = TMath::Power(paramError, 2);
986 j[
"fArrays"][key][
"values"][i] = 0.0;
987 j[
"fArrays"][key][
"errors"][i] = 0.0;
991 if (key.compare(
"mass") == 0) {
999 double margin = 0.05 * (max - min);
1002 j[
"fArrays"][key][
"min"] = min;
1003 j[
"fArrays"][key][
"max"] = max;
1009 double min = std::numeric_limits<double>::max();
1010 double max = -std::numeric_limits<double>::max();
1011 std::vector<double> tmpContent;
1013 std::map<std::string, double> paramMinGlobal;
1014 std::map<std::string, double> paramMaxGlobal;
1015 bool firstChild =
true;
1018 if (child !=
nullptr) {
1023 NLogWarning(
"NGnNavigator::ExportJson: Exception in recursive ExportToJson for child.");
1027 if (childJson.contains(
"fArrays")) {
1028 for (
auto & [param, arr] : childJson[
"fArrays"].items()) {
1029 if (arr.contains(
"min") && arr.contains(
"max")) {
1030 double cmin = arr[
"min"].get<
double>();
1031 double cmax = arr[
"max"].get<
double>();
1032 if (firstChild || paramMinGlobal.find(param) == paramMinGlobal.end()) {
1033 paramMinGlobal[param] = cmin;
1034 paramMaxGlobal[param] = cmax;
1037 paramMinGlobal[param] = std::min(paramMinGlobal[param], cmin);
1038 paramMaxGlobal[param] = std::max(paramMaxGlobal[param], cmax);
1045 j[
"children"][
"content"].push_back(childJson);
1049 if (!paramMinGlobal.empty()) {
1050 for (
const auto & [param, minVal] : paramMinGlobal) {
1051 j[
"fArrays"][param][
"min"] = minVal;
1052 j[
"fArrays"][param][
"max"] = paramMaxGlobal[param];
1056 bool hasContent =
false;
1057 for (
auto & c : j[
"children"][
"content"]) {
1065 j[
"children"].erase(
"content");
1073 j[
"ndmspc"][
"content"][
"fMinimum"] = min;
1074 j[
"ndmspc"][
"content"][
"fMaximum"] = max;
1080 for (
const auto & child : j[
"children"][
"content"]) {
1082 if (child ==
nullptr || child.is_null()) {
1088 if (child.contains(
"ndmspc")) {
1091 double max = -std::numeric_limits<double>::max();
1093 for (
auto & [key, value] : child[
"ndmspc"].items()) {
1094 if (value.is_object()) {
1097 max = TMath::Max(max, value[
"fMaximum"].get<double>());
1100 j[
"fArray"][i] = max;
1106 if (j[
"children"][
"content"].is_null()) j[
"children"].erase(
"content");
1115 TString opt = option;
1120 NLogInfo(
"NGnNavigator: name='%s' title='%s' level=%d levels=%d projection='%s' title='%s'", GetName(), GetTitle(),
1125 NLogInfo(
"NGnNavigator: name='%s' title='%s' level=%d levels=%d projection=nullptr", GetName(), GetTitle(),
fLevel,
1129 NLogInfo(
"NGnNavigator: This is the root navigator.");
1132 for (
size_t l = 0; l <
fLevels.size(); l++) {
1133 std::string axesStr =
"";
1135 TAxis * axis = binningDef->
GetContent()->GetAxis(a);
1136 axesStr += TString::Format(
"%d('%s') ", a, axis->GetName()).Data();
1138 NLogInfo(
" Level %zu axes: %s", l, axesStr.c_str());
1147 std::vector<int> childIndices;
1148 for (
size_t i = 0; i <
fChildren.size(); i++) {
1151 childIndices.push_back(i);
1156 NLogTrace(
"NGnNavigator: %zu children with indices: %s", childIndices.size(),
1158 for (
size_t i = 0; i <
fChildren.size(); i++) {
1160 if (child && child->
GetChildren().empty() ==
false) {
1161 child->
Print(option);
1172 j[
"name"] = GetName();
1173 j[
"title"] = GetTitle();
1193 for (
size_t level = 0; level <
fNLevels; level++) {
1194 NLogDebug(
"NGnNavigator::Draw: Level %d/%d", level + 1,
fNLevels);
1196 NLogWarning(
"NGnNavigator::Draw: Level %d has projection with dimension %d > 2, which is not supported for "
1209 TString opt = option;
1211 if (opt.Contains(
"HOVER")) {
1214 if (opt.Contains(
"CLICK")) {
1219 if (gPad) SafeDelete(gPad);
1222 gROOT->MakeDefCanvas();
1226 Int_t cx = TMath::Ceil(
fNLevels / (Double_t)cy);
1227 gPad->Divide(cy, cx);
1230 TVirtualPad * originalPad = gPad;
1233 NLogDebug(
"NGnNavigator::Draw: Drawing level %d", level);
1234 TVirtualPad * pad = originalPad->cd(level + 1);
1236 NLogDebug(
"NGnNavigator::Draw: Clearing pad %d", level + 1);
1241 NLogDebug(
"NGnNavigator::Draw: Using current object at level %d: %s", level, obj->GetName());
1246 for (
size_t i = 0; i < obj->
GetChildren().size(); i++) {
1249 NLogDebug(
"NGnNavigator::Draw: Found child at level %d: %s", level, child->
GetProjection()->GetTitle());
1254 NLogDebug(
"NGnNavigator::Draw: Using child object at level %d: %s", level, obj ? obj->GetName() :
"nullptr");
1256 if (obj ==
nullptr) {
1257 NLogError(
"NGnNavigator::Draw: Child object at level %d is nullptr !!!", level);
1262 NLogDebug(
"NGnNavigator::Draw: Drawing projection at level %d: %s", level, projection->GetTitle());
1263 projection->SetMinimum(0);
1264 projection->SetStats(kFALSE);
1268 obj->AppendPad(option);
1271 NLogError(
"NGnNavigator::Draw: Projection at level %d is nullptr !!!", level);
1275 NLogError(
"NGnNavigator::Draw: Pad %d is nullptr !!!", level + 1);
1286 NLogInfo(
"NGnNavigator::Paint: Painting object ...");
1288 NLogDebug(
"NGnNavigator::Paint: Painting to pad=%d projection name=%s title=%s ...",
fLevel + 1,
1323 Double_t x_pad = gPad->AbsPixeltoX(px);
1324 Double_t y_pad = gPad->AbsPixeltoY(py);
1327 Double_t x_user = gPad->PadtoX(x_pad);
1328 Double_t y_user = gPad->PadtoY(y_pad);
1330 size_t bin =
fProjection->FindBin(x_user, y_user);
1332 TVirtualPad * originalPad = gPad;
1335 bool isActionTriggered = (
event ==
fTrigger);
1338 isActionTriggered = isActionTriggered && (isBinChanged ||
event == kButton1Down);
1340 if (isActionTriggered) {
1341 Int_t binx, biny, binz;
1343 Double_t content =
fProjection->GetBinContent(bin);
1344 NLogDebug(
"NGnNavigator::ExecuteEvent: [%s] Mouse trigger on bin=[%d, %d] at px=[%f, %f] with content: %f "
1345 "level=%d nLevels=%d",
1346 gPad->GetName(), binx, biny, x_user, y_user, content,
fLevel,
fNLevels);
1352 if (nDimensions == 1) {
1356 NLogTrace(
"NGnNavigator::ExecuteEvent: Index in histogram: %d level=%d", index,
fLevel);
1358 TCanvas * cObject = (TCanvas *)gROOT->GetListOfCanvases()->FindObject(
"cObject");
1360 NLogTrace(
"NGnNavigator::ExecuteEvent: [%s]Child object '%p' found at index %d", gPad->GetName(),
1363 gPad = originalPad->GetMother();
1364 TVirtualPad * pad = gPad->cd(
fLevel + 1 + 1);
1369 hProj->SetStats(kFALSE);
1370 hProj->SetMinimum(0);
1371 hProj->Draw(
"text colz");
1381 latex.SetTextAlign(22);
1382 latex.SetTextSize(0.05);
1383 latex.DrawLatex(0.5, 0.5,
"Select bottom pad to see projection");
1391 NLogTrace(
"NGnNavigator::ExecuteEvent: No child object found at index %d", index);
1393 TH1 * hProj = (TH1 *)
GetObject(objName, index);
1394 if (hProj ==
nullptr) {
1395 NLogError(
"NGnNavigator::ExecuteEvent: No histogram found for index %d", index);
1399 if (cObject ==
nullptr) {
1400 cObject =
new TCanvas(
"cObject",
"cObject", 800, 600);
1405 if (hProj->GetXaxis()->IsAlphanumeric()) {
1406 TPaveText * pt =
new TPaveText(0.15, 0.15, 0.85, 0.85);
1407 for (Int_t binx = 1; binx <= hProj->GetNbinsX(); ++binx) {
1408 std::string name = hProj->GetXaxis()->GetBinLabel(binx);
1409 std::string value = TString::Format(
"%.3f", hProj->GetBinContent(binx)).Data();
1410 std::string t = TString::Format(
"%s: %s", name.c_str(), value.c_str()).Data();
1412 pt->AddText(t.c_str());
1422 gPad->ModifiedUpdate();
1425 if (event == kMouseMotion) {
1429 Int_t binx, biny, binz;
1431 NLogTrace(
"[%s] Mouse hover on bin[%d, %d] at px[%f, %f] level=%d nLevels=%d", gPad->GetName(), binx, biny,
1435 NLogTrace(
"[%s] Setting point for level %d %s", gPad->GetName(),
fLevel,
fProjection->GetTitle());
1446 NLogTrace(
"NGnNavigator::GetChild: index=%d, size=%zu", index,
fChildren.size());
1470 THnSparse * hnsObjContent = binningDef->
GetContent();
1472 std::vector<std::vector<int>> ranges;
1477 NLogDebug(
"NGnNavigator::GetChild: Setting axis ranges for level=%d",
fLevel);
1479 for (
size_t i = 0; i < levels.size(); i++) {
1480 int coords_i = (int)coords[i][
fLevel];
1481 ranges.push_back({levels[i], coords_i, coords_i});
1482 NLogDebug(
"NGnNavigator::GetChild: level=%d axis=%d coord=%d",
fLevel, levels[i], coords_i);
1486 coords[0].resize(3, 0);
1488 size_t bin =
fProjection->GetBin(coords[0][0], coords[0][1], coords[0][2]);
1492 if (!next)
return nullptr;
1546 return it->second[index];
1560 NLogTrace(
"NGnNavigator::SetObject: name=%s, obj=%p, index=%d", name.c_str(), obj, index,
1598 return it->second[index];
1600 return TMath::QuietNaN();
1608 if (!std::isnan(value)) {
1610 NLogTrace(
"NGnNavigator::SetParameter: Resizing parameter content map for '%s' to %d", name.c_str(),
fNCells);
1613 NLogTrace(
"NGnNavigator::SetParameter: name=%s, value=%f, index=%d", name.c_str(), value, index,
1645 return it->second[index];
1647 return TMath::QuietNaN();
1655 if (!std::isnan(value)) {
1658 NLogTrace(
"NGnNavigator::SetParameter: Resizing parameter content map for '%s' to %d", name.c_str(),
fNCells);
1661 NLogTrace(
"NGnNavigator::SetParameter: name=%s, value=%f, index=%d", name.c_str(), value, index,
1678 const std::string & minmaxMode, Option_t * option)
const
1683 std::vector<int> projIds;
1684 return DrawSpectra(parameterName, projIds, minmax, minmaxMode, option);
1688 std::vector<double> minmax,
const std::string & minmaxMode,
1689 Option_t * option)
const
1695 std::vector<int> projIds;
1697 for (
const auto & axisName : projAxes) {
1698 TAxis * axis =
nullptr;
1699 for (
int i = 0; i <
fProjection->GetDimension(); i++) {
1707 if (axis && axis->GetName() == axisName) {
1708 projIds.push_back(i);
1713 if (projIds.empty()) {
1714 NLogError(
"NGnNavigator::DrawSpectra: No projection axes found for names: %s",
1719 if (projIds.size() > 3) {
1720 NLogError(
"NGnNavigator::DrawSpectra: Too many projection dimensions: %zu (max 3)", projIds.size());
1724 if (projIds.size() != projAxes.size()) {
1725 NLogError(
"NGnNavigator::DrawSpectra: Not all projection axes found: %s",
1730 return DrawSpectra(parameterName, projIds, minmax, minmaxMode, option);
1734 const std::string & minmaxMode, Option_t * option)
const
1740 if (parameterName.empty()) {
1741 NLogError(
"NGnNavigator::DrawSpectra: Parameter name is empty");
1747 NLogError(
"NGnNavigator::DrawSpectra: Parameter name '%s' not found in fParameterContentMap",
1748 parameterName.c_str());
1751 Int_t screenWidth = gClient->GetDisplayWidth();
1752 Int_t screenHeight = gClient->GetDisplayHeight();
1755 TCanvas * c =
nullptr;
1757 constexpr
double canvasScale = 0.2;
1758 Int_t canvasWidth =
static_cast<Int_t
>(screenWidth * canvasScale);
1759 Int_t canvasHeight =
static_cast<Int_t
>(screenHeight * canvasScale);
1761 if (canvasWidth < 800) canvasWidth = 800;
1762 if (canvasHeight < 600) canvasHeight = 600;
1764 NLogTrace(
"Screen size: %dx%d", screenWidth, screenHeight);
1767 THnSparse * hnsObjContent = binningDef->
GetContent();
1769 std::vector<std::vector<int>> projections;
1770 if (projIds.empty()) {
1772 std::iota(projIds.begin(), projIds.end(), 0);
1776 projections.push_back(projIds);
1779 if (projections.empty()) {
1780 NLogError(
"NGnNavigator::DrawSpectra: No projections found");
1783 if (projections[0].size() > 3) {
1784 NLogError(
"NGnNavigator::DrawSpectra: Too many projection dimensions: %zu (max 3)", projections[0].size());
1788 TList * outputList =
new TList();
1789 for (
const auto & proj : projections) {
1794 TH1 * hParameterProjection = (TH1 *)
fProjection->Clone(
"hParameterProjection");
1796 hParameterProjection->SetDirectory(
nullptr);
1800 hParameterProjection->SetContent(
GetParameters(parameterName).data());
1810 THnSparse * hsParam = THnSparse::CreateSparse(parameterName.c_str(), parameterName.c_str(), hParameterProjection);
1813 int nDimensions = hParameterProjection->GetDimension();
1814 for (
int i = 0; i < nDimensions; i++) {
1815 TAxis * axis =
nullptr;
1817 axis = hParameterProjection->GetXaxis();
1819 axis = hParameterProjection->GetYaxis();
1821 axis = hParameterProjection->GetZaxis();
1823 hsParam->GetAxis(i)->SetName(axis->GetName());
1824 hsParam->GetAxis(i)->SetTitle(axis->GetTitle());
1825 if (axis->IsVariableBinSize()) {
1826 hsParam->GetAxis(i)->Set(axis->GetNbins(), axis->GetXbins()->GetArray());
1828 if (axis->IsAlphanumeric()) {
1829 for (
int j = 1; j <= axis->GetNbins(); j++) {
1830 const char * label = axis->GetBinLabel(j);
1831 hsParam->GetAxis(i)->SetBinLabel(j, label);
1836 delete hParameterProjection;
1838 std::vector<int> dims;
1842 for (
auto &
id : proj) {
1843 dims.push_back(currentLevels[
id]);
1846 if (dims.size() > 3) {
1847 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;
1860 for (
int dim : dims) {
1861 int nBins = hnsObjContent->GetAxis(dim)->GetNbins();
1862 ranges.push_back({dim, 1, nBins});
1866 Int_t * p =
new Int_t[hnsObjContent->GetNdimensions()];
1867 Long64_t linBin = 0;
1868 std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{hnsObjContent->CreateIter(
true )};
1869 while ((linBin = iter->Next()) >= 0) {
1871 Double_t v = hnsObjContent->GetBinContent(linBin, p);
1872 Long64_t idx = hnsObjContent->GetBin(p);
1874 NLogTrace(
"Bin %lld(%lld): %f %s", linBin, idx, v, binCoords.c_str());
1875 dimsResults[0].insert(p[dims[0]]);
1876 if (dims.size() > 1) dimsResults[1].insert(p[dims[1]]);
1877 if (dims.size() > 2) dimsResults[2].insert(p[dims[2]]);
1880 if (!gROOT->IsBatch()) {
1891 int nPads = dims.size() > 2 ? dimsResults[2].size() : 1;
1892 NLogDebug(
"Number of pads: %d", nPads);
1893 std::vector<std::string> projNames;
1895 NLogTrace(
"Projection dims: %d %d %d", dims[0], dims.size() > 1 ? dims[1] : -1, dims.size() > 2 ? dims[2] : -1);
1896 projNames.push_back(hnsObjContent->GetAxis(dims[0])->GetName());
1897 if (dims.size() > 1) projNames.push_back(hnsObjContent->GetAxis(dims[1])->GetName());
1898 if (dims.size() > 2) projNames.push_back(hnsObjContent->GetAxis(dims[2])->GetName());
1904 std::string canvasName = Form(
"c_%s", posfix.c_str());
1905 NLogTrace(
"Creating canvas '%s' with size %dx%d", canvasName.c_str(), canvasWidth, canvasHeight);
1908 TCanvas * existingCanvas = (TCanvas *)gROOT->GetListOfCanvases()->FindObject(canvasName.c_str());
1909 if (existingCanvas) {
1910 NLogTrace(
"Deleting existing canvas '%s'", canvasName.c_str());
1911 delete existingCanvas;
1914 c =
new TCanvas(canvasName.c_str(), canvasName.c_str(), canvasWidth, canvasHeight);
1915 c->SetBit(kMustCleanup, kFALSE);
1919 TList * stackList =
new TList();
1921 for (
int iPad = 0; iPad < nPads; iPad++) {
1924 std::string stackName = Form(
"hStack_%s_%d", posfix.c_str(), iPad);
1925 std::string stackTitle = parameterName +
" : ";
1926 stackTitle += projNames[0];
1927 stackTitle += projNames.size() > 1 ?
" vs " + projNames[1] :
"";
1928 if (proj.size() > 2) {
1929 p[proj[2]] = iPad + 1;
1936 TAxis * aPad = hsParam->GetAxis(proj[2]);
1937 if (aPad->IsAlphanumeric()) {
1938 stackTitle += projNames.size() > 2 ?
" for " + projNames[2] +
" [" + aPad->GetBinLabel(p[proj[2]]) +
"]" :
"";
1941 double binLowEdge = aPad->GetBinLowEdge(p[proj[2]]);
1942 double binUpEdge = aPad->GetBinUpEdge(p[proj[2]]);
1944 projNames.size() > 2 ?
" for " + projNames[2] +
" " + Form(
" [%.3f,%.3f]", binLowEdge, binUpEdge) :
"";
1947 NLogTrace(
"Creating stack '%s' with title '%s'", stackName.c_str(), stackTitle.c_str());
1955 THStack * hStack =
new THStack(stackName.c_str(), stackTitle.c_str());
1956 hStack->SetBit(kMustCleanup, kFALSE);
1958 int nStacks = proj.size() > 1 ? dimsResults[1].size() : 1;
1959 double stackMin = std::numeric_limits<double>::max();
1960 double stackMax = std::numeric_limits<double>::lowest();
1962 std::string mode = (minmaxMode ==
"VE" || minmaxMode ==
"V" || minmaxMode ==
"D") ? minmaxMode :
"V";
1963 for (
int iStack = 0; iStack < nStacks; iStack++) {
1965 if (proj.size() > 1) p[proj[1]] = iStack + 1;
1966 std::vector<std::vector<int>> ranges;
1967 if (proj.size() > 2) ranges.push_back({proj[2], p[proj[2]], p[proj[2]]});
1968 if (proj.size() > 1) ranges.push_back({proj[1], p[proj[1]], p[proj[1]]});
1971 if (!hProj || hProj->GetEntries() == 0) {
1972 NLogError(
"Failed to project THnSparse for stack %d with projection IDs: %s", iStack,
1977 if (proj.size() > 1) {
1978 TAxis * aStack = hsParam->GetAxis(proj[1]);
1979 if (aStack->IsAlphanumeric()) {
1980 std::string label = aStack->GetBinLabel(p[proj[1]]);
1981 hProj->SetName(Form(
"%s_%s", aStack->GetName(), label.c_str()));
1982 hProj->SetTitle(Form(
"%s [%s]", aStack->GetName(), label.c_str()));
1985 double binLowEdge = aStack->GetBinLowEdge(p[proj[1]]);
1986 double binUpEdge = aStack->GetBinUpEdge(p[proj[1]]);
1987 hProj->SetName(Form(
"%s_%.3f_%.3f", aStack->GetName(), binLowEdge, binUpEdge));
1988 hProj->SetTitle(Form(
"%s [%.3f,%.3f]", aStack->GetName(), binLowEdge, binUpEdge));
1993 for (
int bin = 1; bin <= hProj->GetNbinsX(); ++bin) {
1994 double val = hProj->GetBinContent(bin);
1995 double err = hProj->GetBinError(bin);
1997 if (stackMin > val - err) stackMin = val - err;
1998 if (stackMax < val + err) stackMax = val + err;
2000 else if (mode ==
"V") {
2001 if (stackMin > val) stackMin = val;
2002 if (stackMax < val) stackMax = val;
2006 hProj->SetMarkerStyle(20);
2007 hProj->SetMarkerColor(iStack + 1);
2009 TH1 * hProjClone = (TH1 *)hProj->Clone();
2012 hProjClone->SetDirectory(
nullptr);
2013 hStack->Add(hProjClone);
2019 hStack->SetMinimum(-1111);
2020 hStack->SetMaximum(-1111);
2024 if (minmax.size() > 0) {
2025 if (minmax.size() == 2) {
2026 stackMin = minmax[0];
2027 stackMax = minmax[1];
2029 else if (minmax.size() == 1) {
2031 double percent = minmax[0];
2032 double center = 0.5 * (stackMax + stackMin);
2033 double halfRange = 0.5 * (stackMax - stackMin);
2034 double margin = percent * halfRange;
2035 stackMin = center - (halfRange + margin);
2036 stackMax = center + (halfRange + margin);
2041 if (stackMin == stackMax) {
2042 if (stackMin == 0.0) {
2051 hStack->SetMinimum(stackMin);
2052 hStack->SetMaximum(stackMax);
2055 if (hStack->GetNhists() == 0) {
2056 NLogError(
"No histograms were added to the stack for pad %d with projection IDs: %s", iPad,
2069 stackList->Add(hStack);
2076 if (stackList->GetEntries() > 0) {
2077 nPads = stackList->GetEntries();
2078 c->DivideSquare(nPads);
2079 for (
int iPad = 0; iPad < nPads; iPad++) {
2081 THStack * hStack = (THStack *)stackList->At(iPad);
2083 hStack->Draw(
"nostack E");
2084 NLogTrace(
"Drawing stack with option: %s in pad %d %d",
"nostack E", iPad + 1, hStack->GetNhists());
2085 hStack->GetHistogram()->GetXaxis()->SetTitle(projNames[0].c_str());
2086 hStack->GetHistogram()->GetYaxis()->SetTitle(parameterName.c_str());
2087 if (dims.size() > 1) gPad->BuildLegend(0.75, 0.75, 0.95, 0.95,
"");
2088 c->ModifiedUpdate();
2107 if (fParent ==
nullptr) {
2112 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< int > ArrayToVector(Int_t *v1, int size)
Convert array to vector.
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.