ndmspc  v1.1.1-1
NBinning.cxx
1 #include <string>
2 #include <vector>
3 #include "TAxis.h"
4 #include <TAttAxis.h>
5 #include <TObjArray.h>
6 #include "NBinningDef.h"
7 #include "NBinningPoint.h"
8 #include "NDimensionalExecutor.h"
9 #include "NUtils.h"
10 #include "NLogger.h"
11 
12 #include "NBinning.h"
13 
15 ClassImp(Ndmspc::NBinning);
17 
18 namespace Ndmspc {
19 NBinning::NBinning() : TObject()
20 {
24 }
25 NBinning::NBinning(std::vector<TAxis *> axes) : TObject(), fAxes(axes)
26 {
30 
31  Initialize();
32 }
33 NBinning::NBinning(TObjArray * axes) : TObject()
34 {
38 
39  if (axes == nullptr) {
40  NLogError("NBinning(TObjArray * axes) : axes is nullptr");
41  return;
42  }
43 
44  for (int i = 0; i < axes->GetEntriesFast(); i++) {
45  TAxis * axis = dynamic_cast<TAxis *>(axes->At(i));
46  if (axis) {
47  fAxes.push_back((TAxis *)axis->Clone());
48  }
49  else {
50  NLogError("NBinning: Axis %d is not a TAxis", i);
51  }
52  }
53 
54  Initialize();
55 }
57 {
61 
62  // Cleanup fDefinitions
63  for (auto & def : fDefinitions) {
64  delete def.second;
65  }
66  fDefinitions.clear();
67 
68  // Cleanup fAxes
69  for (auto & axis : fAxes) {
70  if (axis) {
71  delete axis; // Delete the axis if it was created by this class
72  }
73  }
74 
75  delete fMap;
76  delete fContent;
77 }
79 {
83  fMap->Reset();
84  fContent->Reset();
85  if (fPoint != nullptr) {
86  fPoint->Reset();
87  }
88 }
89 
91 {
95 
96  if (fAxes.size() == 0) {
97  NLogError("No axes provided");
98  return;
99  }
100 
101  int dim = fAxes.size();
102  // Calculate maximyn=m of nbins
103  int nbinsMax = 0;
104  int nContentDims = 0;
105  Binning binningType;
106  for (int i = 0; i < dim; i++) {
107  int nbins = fAxes[i]->GetNbins();
108  if (nbins > nbinsMax) {
109  nbinsMax = nbins;
110  }
111  // NLogDebug("Axis %d: %s nbins=%d", i, fAxes[i]->GetName(), nbins);
112  // if (nbins == 1 || axes[i]->IsAlphanumeric()) {
113  TString axisname(fAxes[i]->GetName());
114  bool isUser = axisname.Contains("/U");
115  if (isUser) {
116  axisname.ReplaceAll("/U", "");
117  fAxes[i]->SetName(axisname.Data());
118  }
119 
120  if (isUser) {
121  binningType = Binning::kUser;
122  nContentDims++;
123  }
124  else if (fAxes[i]->IsAlphanumeric()) {
125  // TODO: Optimized beiing for alphanumeric axis (maybe no need to fix)
126  // binningType = Binning::kSingle;
127  // nContentDims++;
128  binningType = Binning::kMultiple;
129  nContentDims += 3;
130  }
131  else {
132  binningType = Binning::kMultiple;
133  nContentDims += 3;
134  }
135  fBinningTypes.push_back(binningType);
136  fAxisTypes.push_back(AxisType::kFixed);
137  }
138  int dimBinning = 4;
139  Int_t * nbinsBinning = new Int_t[dimBinning];
140  Double_t * xminBinning = new Double_t[dimBinning];
141  Double_t * xmaxBinning = new Double_t[dimBinning];
142  // set first item nbinsBinning to dim min to zero and max to dim
143 
144  nbinsBinning[0] = dim;
145  xminBinning[0] = 0;
146  xmaxBinning[0] = dim;
147  for (int i = 1; i < dimBinning; i++) {
148  nbinsBinning[i] = nbinsMax;
149  xminBinning[i] = 0;
150  xmaxBinning[i] = nbinsMax;
151  }
152 
153  if (fMap) {
154  delete fMap;
155  }
156  fMap = new THnSparseI("ngntBinningMap", "NGnTree binning map", dimBinning, nbinsBinning, xminBinning, xmaxBinning);
157  if (fMap == nullptr) {
158  NLogError("Cannot create binnings !!!");
159  return;
160  }
161  fMap->GetAxis(0)->SetNameTitle("dim", "dimension");
162  fMap->GetAxis(1)->SetNameTitle("rebin", "rebins");
163  fMap->GetAxis(2)->SetNameTitle("start", "rebins start");
164  fMap->GetAxis(3)->SetNameTitle("bin", "bin id");
165 
166  for (int i = 0; i < dim; i++) {
167  fMap->GetAxis(0)->SetBinLabel(i + 1, fAxes[i]->GetName());
168  }
169 
170  int dimBinningContent = nContentDims;
171  Int_t * nbinsBinningContent = new Int_t[dimBinningContent];
172  Double_t * xminBinningContent = new Double_t[dimBinningContent];
173  Double_t * xmaxBinningContent = new Double_t[dimBinningContent];
174  int iContentDim = 0;
175  for (int i = 0; i < dim; i++) {
176  if (fBinningTypes[i] == Binning::kSingle) {
177  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
178  nbinsBinningContent[iContentDim] = fAxes[i]->GetNbins();
179  xminBinningContent[iContentDim] = 0;
180  xmaxBinningContent[iContentDim] = fAxes[i]->GetNbins();
181  iContentDim++;
182  NLogTrace("[S] Binning %d: %d", i, fAxes[i]->GetNbins());
183  }
184  else if (fBinningTypes[i] == Binning::kMultiple) {
185  for (int j = 0; j < 3; j++) {
186  nbinsBinningContent[iContentDim + j] = fAxes[i]->GetNbins();
187  xminBinningContent[iContentDim + j] = 0;
188  xmaxBinningContent[iContentDim + j] = fAxes[i]->GetNbins();
189  }
190  iContentDim += 3;
191  NLogTrace("[M] Binning %d: %d", i, fAxes[i]->GetNbins());
192  }
193  else if (fBinningTypes[i] == Binning::kUser) {
194  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
195  nbinsBinningContent[iContentDim] = fAxes[i]->GetNbins();
196  xminBinningContent[iContentDim] = 0;
197  xmaxBinningContent[iContentDim] = fAxes[i]->GetNbins();
198  iContentDim++;
199  NLogTrace("[U] Binning %d: %d", i, fAxes[i]->GetNbins());
200  }
201  else {
202  NLogError("Invalid binning type %d", fBinningTypes[i]);
203  return;
204  }
205  }
206  fContent = new THnSparseI("ngntBinningContent", "NGnTree binning content", dimBinningContent, nbinsBinningContent,
207  xminBinningContent, xmaxBinningContent);
208 
209  int iContentAxis = 0;
210  std::vector<std::string> types = {"rebin", "start", "bin"};
211  for (int i = 0; i < dim; i++) {
212  std::string name = fAxes[i]->GetName();
213  std::string title = fAxes[i]->GetName();
214  // NLogTrace("Binning %d: %d %d", i, axes[i]->GetNbins(), fBinningTypes[i]);
215  if (fBinningTypes[i] == Binning::kSingle) {
216  fContent->GetAxis(iContentAxis)->SetNameTitle(name.c_str(), title.c_str());
217  iContentAxis++;
218  }
219  else if (fBinningTypes[i] == Binning::kMultiple) {
220  for (int j = 0; j < 3; j++) {
221  int imod = j % 3;
222  std::string n = name + "_" + types[imod];
223  std::string t = title + " (" + types[imod] + ")";
224  fContent->GetAxis(iContentAxis)->SetNameTitle(n.c_str(), t.c_str());
225  iContentAxis++;
226  }
227  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
228  }
229  else if (fBinningTypes[i] == Binning::kUser) {
230  fContent->GetAxis(iContentAxis)->SetNameTitle(name.c_str(), title.c_str());
231  iContentAxis++;
232  }
233  }
234  for (int i = 0; i < fContent->GetNdimensions(); i++) {
235  NLogTrace("Axis[fContent] %d: %s nbins=%d", i, fContent->GetAxis(i)->GetName(), fContent->GetAxis(i)->GetNbins());
236  }
237 
238  fPoint = new NBinningPoint(this);
239 
240  delete[] nbinsBinning;
241  delete[] xminBinning;
242  delete[] xmaxBinning;
243 }
244 
245 void NBinning::Print(Option_t * option) const
246 {
250 
251  if (fMap == nullptr) {
252  NLogError("THnSparse fMap is null");
253  return;
254  }
255 
256  TString opt(option);
257  opt.ToLower();
258 
259  NLogInfo("NBinning base axes:");
260  for (size_t i = 0; i < fAxes.size(); i++) {
261  NLogInfo(" Axis %d: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, fAxes[i]->GetName(), fAxes[i]->GetTitle(),
262  fAxes[i]->GetNbins(), fAxes[i]->GetXmin(), fAxes[i]->GetXmax());
263  }
264 
265  if (opt.Contains("A")) {
266  NLogInfo("NBinning map name='%s' title='%s'", fMap->GetName(), fMap->GetTitle());
267  NLogInfo(" dimensions: %d", fMap->GetNdimensions());
268  // loop over all axes and print name title
269  for (int i = 0; i < fMap->GetNdimensions(); i++) {
270  NLogInfo(" [%d] name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, fMap->GetAxis(i)->GetName(),
271  fMap->GetAxis(i)->GetTitle(), fMap->GetAxis(i)->GetNbins(), fMap->GetAxis(i)->GetXmin(),
272  fMap->GetAxis(i)->GetXmax());
273  }
274  NLogInfo(" filled bins = %lld", fMap->GetNbins());
275  NLogInfo("NBinning content name='%s' title='%s'", fContent->GetName(), fContent->GetTitle());
276  NLogInfo(" dimensions: %d", fContent->GetNdimensions());
277  // loop over all axes and print name title
278  for (int i = 0; i < fContent->GetNdimensions(); i++) {
279  NLogInfo(" [%d] name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, fContent->GetAxis(i)->GetName(),
280  fContent->GetAxis(i)->GetTitle(), fContent->GetAxis(i)->GetNbins(), fContent->GetAxis(i)->GetXmin(),
281  fContent->GetAxis(i)->GetXmax());
282  }
283  }
284  NLogInfo("NBinning content:");
285  NLogInfo(" filled bins = %lld", fContent->GetNbins());
286  // print list of definitions names from fDefinitions
287  NLogInfo("NBinning definitions:");
288  for (const auto & kv : fDefinitions) {
289  if (kv.first == fCurrentDefinitionName) {
290  NLogInfo(" '%s' (current)", kv.first.c_str());
291  }
292  else {
293  NLogInfo(" '%s'", kv.first.c_str());
294  }
295  }
296 
297  if (option && opt.Contains("all")) {
298  NLogInfo("NBinning content:");
299  PrintContent(option);
300  }
301 
302  // // loop over definition and print
303  // for (const auto & kv : fDefinition) {
304  // NLogInfo("Binning '%s':", kv.first.c_str());
305  // for (const auto & v : kv.second) {
306  // NLogInfo(" %s", NUtils::GetCoordsString(v, -1).c_str());
307  // }
308  // }
309 
310  // fMap->Print(option);
311 
312  // // Using executor print all bins
313  // NDimensionalExecutor executor(fMap, true);
314  // // NDimensionalExecutor executor(fMap, false);
315  // auto binning_task = [this, &all_bins](const std::vector<int> & coords) {
316  // fMap->Print();
317  // NUtils::PrintPointSafe(coords, -1);
318  // };
319  //
320  // executor.Execute(binning_task);
321 
322  // size_t num_threads_to_use = 0;
323  // // set num_threads_to_use to the number of available threads
324  // if (num_threads_to_use < 1) num_threads_to_use = std::thread::hardware_concurrency();
325  // NLogInfo("Using %zu threads ...", num_threads_to_use);
326  // std::vector<NThreadData> thread_data_vector(num_threads_to_use);
327  // for (size_t i = 0; i < thread_data_vector.size(); ++i) {
328  // thread_data_vector[i].SetAssignedIndex(i);
329  // }
330  //
331  // // 2. Define the lambda (type in signature updated)
332  // auto parallel_task = [](const std::vector<int> & coords, NThreadData & thread_obj) {
333  // NUtils::PrintPointSafe(coords, thread_obj.GetAssignedIndex());
334  // thread_obj.Process(coords);
335  // // thread_obj.Print();
336  // };
337  //
338  // // 3. Call ExecuteParallel (template argument updated)
339  // executor.ExecuteParallel<NThreadData>(parallel_task, thread_data_vector);
340 }
341 void NBinning::PrintContent(Option_t * option) const
342 {
346 
347  std::map<std::string, std::vector<int>> binningMap;
348 
349  TString opt(option);
350  // loop over all selected bins via ROOT iterarot for THnSparse
351  THnSparse * cSparse = fContent;
352  Int_t * bins = new Int_t[cSparse->GetNdimensions()];
353  Long64_t linBin = 0;
354  std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{cSparse->CreateIter(true /*use axis range*/)};
355  while ((linBin = iter->Next()) >= 0) {
356  Double_t v = cSparse->GetBinContent(linBin, bins);
357  Long64_t idx = cSparse->GetBin(bins);
358  std::string binCoords = NUtils::GetCoordsString(NUtils::ArrayToVector(bins, cSparse->GetNdimensions()), -1);
359  NLogTrace("Bin %lld: %f %s idx=%lld content=%f", linBin, v, binCoords.c_str(), idx, v);
360 
361  size_t iAxis = 0;
362  bool isValid = false;
363  // for (int i = 0; i < cSparse->GetNdimensions(); i += 3) {
364  int index = 0;
365  for (iAxis = 0; iAxis < fAxes.size(); iAxis++) {
366  int min;
367  int max;
368  // Print type of binning
369  // NLogTrace("Axis %d: %s [%s]", iAxis, fAxes[iAxis]->GetName(),
370  // fBinningTypes[iAxis] == Binning::kSingle ? "S" : "M");
371  if (fBinningTypes[iAxis] == Binning::kSingle) {
372  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, bins[index], min, max);
373  binCoords += TString::Format(" | (S%c) %s %d %d %d [%d,%d] [%d,%d]", GetAxisTypeChar(iAxis),
374  fAxes[iAxis]->GetName(), 1, 1, bins[index], min, max, 1, fAxes[iAxis]->GetNbins())
375  .Data();
376  binningMap[fAxes[iAxis]->GetName()] = {1, 1, bins[index]};
377  index++;
378  }
379  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
380  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], bins[index], bins[index + 1], bins[index + 2], min, max);
381  binCoords +=
382  TString::Format(" | (M%c) %s %d %d %d [%d,%d] [%d,%d]", GetAxisTypeChar(iAxis), fAxes[iAxis]->GetName(),
383  bins[index], bins[index + 1], bins[index + 2], min, max, 1, fAxes[iAxis]->GetNbins())
384  .Data();
385  binningMap[fAxes[iAxis]->GetName()] = {bins[index], bins[index + 1], bins[index + 2]};
386  index += 3;
387  }
388  else if (fBinningTypes[iAxis] == Binning::kUser) {
389  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], fAxes[iAxis]->GetNbins(), 1, 1, min, max);
390  binCoords += TString::Format(" | (U) %s %d %d %d [%d,%d] [%d,%d]", fAxes[iAxis]->GetName(),
391  fAxes[iAxis]->GetNbins(), 1, 1, min, max, 1, fAxes[iAxis]->GetNbins())
392  .Data();
393  // binningMap[fAxes[iAxis]->GetName()] = {1, 1, bins[index]};
394  binningMap[fAxes[iAxis]->GetName()] = {fAxes[iAxis]->GetNbins(), 1, 1};
395  index++;
396  }
397  else {
398  NLogError("[NBinning::PrintContent] Unknown binning type [%d]", fBinningTypes[iAxis]);
399  continue;
400  }
401  if (!isValid) {
402  NLogError("Cannot get axis range for axis %d", iAxis);
403  continue;
404  }
405  }
406  if (!isValid) {
407  // NLogError("Cannot get axis range for axis %d", iAxis);
408  NLogError("Bin %lld: %s [not valid for axis=%s]", linBin, binCoords.c_str(), fAxes[iAxis]->GetName());
409  continue;
410  }
411  NLogDebug("Bin %lld: %s", linBin, binCoords.c_str());
412  }
413  delete[] bins;
414 }
415 
417 {
421  Long64_t nBinsFilled = 0;
422 
423  // fContent->Reset();
424 
425  std::vector<int> mins(fMap->GetAxis(0)->GetNbins(), 1);
426  std::vector<int> maxs(fMap->GetAxis(0)->GetNbins(), 0);
427  std::vector<std::vector<std::vector<int>>> content(fMap->GetAxis(0)->GetNbins());
428 
429  // loop over all selected bins via ROOT iterarot for THnSparse
430  THnSparse * cSparse = fMap;
431  Int_t * p = new Int_t[cSparse->GetNdimensions()];
432  Long64_t linBin = 0;
433  std::unique_ptr<ROOT::Internal::THnBaseBinIter> iter{cSparse->CreateIter(true /*use axis range*/)};
434  // Print number of filled bins
435  // NLogInfo("Filled bins = %lld", cSparse->GetNbins());
436  while ((linBin = iter->Next()) >= 0) {
437  Double_t v = cSparse->GetBinContent(linBin, p);
438  // continue;
439  int idx = p[0] - 1;
440  NLogTrace("NBinning::FillAll: Bin %lld: %d %d %d %d type=%d content=%f", linBin, p[0], p[1], p[2], p[3],
441  fBinningTypes[idx], v);
442  if (fBinningTypes[idx] == Binning::kSingle) {
443 
444  content[idx].push_back({p[0], p[3]});
445  }
446  else if (fBinningTypes[idx] == Binning::kMultiple) {
447  // NLogDebug("Binning %d: %d", i, axes[idim]->GetNbins());
448  content[idx].push_back({p[0], p[1], p[2], p[3]});
449  }
450  else if (fBinningTypes[idx] == Binning::kUser) {
451  // TODO: Fix nbins for user binning (it should ok now)
452  content[idx].push_back({p[0], 1});
453  }
454  else {
455  NLogError("NBinning::FillAll: Unknown binning type %d", fBinningTypes[idx]);
456  continue;
457  }
458  maxs[idx] = maxs[idx] + 1;
459  }
460  delete[] p;
461 
462  Long64_t nTotalBins = 1;
463  // loop over content vector and set axis types
464  for (size_t i = 0; i < content.size(); i++) {
465  if (content[i].size() == 0) {
466  NLogWarning("NBinning::FillAll: No content for binning %zu", i);
467  continue;
468  }
469 
470  if (content[i].size() > 1) {
471  TAxis * axis = fAxes[i];
472  fAxisTypes[i] = AxisType::kVariable;
473  NLogTrace("NBinning::FillAll: Axis id=%d name=%s bins=%zu", i, axis->GetName(), content[i].size());
474  // check if i is persent in variable axes of def
475  bool found = false;
476  for (size_t j = 0; j < def->GetVariableAxes().size(); j++) {
477  if (def->GetVariableAxes()[j] == static_cast<int>(i)) {
478  NLogTrace("NBinning::FillAll: Axis id=%d name=%s already in variable axes of def", i, axis->GetName());
479  found = true;
480  break;
481  }
482  }
483  NLogTrace("NBinning::FillAll: Axis id=%d name=%s set to variable found=%d", i, axis->GetName(), found);
484  if (!found) def->AddVariableAxis(i);
485  }
486  nTotalBins *= content[i].size();
487  }
488 
489  def->Print();
490  NLogDebug("NBinning::FillAll: Filling total of %lld bins ...", nTotalBins);
491 
492  auto start_par = std::chrono::high_resolution_clock::now();
493  // Loop over all binning combinations
494  NDimensionalExecutor executor(mins, maxs);
495  auto binning_task = [&content, &nBinsFilled, &nTotalBins, start_par, def, this](const std::vector<int> & coords) {
496  std::vector<int> pointContentVector;
497  NLogTrace("Binning task: %s", NUtils::GetCoordsString(coords, -1).c_str());
498  for (size_t i = 0; i < coords.size(); i++) {
499  NLogTrace(" Binning %zu: coord=%d content size=%zu", i, coords[i], content[i].size());
500  if (content[i][coords[i] - 1].size() == 2) {
501  pointContentVector.push_back(content[i][coords[i] - 1][1]);
502  }
503  else {
504  pointContentVector.push_back(content[i][coords[i] - 1][1]);
505  pointContentVector.push_back(content[i][coords[i] - 1][2]);
506  pointContentVector.push_back(content[i][coords[i] - 1][3]);
507  }
508  }
509 
510  // NUtils::PrintPointSafe(pointContentVector, -1);
511  Int_t nContentDims = fContent->GetNdimensions();
512  NLogTrace("NBinning::FillAll: pointContentVector dims=%zu nContentDims=%d", pointContentVector.size(),
513  nContentDims);
514 
515  auto pointContent = std::make_unique<Int_t[]>(nContentDims);
516 
517  // Int_t pointContent[nContentDims];
518  NUtils::VectorToArray(pointContentVector, pointContent.get());
519  Long64_t pointContentBin = fContent->GetBin(pointContent.get());
520 
521  // ids.push_back(pointContentBin);
522  if (def) {
523  NBinningPoint point(this);
524  fContent->GetBinContent(pointContentBin, point.GetCoords());
525  point.RecalculateStorageCoords();
526  Long64_t linBin = def->GetContent()->GetBin(point.GetStorageCoords());
527  def->GetContent()->SetBinContent(linBin, pointContentBin);
528  def->GetIds().push_back(pointContentBin);
529  }
530 
531  NLogTrace("NBinning::FillAll: Setting content bin %lld", pointContentBin);
532 
533  fContent->SetBinContent(pointContentBin, 1);
534  nBinsFilled++;
535  // NLogDebug("NBinning::FillAll: Filled bin %lld: %s", nBinsFilled,
536  // NUtils::GetCoordsString(pointContentVector, -1).c_str());
537  NLogTrace("NBinning::FillAll: Filled bin %lld: %lld", nBinsFilled, nTotalBins);
538  int refreshRate = nTotalBins / 100;
539  if (refreshRate == 0) refreshRate = nTotalBins;
540  if (nBinsFilled % (refreshRate) == 0) Ndmspc::NUtils::ProgressBar(nBinsFilled, nTotalBins, start_par, "I ");
541  // NLogDebug("NBinning::FillAll: [%3.2f%%] nBinsFilled=%lld", (double)nBinsFilled / nTotalBins * 100,
542  // nBinsFilled);
543  };
544  executor.Execute(binning_task);
545 
546  auto end_par = std::chrono::high_resolution_clock::now();
547  std::chrono::duration<double, std::milli> par_duration = end_par - start_par;
548 
549  NLogInfo("NBinning::FillAll: Filled %lld bins in %s s", nTotalBins,
550  NUtils::FormatTime(par_duration.count() / 1000).c_str());
551 
552  fMap->Reset();
553 
554  return nBinsFilled;
555 }
556 
557 bool NBinning::AddBinning(size_t id, std::vector<int> binning, size_t n)
558 {
562 
563  if (fAxes.size() == 0) {
564  NLogError("AddBinning: No axes defined !!!");
565  return false;
566  }
567 
568  if (id <= 0 || id > fAxes.size()) {
569  NLogError("AddBinning: Invalid binning id %d", id);
570  return false;
571  }
572 
573  binning.insert(binning.begin(), id);
574  Int_t * point = new Int_t[fMap->GetNdimensions()];
575  NUtils::VectorToArray(binning, point);
576  if (binning.size() == 2) {
577  point[3] = point[1];
578  point[2] = 1;
579  point[1] = 1;
580  }
581  for (size_t i = 0; i < n; i++) {
582  NLogTrace("Adding binning %d: %d %d %d %d", i, point[0], point[1], point[2], point[3]);
583  fMap->SetBinContent(point, 1);
584  point[3] += 1;
585  }
586  delete[] point;
587 
588  return true;
589 }
590 bool NBinning::AddBinningVariable(size_t id, std::vector<int> mins)
591 {
595  if (id <= 0 || id > fAxes.size()) {
596  NLogError("AddBinningVariable: Invalid binning id %d", id);
597  return false;
598  }
599 
600  // lopp over all mins and set binning
601  for (size_t i = 1; i < mins.size(); i++) {
602 
603  if (mins[i] < 1 || mins[i] > fAxes[id - 1]->GetNbins() + 1) {
604  // NLogWarning("AddBinningVariable: Invalid binning value mins=%d", mins[i]);
605  return true;
606  }
607  // if (mins[i] == fAxes[id - 1]->GetNbins() || i == mins.size() - 1) mins[i]++;
608  int rebin = mins[i] - mins[i - 1];
609  if (rebin < 1) {
610  NLogError("AddBinningVariable: Invalid binning value rebin=%d", rebin);
611  return false;
612  }
613 
614  int rebin_start = mins[i - 1] % rebin;
615  int bin = mins[i] / rebin;
616 
617  // int rebin_start = ((mins[i - 1]) % rebin) + 1;
618  // int bin = (mins[i] / rebin);
619  if (rebin == 1) {
620  rebin_start = 1;
621  bin = mins[i - 1];
622  }
623  // rebin_start + 1 is just that it looks better in the output
624  // NLogDebug("Adding partial binning %d: %d %d %d %d [%d,%d]", i - 1, id, rebin, rebin_start + 1, bin,
625  // mins[i - 1], mins[i]);
626  AddBinning(id, {rebin, rebin_start, bin}, 1);
627  }
628 
629  return true;
630 }
631 bool NBinning::AddBinningViaBinWidths(size_t id, std::vector<std::vector<int>> widths)
632 {
636  // NLogTrace("Adding binning via bin widths for id=%d", id);
637  std::vector<int> mins;
638  // Print vector of widths
639  mins.push_back(1);
640  for (auto & w : widths) {
641  TAxis * axis = fAxes[id - 1];
642  int width = w[0];
643  int nWidths = w.size() > 1 ? w[1] : axis->GetNbins() / width;
644 
645  // NLogDebug(" width=%d nWidths=%d last min=%d", width, nWidths, mins[mins.size() - 1]);
646  for (int iWidth = 0; iWidth < nWidths; iWidth++) {
647  if (mins[mins.size() - 1] > axis->GetNbins()) {
648  // NLogWarning("NBinning::AddBinningViaBinWidths: Exceeding axis nbins %d", axis->GetNbins());
649  break;
650  }
651  mins.push_back(mins[mins.size() - 1] + width);
652  // NLogDebug(" width=%d nWidths=%d iWidth=%d -> min=%d", width, nWidths, iWidth, mins[mins.size() - 1]);
653  }
654  }
655 
656  NLogTrace("NBinning::AddBinningViaBinWidths: Adding binning via bin widths: %s",
657  NUtils::GetCoordsString(mins, -1).c_str());
658 
659  return AddBinningVariable(id, mins);
660 }
661 
662 std::vector<std::vector<int>> NBinning::GetCoordsRange(std::vector<int> c) const
663 {
664  std::vector<std::vector<int>> coordsRange;
665  std::vector<int> ids;
666  std::vector<int> mins;
667  std::vector<int> maxs;
668  // int iAxis = 0;
669  bool isValid;
670  int index = 0;
671  for (size_t iAxis = 0; iAxis < fAxes.size(); iAxis++) {
672  // for (int i = 0; i < fContent->GetNdimensions(); i += 3) {
673  int min;
674  int max;
675  if (fBinningTypes[iAxis] == Binning::kSingle) {
676  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, c[index], min, max);
677  index++;
678  }
679  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
680  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], c[index], c[index + 1], c[index + 2], min, max);
681  index += 3;
682  }
683  else if (fBinningTypes[iAxis] == Binning::kUser) {
684  // isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, c[index], min, max);
685  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], fAxes[iAxis]->GetNbins(), 1, 1, min, max);
686  index++;
687  }
688  else {
689  NLogError("NBinning::GetCoordsRange: Unknown binning type %d", fBinningTypes[iAxis]);
690  continue;
691  }
692  if (!isValid) {
693  // NLogError("Cannot get axis range for axis %d", iAxis);
694  return {};
695  }
696  // print min max
697  NLogDebug("Axis %d: %s [%d,%d]", iAxis, fAxes[iAxis]->GetName(), min, max);
698  ids.push_back(iAxis); // +1 because id starts from 1
699  mins.push_back(min);
700  maxs.push_back(max);
701  }
702 
703  coordsRange.push_back(ids);
704  coordsRange.push_back(mins);
705  coordsRange.push_back(maxs);
706  return coordsRange;
707 }
708 
709 Binning NBinning::GetBinningType(size_t i) const
710 {
711  if (i >= fBinningTypes.size()) {
712  NLogError("Invalid binning type %d", i);
713  // return Binning::kSingle;
714  return Binning::kUndefined;
715  }
716  return fBinningTypes[i];
717 }
718 std::vector<std::vector<int>> NBinning::GetAxisRanges(std::vector<int> c) const
719 {
723  std::vector<std::vector<int>> axisRanges;
724 
725  bool isValid;
726  int index = 0;
727  for (size_t iAxis = 0; iAxis < fAxes.size(); iAxis++) {
728  // for (int i = 0; i < fContent->GetNdimensions(); i += 3) {
729  int min;
730  int max;
731  if (fBinningTypes[iAxis] == Binning::kSingle) {
732  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], 1, 1, c[index], min, max);
733  index++;
734  }
735  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
736  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], c[index], c[index + 1], c[index + 2], min, max);
737  index += 3;
738  }
739  else if (fBinningTypes[iAxis] == Binning::kUser) {
740  isValid = NUtils::GetAxisRangeInBase(fAxes[iAxis], fAxes[iAxis]->GetNbins(), 1, 1, min, max);
741  index++;
742  }
743  else {
744  NLogError("[NBinning::GetAxisRanges] Unknown binning type [%d]", fBinningTypes[iAxis]);
745  continue;
746  }
747  if (!isValid) {
748  // NLogError("Cannot get axis range for axis %d", iAxis);
749  return {};
750  }
751  // print min max
752  NLogTrace("Axis %d: %s [%d,%d]", iAxis, fAxes[iAxis]->GetName(), min, max);
753  axisRanges.push_back({(int)iAxis, min, max});
754  }
755 
756  return axisRanges;
757 }
758 std::vector<int> NBinning::GetAxisBinning(size_t axisId, const std::vector<int> & c) const
759 {
763  std::vector<int> binning;
764 
765  int index = 0;
766  for (size_t iAxis = 0; iAxis < fAxes.size(); iAxis++) {
767  // for (int i = 0; i < fContent->GetNdimensions(); i += 3) {
768  // int min;
769  // int max;
770  if (fBinningTypes[iAxis] == Binning::kSingle) {
771  if (iAxis == axisId) {
772  binning.push_back(1);
773  binning.push_back(1);
774  binning.push_back(c[index]);
775  break;
776  }
777  index++;
778  }
779  else if (fBinningTypes[iAxis] == Binning::kMultiple) {
780  if (iAxis == axisId) {
781  binning.push_back(c[index]);
782  binning.push_back(c[index + 1]);
783  binning.push_back(c[index + 2]);
784  break;
785  }
786  index += 3;
787  }
788  else if (fBinningTypes[iAxis] == Binning::kUser) {
789  if (iAxis == axisId) {
790  binning.push_back(c[index]);
791  binning.push_back(1);
792  binning.push_back(1);
793  break;
794  }
795  index++;
796  }
797  else {
798  NLogError("[NBinning::GetAxisBinning] Unknown binning type [%d]", fBinningTypes[iAxis]);
799  continue;
800  }
801  }
802 
803  return binning;
804 }
805 
806 bool NBinning::GetAxisRange(size_t axisId, double & min, double & max, std::vector<int> c) const
807 {
811  int minBin = 0;
812  int maxBin = 0;
813  Bool_t isValid = GetAxisRangeInBase(axisId, minBin, maxBin, c);
814 
815  min = fAxes[axisId]->GetBinLowEdge(minBin);
816  max = fAxes[axisId]->GetBinUpEdge(maxBin);
817  return isValid;
818 }
819 
820 bool NBinning::GetAxisRangeInBase(size_t axisId, int & min, int & max, std::vector<int> c) const
821 {
825  if (axisId >= fAxes.size()) {
826  NLogError("Invalid axis id %d", axisId);
827  return false;
828  }
829 
830  // Generate c if not provided
831 
832  int minBin = 0;
833  int maxBin = 0;
834  Bool_t isValid = false;
835  if (fBinningTypes[axisId] == Binning::kSingle) {
836  isValid = NUtils::GetAxisRangeInBase(fAxes[axisId], 1, 1, c[0], minBin, maxBin);
837  }
838  else if (fBinningTypes[axisId] == Binning::kMultiple) {
839  isValid = NUtils::GetAxisRangeInBase(fAxes[axisId], c[0], c[1], c[2], minBin, maxBin);
840  }
841 
842  min = minBin;
843  max = maxBin;
844  return isValid;
845 }
846 
848 {
852 
853  // TODO: Verify memery leak and its posible consequence for user
854 
855  TObjArray * axesArray = new TObjArray();
856 
857  // loop over all axes and create TObjArray
858  for (size_t i = 0; i < fAxes.size(); i++) {
859  TAxis * axis = (TAxis *)fAxes[i];
860  TAxis * axisNew = (TAxis *)axis->Clone();
861 
862  std::string name = axis->GetName();
863  NLogTrace("NBinning::GetListOfAxes(): Binning '%s': %d", name.c_str(), axis->GetNbins());
864 
865  auto bins = std::make_unique<double[]>(axis->GetNbins() + 1);
866  // double bins[axis->GetNbins() + 1];
867  int count = 0;
868  int iBin = 1; // start from bin 1
869  bins[count++] = axis->GetBinLowEdge(1);
870 
871  NBinningDef * def = GetDefinition();
872  std::map<std::string, std::vector<std::vector<int>>> definition = def->GetDefinition();
873  for (auto & v : definition.at(name)) {
874  NLogTrace(" %s", NUtils::GetCoordsString(v, -1).c_str());
875 
876  int n = v.size() > 1 ? v[1] : axis->GetNbins() / v[0];
877  for (int i = 0; i < n; i++) {
878  iBin += v[0];
879  bins[count++] = axis->GetBinLowEdge(iBin);
880  }
881  }
882  // loop over bins and print
883  for (int i = 0; i < count; i++) {
884  NLogTrace(" %s: %d %f", axis->GetName(), i + 1, bins[i]);
885  }
886  axisNew->Set(count - 1, bins.get());
887  axesArray->Add(axisNew);
888  }
889 
890  return axesArray;
891 }
892 
893 bool NBinning::SetAxisType(size_t axisId, AxisType at)
894 {
898  if (axisId >= fAxes.size()) {
899  NLogError("Invalid axis id %d", axisId);
900  return false;
901  }
902  fAxisTypes[axisId] = at;
903  return true;
904 }
905 
906 AxisType NBinning::GetAxisType(size_t i) const
907 {
911  if (i >= fAxisTypes.size()) {
912  NLogError("Invalid axis type %d", i);
913  return AxisType::kUndefined; // Undefined
914  }
915  return fAxisTypes[i];
916 }
917 char NBinning::GetAxisTypeChar(size_t i) const
918 {
919  if (i >= fAxisTypes.size()) {
920  NLogError("Invalid axis type %d", i);
921  return 'X'; // Undefined
922  }
923  switch (fAxisTypes[i]) {
924  case AxisType::kFixed: return 'F';
925  case AxisType::kVariable: return 'V';
926  case AxisType::kUndefined:
927  default: return 'X';
928  }
929 }
930 
931 std::vector<int> NBinning::GetAxisIndexes(AxisType type) const
932 {
936  std::vector<int> ids;
937  for (size_t i = 0; i < fAxes.size(); i++) {
938  if (fAxisTypes[i] == type) {
939  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
940  ids.push_back(i);
941  }
942  else {
943  NLogTrace("Axis %d: %s type=%d [not selected]", i, fAxes[i]->GetName(), fAxisTypes[i]);
944  }
945  }
946  return ids;
947 }
948 
949 std::vector<TAxis *> NBinning::GetAxesByType(AxisType type) const
950 {
954  std::vector<TAxis *> axes;
955  for (size_t i = 0; i < fAxes.size(); i++) {
956  if (fAxisTypes[i] == type) {
957  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
958  axes.push_back(fAxes[i]);
959  }
960  else {
961  NLogTrace("Axis %d: %s type=%d [not selected]", i, fAxes[i]->GetName(), fAxisTypes[i]);
962  }
963  }
964  return axes;
965 }
966 
967 std::vector<int> NBinning::GetAxisIndexesByNames(std::vector<std::string> names) const
968 {
972  std::vector<int> ids;
973  for (auto & name : names) {
974  for (size_t i = 0; i < fAxes.size(); i++) {
975  if (fAxes[i]->GetName() == name) {
976  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
977  ids.push_back(i);
978  break; // break inner loop if found
979  }
980  }
981  }
982  return ids;
983 }
984 
985 std::vector<std::string> NBinning::GetAxisNamesByType(AxisType type) const
986 {
990  std::vector<std::string> names;
991  for (size_t i = 0; i < fAxes.size(); i++) {
992  if (fAxisTypes[i] == type) {
993  NLogTrace("Axis %d: %s type=%d", i, fAxes[i]->GetName(), fAxisTypes[i]);
994  names.push_back(fAxes[i]->GetName());
995  continue;
996  }
997  else {
998  NLogTrace("Axis %d: %s type=%d [not selected]", i, fAxes[i]->GetName(), fAxisTypes[i]);
999  }
1000  }
1001  return names;
1002 }
1003 std::vector<std::string> NBinning::GetAxisNamesByIndexes(std::vector<int> ids) const
1004 {
1008  std::vector<std::string> names;
1009  for (auto & id : ids) {
1010  // FIXME: change to size_t
1011  if (id < 0 || id >= (int)fAxes.size()) {
1012  NLogError("Invalid axis id %d", id);
1013  continue;
1014  }
1015  NLogTrace("Axis %d: %s type=%d", id, fAxes[id]->GetName(), fAxisTypes[id]);
1016  names.push_back(fAxes[id]->GetName());
1017  }
1018  return names;
1019 }
1020 
1021 NBinningDef * NBinning::GetDefinition(const std::string & name)
1022 {
1023 
1027 
1028  if (name.empty()) {
1029  if (fCurrentDefinitionName.empty()) {
1030  return nullptr;
1031  }
1032  // check if current definition exists
1033  if (fDefinitions.find(fCurrentDefinitionName) == fDefinitions.end()) {
1034  NLogError("NBinning::GetDefinition: Current definition '%s' not found", fCurrentDefinitionName.c_str());
1035  return nullptr;
1036  }
1037  NLogTrace("NBinning::GetDefinition: Using current definition '%s'", fCurrentDefinitionName.c_str());
1039  }
1040 
1041  if (fDefinitions.find(name) == fDefinitions.end()) {
1042  NLogError("NBinning::GetDefinition: Definition '%s' not found", name.c_str());
1043  return nullptr;
1044  }
1045  NLogTrace("NBinning::GetDefinition: Using definition '%s'", name.c_str());
1046  fCurrentDefinitionName = name;
1047  return fDefinitions.at(name);
1048 }
1049 
1050 void NBinning::AddBinningDefinition(std::string name, std::map<std::string, std::vector<std::vector<int>>> binning,
1051  bool forceDefault)
1052 {
1056  if (fDefinitions.find(name) != fDefinitions.end()) {
1057  NLogError("Binning definition '%s' already exists", name.c_str());
1058  return;
1059  }
1060 
1061  NLogInfo("NBinning::AddBinningDefinition: Adding binning definition '%s'", name.c_str());
1062  NBinningDef * def = new NBinningDef(name, binning, this);
1063  fDefinitionNames.push_back(name);
1064  fDefinitions[name] = def;
1065  fCurrentDefinitionName = name;
1066  fMap->Reset();
1067  // loop over binning axes
1068  for (size_t i = 0; i < fAxes.size(); i++) {
1069  TAxis * axis = fAxes[i];
1070  std::string axisName = axis->GetName();
1071  // NLogDebug("Axis %zu: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i, axisName.c_str(),
1072  // axis->GetTitle(), axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
1073  if (!binning[axisName].empty()) {
1074  AddBinningViaBinWidths(i + 1, binning[axisName]);
1075  SetAxisType(i, AxisType::kVariable);
1076  // GetDefinition()[axisName] = binning[axisName];
1077  // def->SetAxisDefinition(axisName, binning[axisName]);
1078  }
1079  else {
1080  AddBinning(i + 1, {axis->GetNbins(), 1, 1}, 1);
1081  // GetDefinition()[axisName] = {{axis->GetNbins()}};
1082  // def->SetAxisDefinition(axisName, {{axis->GetNbins()}});
1083  }
1084  }
1085 
1086  // Long64_t nStart = fContent->GetNbins();
1087  // def->SetStartId(nStart);
1088  // std::vector<Long64_t> entries;
1089  Long64_t nFilled = FillAll(def);
1090  // def->Print();
1091  NLogTrace("NBinning::AddBinningDefinition: Filled %lld bins for definition '%s'", nFilled,
1092  NUtils::GetCoordsString(def->GetIds(), -1).c_str());
1093  // def->SetNEntries(nFilled);
1094 
1095  if (forceDefault || fCurrentDefinitionName.empty()) {
1096  fCurrentDefinitionName = name;
1097  NLogTrace("Set default binning definition '%s'", fCurrentDefinitionName.c_str());
1098  }
1099  else {
1100  NLogTrace("Added binning definition '%s' [not default]", name.c_str());
1101  }
1102 }
1103 
1105 {
1109 
1110  if (fPoint == nullptr) {
1111  fPoint = new NBinningPoint(this);
1112  }
1113  return fPoint;
1114 }
1115 
1116 NBinningPoint * NBinning::GetPoint(size_t id, std::string binning)
1117 {
1121 
1122  // TODO: Optimize speed here
1123 
1124  NBinningDef * def = GetDefinition(binning);
1125  if (def == nullptr) {
1126  NLogError("NBinning::FillPoint: Definition '%s' not found", binning.c_str());
1127  return nullptr;
1128  }
1129 
1130  if (fPoint == nullptr) {
1131  fPoint = new NBinningPoint(this);
1132  }
1133 
1134  Long64_t linBin = def->GetId(id);
1135  if (linBin < 0) {
1136  NLogError("NBinning::GetPoint: Invalid linear bin %lld for id=%d in definition '%s'", linBin, id, binning.c_str());
1137  return nullptr;
1138  }
1139  if (linBin >= fContent->GetNbins()) {
1140  NLogError("NBinning::GetPoint: Linear bin %lld out of range [0,%lld) for id=%d in definition '%s'", linBin,
1141  fContent->GetNbins(), id, binning.c_str());
1142  return nullptr;
1143  }
1144  fContent->GetBinContent(linBin, fPoint->GetCoords());
1146 
1147  return fPoint;
1148 }
1149 
1150 bool NBinning::SetCfg(const json & cfg)
1151 {
1155  GetPoint()->SetCfg(cfg);
1156 
1157  return true;
1158 }
1159 
1160 void NBinning::SetCurrentDefinitionName(const std::string & name)
1161 {
1166 
1167  if (name.empty()) {
1168  if (!fDefinitionNames.empty()) {
1170  NLogInfo("Binning definition name='' set to first available definition '%s'", fCurrentDefinitionName.c_str());
1171  return;
1172  }
1173  else {
1174  NLogError("Binning definition name='' and no definitions are available !!! Ignorred ...");
1175  return;
1176  }
1177  }
1178 
1179  if (fDefinitions.find(name) == fDefinitions.end()) {
1180  NLogError("Binning definition '%s' not found", name.c_str());
1181  return;
1182  }
1183 
1184  // check if name is already current
1185  if (fCurrentDefinitionName.compare(name) == 0) {
1186  NLogTrace("Binning definition '%s' is already current", name.c_str());
1187  return;
1188  }
1189 
1190  // Set current definition name
1191  fCurrentDefinitionName = name;
1192 
1193  // Reset Point
1194  if (fPoint != nullptr) {
1195  fPoint = new NBinningPoint(this);
1196  }
1197  fPoint->Reset();
1198 }
1199 
1200 } // namespace Ndmspc
Defines binning mapping and content for NDMSPC histograms.
Definition: NBinningDef.h:26
THnSparse * GetContent() const
Get the template content histogram.
Definition: NBinningDef.h:118
std::map< std::string, std::vector< std::vector< int > > > GetDefinition() const
Get the binning mapping definition.
Definition: NBinningDef.h:52
std::vector< int > GetVariableAxes() const
Get list of variable axes indices.
Definition: NBinningDef.h:71
virtual void Print(Option_t *option="") const
Print binning definition information.
void AddVariableAxis(size_t axis)
Add a variable axis index.
Definition: NBinningDef.h:77
Long64_t GetId(size_t index) const
Get bin ID at specified index.
std::vector< Long64_t > GetIds() const
Get list of bin IDs.
Definition: NBinningDef.h:93
Represents a single point in multi-dimensional binning.
Definition: NBinningPoint.h:23
bool RecalculateStorageCoords(Long64_t entry=-1, bool useBinningDefCheck=false)
Recalculate storage coordinates for the point.
Int_t * GetStorageCoords() const
Get pointer to storage coordinates array.
Definition: NBinningPoint.h:69
void SetCfg(json cfg)
Set configuration JSON object.
Int_t * GetCoords() const
Get pointer to content coordinates array.
Definition: NBinningPoint.h:57
virtual void Reset()
Reset the binning point to initial state.
NBinning object for managing multi-dimensional binning and axis definitions.
Definition: NBinning.h:45
NBinningDef * GetDefinition(const std::string &name="")
Get binning definition by name.
Definition: NBinning.cxx:1021
std::vector< std::string > GetAxisNamesByType(AxisType type) const
Get axis names by type.
Definition: NBinning.cxx:985
std::vector< int > GetAxisIndexes(AxisType type) const
Get indexes of axes by type.
Definition: NBinning.cxx:931
std::vector< std::string > GetAxisNamesByIndexes(std::vector< int > axisIds) const
Get axis names by indexes.
Definition: NBinning.cxx:1003
std::vector< AxisType > fAxisTypes
Axis types.
Definition: NBinning.h:325
std::vector< TAxis * > fAxes
List of axes.
Definition: NBinning.h:323
NBinningPoint * GetPoint()
Get the current binning point.
Definition: NBinning.cxx:1104
std::vector< int > GetAxisIndexesByNames(std::vector< std::string > axisNames) const
Get axis indexes by axis names.
Definition: NBinning.cxx:967
bool GetAxisRange(size_t axisId, double &min, double &max, std::vector< int > c) const
Get axis range for a specific axis and coordinates.
Definition: NBinning.cxx:806
std::vector< std::vector< int > > GetAxisRanges(std::vector< int > c) const
Get axis ranges for given coordinates.
Definition: NBinning.cxx:718
TObjArray * GenerateListOfAxes()
Generate a list of axes as TObjArray.
Definition: NBinning.cxx:847
bool AddBinningVariable(size_t id, std::vector< int > mins)
Add variable binning for a specific axis.
Definition: NBinning.cxx:590
NBinning()
Default constructor.
Definition: NBinning.cxx:19
virtual void Print(Option_t *option="") const
Print binning information.
Definition: NBinning.cxx:245
AxisType GetAxisType(size_t i) const
Get axis type for a specific axis.
Definition: NBinning.cxx:906
bool AddBinningViaBinWidths(size_t id, std::vector< std::vector< int >> widths)
Add binning via bin widths for a specific axis.
Definition: NBinning.cxx:631
void Initialize()
Initialize the binning object.
Definition: NBinning.cxx:90
bool SetCfg(const json &cfg)
Set configuration from JSON.
Definition: NBinning.cxx:1150
std::vector< std::string > fDefinitionNames
Binning definition names.
Definition: NBinning.h:328
THnSparse * fContent
Content histogram.
Definition: NBinning.h:322
void AddBinningDefinition(std::string name, std::map< std::string, std::vector< std::vector< int >>> binning, bool forceDefault=false)
Add a binning definition.
Definition: NBinning.cxx:1050
std::string fCurrentDefinitionName
Current definition name.
Definition: NBinning.h:326
std::map< std::string, NBinningDef * > fDefinitions
Binning definitions.
Definition: NBinning.h:327
Binning GetBinningType(size_t i) const
Get binning type for a specific axis.
Definition: NBinning.cxx:709
void PrintContent(Option_t *option="") const
Print binning content.
Definition: NBinning.cxx:341
bool GetAxisRangeInBase(size_t axisId, int &min, int &max, std::vector< int > c) const
Get axis range in base for a specific axis and coordinates.
Definition: NBinning.cxx:820
std::vector< int > GetAxisBinning(size_t axisId, const std::vector< int > &c) const
Get binning for a specific axis and coordinates.
Definition: NBinning.cxx:758
virtual ~NBinning()
Destructor.
Definition: NBinning.cxx:56
NBinningPoint * fPoint
! Binning point object
Definition: NBinning.h:329
char GetAxisTypeChar(size_t i) const
Get axis type as character for a specific axis.
Definition: NBinning.cxx:917
void Reset()
Reset the binning object to initial state.
Definition: NBinning.cxx:78
std::vector< std::vector< int > > GetCoordsRange(std::vector< int > c) const
Get coordinate ranges for given coordinates.
Definition: NBinning.cxx:662
bool SetAxisType(size_t id, AxisType type)
Set axis type for a specific axis.
Definition: NBinning.cxx:893
std::vector< TAxis * > GetAxesByType(AxisType type) const
Get axes by type.
Definition: NBinning.cxx:949
void SetCurrentDefinitionName(const std::string &name)
Set current definition name.
Definition: NBinning.cxx:1160
THnSparse * fMap
Mapping histogram.
Definition: NBinning.h:321
std::vector< Binning > fBinningTypes
Binning types.
Definition: NBinning.h:324
bool AddBinning(size_t id, std::vector< int > binning, size_t n=1)
Add binning for a specific axis.
Definition: NBinning.cxx:557
Long64_t FillAll(NBinningDef *def=nullptr)
Fill all bins according to definition.
Definition: NBinning.cxx:416
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.
static std::string FormatTime(long long seconds)
Format time in seconds to human-readable string.
Definition: NUtils.cxx:1515
static bool GetAxisRangeInBase(TAxis *a, int rebin, int rebin_start, int bin, int &min, int &max)
Get axis range in base for rebinned axis.
Definition: NUtils.cxx:1193
static void ProgressBar(int current, int total, std::string prefix="", std::string suffix="", int barWidth=50)
Display progress bar.
Definition: NUtils.cxx:1528
static std::string GetCoordsString(const std::vector< int > &coords, int index=-1, int width=0)
Get string representation of coordinates.
Definition: NUtils.cxx:1443
static void VectorToArray(std::vector< int > v1, Int_t *v2)
Convert vector to array.
Definition: NUtils.cxx:1419
static std::vector< int > ArrayToVector(Int_t *v1, int size)
Convert array to vector.
Definition: NUtils.cxx:1406