ndmspc  v1.2.0-0.1.rc3
NBinningDef.cxx
1 #include "NBinningDef.h"
2 #include "TObjArray.h"
3 #include "TObject.h"
4 #include "NDimensionalExecutor.h"
5 #include "NLogger.h"
6 #include "NUtils.h"
7 #include "NBinning.h"
8 
10 ClassImp(Ndmspc::NBinningDef);
12 
13 namespace Ndmspc {
14 NBinningDef::NBinningDef(std::string name, std::map<std::string, std::vector<std::vector<int>>> definition,
15  NBinning * binning)
16  : TObject(), fBinning(binning), fName(name), fDefinition(definition)
17 {
21 
22  // TODO: build vector of TAxis from the definition
23  // Print definition
24  // for (const auto & kv : fDefinition) {
25  // NLogDebug("NBinningDef: Binning '%s': %zu entries", kv.first.c_str(), kv.second.size());
26  // for (const auto & v : kv.second) {
27  // NLogDebug(" %s", NUtils::GetCoordsString(v, -1).c_str());
28  // }
29  // }
30 
31  if (binning == nullptr) {
32  // NLogError("NBinningDef: Binning is nullptr");
33  return;
34  }
35 
36  std::vector<TAxis *> axes = binning->GetAxes();
37  for (size_t i = 0; i < axes.size(); i++) {
38  TAxis * axis = axes[i];
39  std::string axisName = axis->GetName();
40  // NLogDebug("NBinningDef::NBinningDef: Axis %zu: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i,
41  // axisName.c_str(),
42  // axis->GetTitle(), axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
43  if (fDefinition[axisName].empty()) {
44  SetAxisDefinition(axisName, {{axis->GetNbins()}});
45  }
46  }
47 
48  int dims = axes.size();
49  Int_t * nbins = new Int_t[dims];
50  Double_t * xmin = new Double_t[dims];
51  Double_t * xmax = new Double_t[dims];
52 
53  // fContent = new THnSparseD("content", "content", axes.size());
54  TObjArray * cAxes = new TObjArray();
55 
56  // loop over all axes and create TObjArray
57  for (int i = 0; i < dims; i++) {
58  TAxis * axis = (TAxis *)axes[i];
59  TAxis * axisNew = (TAxis *)axis->Clone();
60 
61  std::string name = axis->GetName();
62  NLogTrace("NBinningDef: Binning '%s': %d", name.c_str(), axis->GetNbins());
63 
64  auto bins = std::make_unique<double[]>(axis->GetNbins() + 1);
65  // double bins[axis->GetNbins() + 1];
66  int count = 0;
67  bins[count++] = axis->GetBinLowEdge(1);
68 
69  int iBin = 0;
70  std::map<std::string, std::vector<std::vector<int>>> definition = GetDefinition();
71  for (auto & v : definition.at(name)) {
72  // NLogDebug(" %s", NUtils::GetCoordsString(v, -1).c_str());
73 
74  int n = v.size() > 1 ? v[1] : axis->GetNbins() / v[0];
75  for (int i = 0; i < n; i++) {
76  iBin += v[0];
77  if (iBin > axis->GetNbins()) {
78  break;
79  }
80  bins[count++] = axis->GetBinUpEdge(iBin);
81  }
82  }
83  // loop over bins and print
84  // for (int i = 0; i < count; i++) {
85  // NLogDebug(" %s: %d %f", axis->GetName(), i + 1, bins[i]);
86  // }
87  axisNew->Set(count - 1, bins.get());
88  cAxes->Add(axisNew);
89  }
90 
91  for (int i = 0; i < cAxes->GetEntries(); i++) {
92  TAxis * axis = (TAxis *)cAxes->At(i);
93  nbins[i] = axis->GetNbins();
94  xmin[i] = 0;
95  xmax[i] = axis->GetNbins();
96  }
97  fContent = new THnSparseL("content", "content", dims, nbins, xmin, xmax);
98  // NLogInfo("---------- NBinningDef::NBinningDef: Created content THnSparse with %d dimensions", dims);
99 
100  for (int i = 0; i < cAxes->GetEntries(); i++) {
101  TAxis * axis = (TAxis *)cAxes->At(i);
102  TAxis * axisContent = fContent->GetAxis(i);
103  axisContent->SetName(axis->GetName());
104  axisContent->SetTitle(axis->GetTitle());
105  if (axis->IsVariableBinSize()) {
106  axisContent->Set(fContent->GetAxis(i)->GetNbins(), axis->GetXbins()->GetArray());
107  }
108  else {
109  axisContent->Set(axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
110  }
111 
112  if (axes[i]->IsAlphanumeric()) {
113  for (int b = 1; b <= axis->GetNbins(); b++) {
114  NLogTrace("NBinningDef::NBinningDef: Setting bin label for axis '%s' bin %d: '%s'", axis->GetName(), b,
115  axis->GetBinLabel(b));
116  axisContent->SetBinLabel(b, axes[i]->GetBinLabel(b));
117  }
118  }
119  }
120 
121  for (size_t i = 0; i < fBinning->GetAxes().size(); i++) {
122  TAxis * a = fBinning->GetAxes()[i];
123  if (a == nullptr) {
124  NLogError("NBinningPoint::GetTitle: Axis %d is nullptr !!!", i);
125  continue;
126  }
127  }
128  // cleanup cAxes
129  for (int i = 0; i < cAxes->GetEntries(); i++) {
130  TAxis * axis = (TAxis *)cAxes->At(i);
131  delete axis;
132  }
133  delete[] nbins;
134  delete[] xmin;
135  delete[] xmax;
136  delete cAxes;
137 }
139 {
143  delete fContent;
144 }
145 
146 void NBinningDef::Print(Option_t * option) const
147 {
150 
151  NLogInfo("NBinningDef: name='%s' %zu axes with %zu entries : %s", fName.c_str(), fDefinition.size(), fIds.size(),
152  NUtils::GetCoordsString(fIds, -1).c_str());
153 
154  std::string axesStr;
155  // loop over variable axes and build string
156  for (size_t i = 0; i < fVariableAxes.size(); i++) {
157  axesStr += fBinning->GetAxes()[fVariableAxes[i]]->GetName();
158  if (i < fVariableAxes.size() - 1) {
159  axesStr += ",";
160  }
161  }
162 
163  NLogInfo(" axis ids='%s' names='[%s]'", NUtils::GetCoordsString(fVariableAxes).c_str(), axesStr.c_str());
164 
165  TString opt = option;
166  opt.ToUpper();
167  if (opt.Contains("A")) {
168  // loop over content dimensions and print name title
169  for (int i = 0; i < fContent->GetNdimensions(); i++) {
170  std::string name = fContent->GetAxis(i)->GetName();
171  NLogInfo(" [%d] name='%s' title='%s' nbins=%d min=%.3f max=%.3f base: nbins=%d", i,
172  fContent->GetAxis(i)->GetName(), fContent->GetAxis(i)->GetTitle(), fContent->GetAxis(i)->GetNbins(),
173  fContent->GetAxis(i)->GetXmin(), fContent->GetAxis(i)->GetXmax(),
174  fDefinition.at(fContent->GetAxis(i)->GetName())[0][0]);
175  }
176  }
177 }
178 
179 Long64_t NBinningDef::GetId(size_t index) const
180 {
184 
185  if (index >= fIds.size()) {
186  NLogError("NBinningDef::GetId: Index %d is out of range [0, %zu)", index, fIds.size());
187  return -1;
188  }
189  return fIds[index];
190 }
191 
193 {
197 
198  fIds.clear();
199  Int_t * c = new Int_t[fContent->GetNdimensions()];
200  auto task = [this, c](const std::vector<int> & coords) {
201  NLogTrace("NBinningDef::RefreshIdsFromContent: Processing coordinates %s", NUtils::GetCoordsString(coords).c_str());
202 
203  for (int i = 0; i < fContent->GetNdimensions(); i++) {
204  c[i] = coords[i];
205  }
206 
207  Long64_t id = fContent->GetBinContent(c);
208  if (id > 0) {
209  NLogTrace("NBinningDef::RefreshIdsFromContent: -> Bin content: %lld", id - 1);
210  fIds.push_back(id - 1);
211  }
212  };
213 
214  std::vector<int> mins(fContent->GetNdimensions(), 1);
215  std::vector<int> maxs(fContent->GetNdimensions());
216  for (int i = 0; i < fContent->GetNdimensions(); i++) {
217  TAxis * axis = fContent->GetAxis(i);
218  NLogTrace("NBinningDef::RefreshIdsFromContent: Axis %d: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i,
219  axis->GetName(), axis->GetTitle(), axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
220  maxs[i] = axis->GetNbins();
221  }
222 
223  NDimensionalExecutor executor(mins, maxs);
224  executor.Execute(task);
225  delete[] c;
226 }
227 
229 {
233 
234  // print all ids
235  NLogTrace("NBinningDef::RefreshContentfomIds: Refreshing content from %zu IDs: %s", fIds.size(),
236  NUtils::GetCoordsString(fIds, -1).c_str());
237 
238  fContent->Reset();
239  // loop over all ids and set content
240  Long64_t id;
241  for (size_t i = 0; i < fIds.size(); ++i) {
242  id = fIds[i];
244  fContent->SetBinContent(fBinning->GetPoint()->GetStorageCoords(), id + 1);
245  }
246  Int_t * c = new Int_t[fContent->GetNdimensions()];
247  std::vector<Long64_t> newIds;
248  fIds.clear();
249  auto task = [this, &newIds, c](const std::vector<int> & coords) {
250  NLogTrace("NBinningDef::RefreshContentfomIds: Processing coordinates %s", NUtils::GetCoordsString(coords).c_str());
251 
252  for (int i = 0; i < fContent->GetNdimensions(); i++) {
253  c[i] = coords[i];
254  }
255 
256  Long64_t id = fContent->GetBinContent(c);
257 
258  // FIXME: This is a workaround to skip empty bins after first filled one
259  // if (id == 0 && fIds.size() > 0) return; // skip empty bins after first filled one
260  // it should be ok now
261  if (id > 0) {
262  NLogTrace("NBinningDef::RefreshContentfomIds: -> Bin content: %lld", id - 1);
263  fIds.push_back(id - 1);
264  }
265  };
266 
267  std::vector<int> mins(fContent->GetNdimensions(), 1);
268  std::vector<int> maxs(fContent->GetNdimensions());
269  for (int i = 0; i < fContent->GetNdimensions(); i++) {
270  TAxis * axis = fContent->GetAxis(i);
271  NLogTrace("NBinningDef::RefreshContentfomIds: Axis %d: name='%s' title='%s' nbins=%d min=%.3f max=%.3f", i,
272  axis->GetName(), axis->GetTitle(), axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
273  maxs[i] = axis->GetNbins();
274  }
275 
276  NDimensionalExecutor executor(mins, maxs);
277  executor.Execute(task);
278  delete[] c;
279 }
280 } // namespace Ndmspc
Defines binning mapping and content for NDMSPC histograms.
Definition: NBinningDef.h:26
std::vector< int > fVariableAxes
List of variable axes indices in the content histogram.
Definition: NBinningDef.h:130
void SetAxisDefinition(std::string axisName, const std::vector< std::vector< int >> &d)
Set axis definition for a specific axis.
Definition: NBinningDef.h:65
std::map< std::string, std::vector< std::vector< int > > > GetDefinition() const
Get the binning mapping definition.
Definition: NBinningDef.h:52
NBinning * fBinning
Pointer to the parent binning.
Definition: NBinningDef.h:127
virtual void Print(Option_t *option="") const
Print binning definition information.
virtual ~NBinningDef()
Destructor.
std::string fName
Name of the binning definition.
Definition: NBinningDef.h:128
void RefreshIdsFromContent()
Refresh bin IDs from content histogram.
std::vector< Long64_t > fIds
List of IDs for the binning definition.
Definition: NBinningDef.h:131
std::map< std::string, std::vector< std::vector< int > > > fDefinition
Binning mapping definition.
Definition: NBinningDef.h:129
Long64_t GetId(size_t index) const
Get bin ID at specified index.
void RefreshContentFromIds()
Refresh content histogram from bin IDs.
NBinningDef(std::string name="default", std::map< std::string, std::vector< std::vector< int >>> definition={}, NBinning *binning=nullptr)
Constructor.
Definition: NBinningDef.cxx:14
THnSparse * fContent
Template histogram for the binning definition.
Definition: NBinningDef.h:132
Int_t * GetStorageCoords() const
Get pointer to storage coordinates array.
Definition: NBinningPoint.h:67
bool SetPointContentFromLinearIndex(Long64_t linBin, bool checkBinningDef=false)
Set point content from linear index.
NBinning object for managing multi-dimensional binning and axis definitions.
Definition: NBinning.h:45
NBinningPoint * GetPoint()
Get the current binning point.
Definition: NBinning.cxx:1128
std::vector< TAxis * > GetAxes() const
Get vector of axis pointers.
Definition: NBinning.h:223
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 GetCoordsString(const std::vector< int > &coords, int index=-1, int width=0)
Get string representation of coordinates.
Definition: NUtils.cxx:1588