Xmipp  v3.23.11-Nereus
histogram.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
4  * Arun Kulshreshth (arun_2000_iitd@yahoo.com)
5  *
6  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307 USA
22  *
23  * All comments concerning this program package may be sent to the
24  * e-mail address 'xmipp@cnb.csic.es'
25  ***************************************************************************/
26 #include <math.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <fstream>
30 #include <algorithm>
31 
32 #include "histogram.h"
33 #include "metadata_vec.h"
34 #include "metadata_row_vec.h"
35 
36 /* ------------------------------------------------------------------------- */
37 /* HISTOGRAMS 1D */
38 /* ------------------------------------------------------------------------- */
39 /* Clear ------------------------------------------------------------------- */
41 {
42  hmin = 0;
43  hmax = 0;
44  step_size = 0;
45  istep_size = 0;
46  no_samples = 0;
48 }
49 
50 /* Assignment -------------------------------------------------------------- */
52 {
53  if (this != &H)
54  {
56  hmin = H.hmin;
57  hmax = H.hmax;
58  step_size = H.step_size;
61  }
62  return *this;
63 }
64 
65 /* Another function for assignament ---------------------------------------- */
67 {
68  *this = H;
69 }
70 /* Initialize -------------------------------------------------------------- */
71 void Histogram1D::init(double min_val, double max_val, int n_steps)
72 {
73  hmin = min_val;
74  hmax = max_val;
75  step_size = (double) (max_val - min_val) / (double) n_steps; // CO: n_steps-1->n_steps
76  istep_size = 1.0 / step_size;
78  no_samples = 0;
79 }
80 
81 /* Insert value ------------------------------------------------------------ */
82 //#define DEBUG
83 void Histogram1D::insert_value(double val)
84 {
85  int i;
86  int Xdim=(int)XSIZE(*this);
87 
88  // The following code is equivalent to val2index(val, i);
89  if (val == hmax)
90  {
91  i = Xdim - 1;
92  ++DIRECT_A1D_ELEM(*this, i);
93  ++no_samples;
94  }
95  else
96  {
97  double aux = (val - hmin) * istep_size;
98  i = (int) aux;
99 
100  if (i < 0 || i >= Xdim)
101  return; // the value is outside our scope
102 
103  ++DIRECT_A1D_ELEM(*this, i);
104  ++no_samples;
105  }
106 #ifdef DEBUG
107 
108  std::cout << " hmin " << hmin << " hmax " << hmax << " value " << val
109  << " index " << i << " (step_size= " << step_size << ")" << std::endl;
110 #endif
111 }
112 #undef DEBUG
113 
114 /* std::cout << hist ------------------------------------------------------------ */
115 std::ostream& operator <<(std::ostream &o, const Histogram1D &hist)
116 {
118  aux.resize(hist.stepNo(), 2);
120  {
121  hist.index2val(i, A2D_ELEM(aux, i, 0));
122  A2D_ELEM(aux, i, 1) = A1D_ELEM(hist, i);
123  }
124  o << aux;
125  return o;
126 }
127 
128 /* Write to file ----------------------------------------------------------- */
130  MDLabel mdlValue,
131  MDLabel mdlCount)
132 {
133  MetaDataVec auxMD;
134  MDRowVec row;
135  double auxD;
136  size_t auxT;
138  {
139  index2val(i, auxD);
140  this->index2val(i, auxD);
141  row.setValue(mdlValue, auxD);
142  auxT=(size_t)A1D_ELEM(*this, i);
143  row.setValue(mdlCount, auxT);
144  auxMD.addRow(row);
145  }
146  auxMD.write(fn);
147  // std::ofstream fh;
148  // fh.open(fn.c_str(), std::ios::out);
149  // if (!fh)
150  // REPORT_ERROR(ERR_IO_NOTOPEN, (std::string)"Histogram1D::write: File " + fn +
151  // " cannot be openned for output");
152  // fh << "; Value Count\n";
153  // fh << *this;
154  // fh.close();
155 }
156 
157 /* Percentil --------------------------------------------------------------- */
158 /* This function returns the value of the variable under which the mass% of
159  the histogram is comprised */
160 double Histogram1D::percentil(double percent_mass)
161 {
162  int i = 0;
163  double acc = 0;
164  double required_mass;
165  double percentil_i;
166  double ret_val;
167 
168  // Check it is a correct mass
169  if (percent_mass > 100)
170  REPORT_ERROR(ERR_VALUE_INCORRECT, "Asked for a percentil greater than 100");
171 
172  // Trivial cases
173  if (percent_mass == 0)
174  return (hmin);
175  if (percent_mass == 100)
176  return (hmax);
177 
178  // Any other case, find index of corresponding piece
179  required_mass = (double) no_samples * percent_mass / 100.0;
180  int N_diff_from_0 = 0;
181  while (acc < required_mass)
182  {
183  acc += A1D_ELEM(*this, i);
184  if (A1D_ELEM(*this, i) > 0)
185  N_diff_from_0++;
186  i++;
187  }
188 
189  // If the sum is just the one we want OK
190  if (acc == required_mass)
191  percentil_i = i;
192  // If there is only one sample different from 0
193  // then there is no way of setting the threshold in the middle
194  // Let's put it at the beginning of the bin
195  else if (N_diff_from_0 == 1)
196  percentil_i = i - 1;
197  // If not, then go back a step and compute which fraction of the
198  // bar is needed to finish the required mass
199  else
200  {
201  /* CO: We cannot assure that there is at least what is supposed to be
202  above this threshold. Let's move to the safe side
203  i--;
204  acc -= A1D_ELEM(*this,i);
205  percentil_i=i+(required_mass-acc)/(double) A1D_ELEM(*this,i); */
206  percentil_i = i - 1;
207  }
208 
209  // Now translate from index to range
210  index2val(percentil_i, ret_val);
211  return ret_val;
212 }
213 
214 /* Mass below -------------------------------------------------------------- */
215 double Histogram1D::mass_below(double value)
216 {
217  // Trivial cases
218  if (value <= hmin)
219  return 0;
220  if (value >= hmax)
221  return no_samples;
222 
223  // Any other case, find index of corresponding piece
224  int i = 0;
225  double acc = 0;
226  double current_value;
227  index2val(i, current_value);
228  while (current_value <= value)
229  {
230  acc += A1D_ELEM(*this, i);
231  i++;
232  index2val(i, current_value);
233  }
234  return acc;
235 }
236 
237 /* Entropy ----------------------------------------------------------------- */
238 double Histogram1D::entropy() const
239 {
241  p.initZeros(XSIZE(*this));
242  double pSum = 0;
244  {
245  A1D_ELEM(p,i) = A1D_ELEM(*this,i) + 1;
246  pSum += A1D_ELEM(p,i);
247  }
248  double entropy = 0;
249  double ipSum = 1.0 / pSum;
251  {
252  double pi = A1D_ELEM(p,i) * ipSum;
253  entropy -= pi * log(pi);
254  }
255  return entropy;
256 }
257 
258 void CDF::calculateCDF(MultidimArray<double> &V, double probStep)
259 {
260  double *ptr=&DIRECT_MULTIDIM_ELEM(V,0);
261  size_t N=MULTIDIM_SIZE(V);
262  std::sort(ptr,ptr+N);
263  minVal = ptr[0];
264  maxVal = ptr[N-1];
265 
266  int Nsteps=(int)round(1.0/probStep);
267  x.resizeNoCopy(Nsteps);
268  probXLessThanx.resizeNoCopy(Nsteps);
269  int i=0;
270  for (double p=probStep/2; p<1; p+=probStep, i++)
271  {
272  size_t idx=(size_t)round(p*N);
273  A1D_ELEM(probXLessThanx,i)=p;
274  A1D_ELEM(x,i)=ptr[idx];
275  }
276 }
277 
278 #define INTERP(x,x0,y0,xF,yF) (y0+(x-x0)*(yF-y0)/(xF-x0))
279 
280 double CDF::getProbability(double xi)
281 {
282  if (xi>maxVal)
283  return 1;
284  else if (xi<minVal)
285  return 0;
286  else
287  {
288  size_t N=XSIZE(x);
289  if (xi<DIRECT_A1D_ELEM(x,0))
290  return INTERP(xi,minVal,0.0,DIRECT_A1D_ELEM(x,0),DIRECT_A1D_ELEM(probXLessThanx,0));
291  else if (xi>DIRECT_A1D_ELEM(x,N-1))
292  return INTERP(xi,DIRECT_A1D_ELEM(x,N-1),DIRECT_A1D_ELEM(probXLessThanx,N-1),maxVal,1.0);
293  else
294  {
295  int iLeft=0;
296  int iRight=N-1;
297  while (iLeft<=iRight)
298  {
299  int iMiddle = iLeft+(iRight-iLeft)/2;
300  if (xi>=DIRECT_A1D_ELEM(x,iMiddle) && xi<=DIRECT_A1D_ELEM(x,iMiddle+1))
301  {
302  if (DIRECT_A1D_ELEM(x,iMiddle)==DIRECT_A1D_ELEM(x,iMiddle+1))
303  return 0.5*(DIRECT_A1D_ELEM(probXLessThanx,iMiddle)+DIRECT_A1D_ELEM(probXLessThanx,iMiddle+1));
304  else
305  return INTERP(xi,DIRECT_A1D_ELEM(x,iMiddle), DIRECT_A1D_ELEM(probXLessThanx,iMiddle),
306  DIRECT_A1D_ELEM(x,iMiddle+1),DIRECT_A1D_ELEM(probXLessThanx,iMiddle+1));
307  }
308  else if (xi<DIRECT_A1D_ELEM(x,iMiddle))
309  iRight=iMiddle;
310  else
311  iLeft=iMiddle;
312  }
313  // std::cout << "It should never reach here" << std::endl;
314  }
315  }
316  return 0.0;
317 }
318 
319 /* Detectability error ----------------------------------------------------- */
320 // Given two histograms (probability density functions) this function returns
321 // the detection error for using both, ie, the probability that given a sample
322 // I would assign it to class 1 when it belongs to class 2 and viceversa.
323 // This is computed by the calculation of the overlapping areas.
324 double detectability_error(const Histogram1D &h1, const Histogram1D &h2)
325 {
326  double hmin, hmax;
327  double step;
328  double v;
329  double error = 0;
330  int ih1, ih2; // Indexes within the histograms
331  double p1, p2; // Probability associated
332 
333  // Find global range
334  hmin = XMIPP_MAX(h1.hmin, h2.hmin);
335  hmax = XMIPP_MIN(h1.hmax, h2.hmax);
336  step = XMIPP_MIN(h1.step_size, h2.step_size) / 2;
337 
338  // Go over the range computing the errors
339  v = hmin;
340  int N = 0;
341  while (v <= hmax)
342  {
343  h1.val2index(v, ih1);
344  p1 = A1D_ELEM(h1, ih1) / h1.no_samples;
345  h2.val2index(v, ih2);
346  p2 = A1D_ELEM(h2, ih2) / h2.no_samples;
347  //#define DEBUG
348 #ifdef DEBUG
349 
350  std::cout << "Comparing at " << v << " (" << ih1 << ") p1=" << p1 << " p2= " << p2 << std::endl;
351  std::cout << " hmin " << hmin << " hmax " << hmax << " stepsize " << h1.step_size << std::endl;
352 #endif//;
353 
354  if (p1 != 0 && p2 != 0)
355  {
356  if (p1 > p2)
357  error += p2;
358  else
359  error += p1;
360  }
361  v += step;
362  N++;
363  }
364 
365  // Normalise such that the result is the area of a probability function
366  error *= step / (hmax - hmin);
367  error /= N;
368 #ifdef DEBUG
369 
370  std::cout << "Total error = " << error << std::endl;
371 #endif
372 
373  return error;
374 }
375 
376 /* Kullback Leibler distance ----------------------------------------------- */
377 double KLDistance(const Histogram1D& h1, const Histogram1D& h2)
378 {
379  if (XSIZE(h1) != XSIZE(h2))
380  REPORT_ERROR(ERR_MULTIDIM_SIZE,"KLDistance: Histograms of different sizes");
381 
382  double retval = 0;
384  if (A1D_ELEM(h2,i) >1e-180 && A1D_ELEM(h1,i) >1e-180)
385  retval += A1D_ELEM(h1,i) * log10(A1D_ELEM(h1,i) / A1D_ELEM(h2,i));
386  return retval;
387 }
388 
389 /* ------------------------------------------------------------------------- */
390 /* IRREGULAR HISTOGRAMS */
391 /* ------------------------------------------------------------------------- */
392 /* Initialization ---------------------------------------------------------- */
394  const MultidimArray<int> &bins)
395 {
396  int steps_no = XSIZE(bins);
397  __binsRightLimits.initZeros(steps_no);
398  __hist.initZeros(steps_no);
399 
400  int k = 0;
401  for (int i = 0; i < steps_no; ++i)
402  {
403  hist.index2val(A1D_ELEM(bins,i), A1D_ELEM(__binsRightLimits,i));
404  for (int j = k; j <= A1D_ELEM(bins,i); ++j)
405  A1D_ELEM(__hist,i) += A1D_ELEM(hist,j);
406  k = A1D_ELEM(bins,i) + 1;
407  }
408 }
409 
410 /* val2index --------------------------------------------------------------- */
411 int IrregularHistogram1D::val2Index(double value) const
412 {
413  int binsNo = XSIZE(__binsRightLimits);
414  /* Binary search is not interesting for small vectors
415  * However, we leave the code, just in case it is needed in the future
416  int ileft=1, iright=binsNo-1;
417  int iret=0;
418  if (value<=DIRECT_A1D_ELEM(__binsRightLimits,0))
419  return =0;
420  else if (value>DIRECT_A1D_ELEM(__binsRightLimits,iright))
421  return iright;
422  else
423  do
424  {
425  iret = (iright+ileft)/2;
426  if (value>DIRECT_A1D_ELEM(__binsRightLimits,iret))
427  ileft=iret+1;
428  else
429  iright=iret;
430  if (value>DIRECT_A1D_ELEM(__binsRightLimits,iret-1) &&
431  value<=DIRECT_A1D_ELEM(__binsRightLimits,iret))
432  break;
433  else if (ileft == iright)
434  {
435  iret=ileft;
436  break;
437  }
438  }
439  while (true);
440  */
441 
442  for (int i = 0; i < binsNo; ++i)
443  if (value <= DIRECT_A1D_ELEM(__binsRightLimits,i))
444  return i;
445 
446  //In case the value is greater, we return the last bin
447  return binsNo - 1;
448 }
449 
450 /* Normalization ----------------------------------------------------------- */
452 {
453  __hist *= 1.0/__hist.sum();
454 }
455 
456 /* Show -------------------------------------------------------------------- */
457 std::ostream & operator <<(std::ostream &_out,
458  const IrregularHistogram1D &_hist)
459 {
460  for (size_t i = 0; i < XSIZE(_hist.__binsRightLimits); i++)
461  _out << "\t" << _hist.__binsRightLimits(i) << "\t\t" << _hist.__hist(i)
462  << std::endl;
463  return _out;
464 }
465 
466 /* Get value --------------------------------------------------------------- */
468 {
469  return __hist;
470 }
471 
472 /* ------------------------------------------------------------------------- */
473 /* HISTOGRAMS 2D */
474 /* ------------------------------------------------------------------------- */
475 /* Clear ------------------------------------------------------------------- */
477 {
478  imin = 0;
479  imax = 0;
480  istep_size = 0;
481  jmin = 0;
482  jmax = 0;
483  jstep_size = 0;
484  no_samples = 0;
486 }
487 
488 /* Assignment -------------------------------------------------------------- */
490 {
491  if (this != &H)
492  {
494  imin = H.imin;
495  imax = H.imax;
497  jmin = H.jmin;
498  jmax = H.jmax;
499  jstep_size = H.jstep_size;
501  }
502  return *this;
503 }
504 
505 /* Another function for assignment -------------------------------------------------------------- */
507 {
508  *this = H;
509 }
510 
511 /* Initialize -------------------------------------------------------------- */
512 void Histogram2D::init(double imin_val, double imax_val, int in_steps,
513  double jmin_val, double jmax_val, int jn_steps)
514 {
515  // V axis
516  imin = imin_val;
517  imax = imax_val;
518  istep_size = (double) (imax_val - imin_val) / (double) in_steps;
519 
520  // U axis
521  jmin = jmin_val;
522  jmax = jmax_val;
523  jstep_size = (double) (jmax_val - jmin_val) / (double) jn_steps;
524 
525  initZeros(in_steps, jn_steps);
526  no_samples = 0;
527 }
528 
529 /* Insert value ------------------------------------------------------------ */
530 void Histogram2D::insert_value(double v, double u)
531 {
532  int i, j;
533  val2index(v, u, i, j);
534  if (i == -1 || j == -1)
535  return; // it is outside our scope
536  int Xdim=(int)XSIZE(*this);
537  int Ydim=(int)YSIZE(*this);
538  i = CLIP(i, 0, Ydim);
539  j = CLIP(j, 0, Xdim);
540  A2D_ELEM(*this, i, j)++;
541  no_samples++;
542 }
543 
544 /* std::cout << hist ------------------------------------------------------------ */
545 std::ostream& operator <<(std::ostream &o, const Histogram2D &hist)
546 {
548  aux.resize(hist.IstepNo() * hist.JstepNo(), 3);
549  int n = 0;
551  {
552  hist.index2val(i, j, A2D_ELEM(aux, n, 0), A2D_ELEM(aux, n, 1));
553  A2D_ELEM(aux, n, 2) = A2D_ELEM(hist, i, j);
554  n++;
555  }
556  o << aux;
557  return o;
558 }
559 
560 /* Write to file ----------------------------------------------------------- */
562 {
563  std::ofstream fh;
564  fh.open(fn.c_str(), std::ios::out);
565  if (!fh)
566  REPORT_ERROR(ERR_IO_NOTOPEN, (std::string)"histogram2D::write: File " + fn + " cannot be openned for output");
567  fh << *this;
568  fh.close();
569 }
570 
571 /* Compute histogram of multidim_array_generic ----------------------------- */
573  int no_steps)
574 {
575  double min=0., max=0.;
576  array.computeDoubleMinMax(min, max);
577  compute_hist(array, hist, min, max, no_steps);
578 }
579 
580 void compute_hist(const MultidimArrayGeneric& v, Histogram1D& hist, double min,
581  double max, int no_steps)
582 {
583  hist.init(min, max, no_steps);
584 #define COMPUTEHIST(type) compute_hist(MULTIDIM_ARRAY_TYPE(v,type),hist,min,max,no_steps);
585 
587 #undef COMPUTEHIST
588 }
double xi
void insert_value(double v, double u)
Definition: histogram.cpp:530
void val2index(double v, int &i) const
Definition: histogram.h:271
void clear()
Definition: histogram.cpp:40
#define YSIZE(v)
void min(Image< double > &op1, const Image< double > &op2)
#define A2D_ELEM(v, i, j)
double istep_size
Definition: histogram.h:705
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
double KLDistance(const Histogram1D &h1, const Histogram1D &h2)
Definition: histogram.cpp:377
int IstepNo() const
Definition: histogram.h:888
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void computeDoubleMinMax(double &minval, double &maxval) const
void init(const Histogram1D &oldHistogram, const MultidimArray< int > &bins)
Initialize class.
Definition: histogram.cpp:393
#define MULTIDIM_SIZE(v)
int JstepNo() const
Definition: histogram.h:932
double mass_below(double value)
Definition: histogram.cpp:215
double detectability_error(const Histogram1D &h1, const Histogram1D &h2)
Definition: histogram.cpp:324
void assign(const Histogram1D &H)
Definition: histogram.cpp:66
double step() const
Definition: histogram.h:328
void init(double imin_val, double imax_val, int in_steps, double jmin_val, double jmax_val, int jn_steps)
Definition: histogram.cpp:512
Histogram1D & operator=(const Histogram1D &H)
Definition: histogram.cpp:51
void setValue(const MDObject &object) override
#define A1D_ELEM(v, i)
double percentil(double percent_mass)
Definition: histogram.cpp:160
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
void index2val(double i, double j, double &v, double &u) const
Definition: histogram.h:843
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
double hmin
Definition: histogram.h:125
double jmax
Definition: histogram.h:707
double hmax
Definition: histogram.h:126
void init(double min_val, double max_val, int n_steps)
Definition: histogram.cpp:71
void calculateCDF(MultidimArray< double > &V, double probStep=0.005)
Calculate the CDF of V with a probability step of 0.005 (p is between 0 and 1)
Definition: histogram.cpp:258
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
size_t addRow(const MDRow &row) override
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
int val2Index(double value) const
Return the index corresponding to a certain value.
Definition: histogram.cpp:411
#define CLIP(x, x0, xF)
Definition: xmipp_macros.h:260
const Histogram1D & getHistogram() const
Get histogram.
Definition: histogram.cpp:467
void insert_value(double val)
Definition: histogram.cpp:83
double jstep_size
Definition: histogram.h:708
#define DIRECT_A1D_ELEM(v, i)
int stepNo() const
Definition: histogram.h:339
friend std::ostream & operator<<(std::ostream &o, const Histogram1D &hist)
Definition: histogram.cpp:115
void clear()
Definition: histogram.cpp:476
void index2val(double i, double &v) const
Definition: histogram.h:295
void log(Image< double > &op)
void compute_hist(const MultidimArrayGeneric &array, Histogram1D &hist, int no_steps)
Definition: histogram.cpp:572
double imax
Definition: histogram.h:704
#define INTERP(x, x0, y0, xF, yF)
Definition: histogram.cpp:278
#define XSIZE(v)
double getProbability(double x)
Get the probability Pr{V<=x}.
Definition: histogram.cpp:280
MultidimArray< T > & operator=(const MultidimArray< T > &op1)
void max(Image< double > &op1, const Image< double > &op2)
#define DIRECT_MULTIDIM_ELEM(v, n)
void write(const FileName &fn)
Definition: histogram.cpp:561
void log10(Image< double > &op)
void assign(const Histogram2D &H)
Definition: histogram.cpp:506
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
MultidimArray< double > __binsRightLimits
Definition: histogram.h:390
int current_value
Definition: svm-toy.cpp:54
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
File cannot be open.
Definition: xmipp_error.h:137
void error(char *s)
Definition: tools.cpp:107
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
int no_samples
Definition: histogram.h:709
int round(double x)
Definition: ap.cpp:7245
void write(const FileName &fn, MDLabel=MDL_X, MDLabel=MDL_COUNT)
Definition: histogram.cpp:129
int no_samples
Definition: histogram.h:129
#define COMPUTEHIST(type)
doublereal * u
double entropy() const
Definition: histogram.cpp:238
double step_size
Definition: histogram.h:127
double jmin
Definition: histogram.h:706
#define pi
void initZeros(const MultidimArray< T1 > &op)
void selfNormalize()
Normalize to be a probability density function.
Definition: histogram.cpp:451
Incorrect value received.
Definition: xmipp_error.h:195
int * n
MDLabel
double imin
Definition: histogram.h:703
Histogram2D & operator=(const Histogram2D &H)
Definition: histogram.cpp:489
double istep_size
Definition: histogram.h:128
Histogram1D __hist
Definition: histogram.h:389
#define SWITCHDATATYPE(datatype, OP)