xref: /petsc/src/sys/classes/draw/utils/hists.c (revision f1580f4e3ce5d5b2393648fd039d0d41b440385d)
1 
2 /*
3   Contains the data structure for plotting a histogram in a window with an axis.
4 */
5 #include <petscdraw.h>               /*I "petscdraw.h" I*/
6 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
7 #include <petscviewer.h>             /*I "petscviewer.h" I*/
8 
9 PetscClassId PETSC_DRAWHG_CLASSID = 0;
10 
11 struct _p_PetscDrawHG {
12   PETSCHEADER(int);
13   PetscErrorCode (*destroy)(PetscDrawSP);
14   PetscErrorCode (*view)(PetscDrawSP, PetscViewer);
15   PetscDraw     win;
16   PetscDrawAxis axis;
17   PetscReal     xmin, xmax;
18   PetscReal     ymin, ymax;
19   int           numBins;
20   int           maxBins;
21   PetscReal    *bins;
22   int           numValues;
23   int           maxValues;
24   PetscReal    *values;
25   int           color;
26   PetscBool     calcStats;
27   PetscBool     integerBins;
28 };
29 
30 #define CHUNKSIZE 100
31 
32 /*@C
33    PetscDrawHGCreate - Creates a histogram data structure.
34 
35    Collective on draw
36 
37    Input Parameters:
38 +  draw  - The window where the graph will be made
39 -  bins - The number of bins to use
40 
41    Output Parameters:
42 .  hist - The histogram context
43 
44    Notes:
45     The difference between a bar chart, `PetscDrawBar`, and a histogram, `PetscDrawHG`, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP
46 
47    The histogram is only displayed when `PetscDrawHGDraw()` is called.
48 
49    The MPI communicator that owns the `PetscDraw` owns this `PetscDrawHG`, but the calls to set options and add data are ignored on all processes except the
50    zeroth MPI process in the communicator. All MPI ranks in the communicator must call `PetscDrawHGDraw()` to display the updated graph.
51 
52    Level: intermediate
53 
54 .seealso: `PetscDrawHGDestroy()`, `PetscDrawHG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawSPCreate()`, `PetscDrawSP`,
55           `PetscDrawHGSetNumberBins()`, `PetscDrawHGReset()`, `PetscDrawHGAddValue()`, `PetscDrawHGDraw()`, `PetscDrawHGSave()`, `PetscDrawHGView()`, `PetscDrawHGSetColor()`,
56           `PetscDrawHGSetLimits()`, `PetscDrawHGCalcStats()`, `PetscDrawHGIntegerBins()`, `PetscDrawHGGetAxis()`, `PetscDrawAxis`, `PetscDrawHGGetDraw()`
57 @*/
58 PetscErrorCode PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist) {
59   PetscDrawHG h;
60 
61   PetscFunctionBegin;
62   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
63   PetscValidLogicalCollectiveInt(draw, bins, 2);
64   PetscValidPointer(hist, 3);
65 
66   PetscCall(PetscHeaderCreate(h, PETSC_DRAWHG_CLASSID, "DrawHG", "Histogram", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawHGDestroy, NULL));
67   PetscCall(PetscLogObjectParent((PetscObject)draw, (PetscObject)h));
68 
69   PetscCall(PetscObjectReference((PetscObject)draw));
70   h->win = draw;
71 
72   h->view    = NULL;
73   h->destroy = NULL;
74   h->color   = PETSC_DRAW_GREEN;
75   h->xmin    = PETSC_MAX_REAL;
76   h->xmax    = PETSC_MIN_REAL;
77   h->ymin    = 0.;
78   h->ymax    = 1.;
79   h->numBins = bins;
80   h->maxBins = bins;
81 
82   PetscCall(PetscMalloc1(h->maxBins, &h->bins));
83 
84   h->numValues   = 0;
85   h->maxValues   = CHUNKSIZE;
86   h->calcStats   = PETSC_FALSE;
87   h->integerBins = PETSC_FALSE;
88 
89   PetscCall(PetscMalloc1(h->maxValues, &h->values));
90   PetscCall(PetscLogObjectMemory((PetscObject)h, (h->maxBins + h->maxValues) * sizeof(PetscReal)));
91 
92   PetscCall(PetscDrawAxisCreate(draw, &h->axis));
93   PetscCall(PetscLogObjectParent((PetscObject)h, (PetscObject)h->axis));
94 
95   *hist = h;
96   PetscFunctionReturn(0);
97 }
98 
99 /*@
100    PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn in the histogram
101 
102    Logically Collective on hist
103 
104    Input Parameters:
105 +  hist - The histogram context.
106 -  bins  - The number of bins.
107 
108    Level: intermediate
109 
110 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGIntegerBins()`
111 @*/
112 PetscErrorCode PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins) {
113   PetscFunctionBegin;
114   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
115   PetscValidLogicalCollectiveInt(hist, bins, 2);
116 
117   if (hist->maxBins < bins) {
118     PetscCall(PetscFree(hist->bins));
119     PetscCall(PetscMalloc1(bins, &hist->bins));
120     PetscCall(PetscLogObjectMemory((PetscObject)hist, (bins - hist->maxBins) * sizeof(PetscReal)));
121     hist->maxBins = bins;
122   }
123   hist->numBins = bins;
124   PetscFunctionReturn(0);
125 }
126 
127 /*@
128   PetscDrawHGReset - Clears histogram to allow for reuse with new data.
129 
130   Logically Collective on hist
131 
132   Input Parameter:
133 . hist - The histogram context.
134 
135   Level: intermediate
136 
137 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`
138 @*/
139 PetscErrorCode PetscDrawHGReset(PetscDrawHG hist) {
140   PetscFunctionBegin;
141   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
142 
143   hist->xmin      = PETSC_MAX_REAL;
144   hist->xmax      = PETSC_MIN_REAL;
145   hist->ymin      = 0.0;
146   hist->ymax      = 0.0;
147   hist->numValues = 0;
148   PetscFunctionReturn(0);
149 }
150 
151 /*@C
152   PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
153 
154   Collective on hist
155 
156   Input Parameter:
157 . hist - The histogram context
158 
159   Level: intermediate
160 
161 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`
162 @*/
163 PetscErrorCode PetscDrawHGDestroy(PetscDrawHG *hist) {
164   PetscFunctionBegin;
165   if (!*hist) PetscFunctionReturn(0);
166   PetscValidHeaderSpecific(*hist, PETSC_DRAWHG_CLASSID, 1);
167   if (--((PetscObject)(*hist))->refct > 0) {
168     *hist = NULL;
169     PetscFunctionReturn(0);
170   }
171 
172   PetscCall(PetscFree((*hist)->bins));
173   PetscCall(PetscFree((*hist)->values));
174   PetscCall(PetscDrawAxisDestroy(&(*hist)->axis));
175   PetscCall(PetscDrawDestroy(&(*hist)->win));
176   PetscCall(PetscHeaderDestroy(hist));
177   PetscFunctionReturn(0);
178 }
179 
180 /*@
181   PetscDrawHGAddValue - Adds another value to the histogram.
182 
183   Logically Collective on hist
184 
185   Input Parameters:
186 + hist  - The histogram
187 - value - The value
188 
189   Level: intermediate
190 
191 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`, `PetscDrawHGReset()`
192 @*/
193 PetscErrorCode PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value) {
194   PetscFunctionBegin;
195   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
196 
197   /* Allocate more memory if necessary */
198   if (hist->numValues >= hist->maxValues) {
199     PetscReal *tmp;
200 
201     PetscCall(PetscMalloc1(hist->maxValues + CHUNKSIZE, &tmp));
202     PetscCall(PetscLogObjectMemory((PetscObject)hist, CHUNKSIZE * sizeof(PetscReal)));
203     PetscCall(PetscArraycpy(tmp, hist->values, hist->maxValues));
204     PetscCall(PetscFree(hist->values));
205 
206     hist->values = tmp;
207     hist->maxValues += CHUNKSIZE;
208   }
209   /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
210      stated convention of using half-open intervals (always the way to go) */
211   if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
212     hist->xmin = value;
213     hist->xmax = value;
214 #if 1
215   } else {
216     /* Update limits */
217     if (value > hist->xmax) hist->xmax = value;
218     if (value < hist->xmin) hist->xmin = value;
219 #else
220   } else if (hist->numValues == 1) {
221     /* Update limits -- We need to overshoot the largest value somewhat */
222     if (value > hist->xmax) hist->xmax = value + 0.001 * (value - hist->xmin) / hist->numBins;
223     if (value < hist->xmin) {
224       hist->xmin = value;
225       hist->xmax = hist->xmax + 0.001 * (hist->xmax - hist->xmin) / hist->numBins;
226     }
227   } else {
228     /* Update limits -- We need to overshoot the largest value somewhat */
229     if (value > hist->xmax) hist->xmax = value + 0.001 * (hist->xmax - hist->xmin) / hist->numBins;
230     if (value < hist->xmin) hist->xmin = value;
231 #endif
232   }
233 
234   hist->values[hist->numValues++] = value;
235   PetscFunctionReturn(0);
236 }
237 
238 /*@
239   PetscDrawHGDraw - Redraws a histogram.
240 
241   Collective on hist
242 
243   Input Parameter:
244 . hist - The histogram context
245 
246   Level: intermediate
247 
248 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`, `PetscDrawHGReset()`
249 @*/
250 PetscErrorCode PetscDrawHGDraw(PetscDrawHG hist) {
251   PetscDraw   draw;
252   PetscBool   isnull;
253   PetscReal   xmin, xmax, ymin, ymax, *bins, *values, binSize, binLeft, binRight, maxHeight, mean, var;
254   char        title[256];
255   char        xlabel[256];
256   PetscInt    numBins, numBinsOld, numValues, initSize, i, p, bcolor, color;
257   PetscMPIInt rank;
258 
259   PetscFunctionBegin;
260   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
261   PetscCall(PetscDrawIsNull(hist->win, &isnull));
262   if (isnull) PetscFunctionReturn(0);
263   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)hist), &rank));
264 
265   if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(0);
266   if (hist->numValues < 1) PetscFunctionReturn(0);
267 
268   color = hist->color;
269   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK + 1;
270   else bcolor = color;
271 
272   xmin      = hist->xmin;
273   xmax      = hist->xmax;
274   ymin      = hist->ymin;
275   ymax      = hist->ymax;
276   numValues = hist->numValues;
277   values    = hist->values;
278   mean      = 0.0;
279   var       = 0.0;
280 
281   draw = hist->win;
282   PetscCall(PetscDrawCheckResizedWindow(draw));
283   PetscCall(PetscDrawClear(draw));
284 
285   if (xmin == xmax) {
286     /* Calculate number of points in each bin */
287     bins    = hist->bins;
288     bins[0] = 0.;
289     for (p = 0; p < numValues; p++) {
290       if (values[p] == xmin) bins[0]++;
291       mean += values[p];
292       var += values[p] * values[p];
293     }
294     maxHeight = bins[0];
295     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
296     xmax = xmin + 1;
297     PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
298     if (hist->calcStats) {
299       mean /= numValues;
300       if (numValues > 1) var = (var - numValues * mean * mean) / (numValues - 1);
301       else var = 0.0;
302       PetscCall(PetscSNPrintf(title, 256, "Mean: %g  Var: %g", (double)mean, (double)var));
303       PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
304       PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
305     }
306     PetscCall(PetscDrawAxisDraw(hist->axis));
307     PetscDrawCollectiveBegin(draw);
308     if (rank == 0) { /* Draw bins */
309       binLeft  = xmin;
310       binRight = xmax;
311       PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[0], bcolor, bcolor, bcolor, bcolor));
312       PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[0], PETSC_DRAW_BLACK));
313       PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[0], PETSC_DRAW_BLACK));
314       PetscCall(PetscDrawLine(draw, binLeft, bins[0], binRight, bins[0], PETSC_DRAW_BLACK));
315     }
316     PetscDrawCollectiveEnd(draw);
317   } else {
318     numBins    = hist->numBins;
319     numBinsOld = hist->numBins;
320     if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
321       initSize = (int)((int)xmax - xmin) / numBins;
322       while (initSize * numBins != (int)xmax - xmin) {
323         initSize = PetscMax(initSize - 1, 1);
324         numBins  = (int)((int)xmax - xmin) / initSize;
325         PetscCall(PetscDrawHGSetNumberBins(hist, numBins));
326       }
327     }
328     binSize = (xmax - xmin) / numBins;
329     bins    = hist->bins;
330 
331     PetscCall(PetscArrayzero(bins, numBins));
332 
333     maxHeight = 0.0;
334     for (i = 0; i < numBins; i++) {
335       binLeft  = xmin + binSize * i;
336       binRight = xmin + binSize * (i + 1);
337       for (p = 0; p < numValues; p++) {
338         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
339         /* Handle last bin separately */
340         if ((i == numBins - 1) && (values[p] == binRight)) bins[i]++;
341         if (!i) {
342           mean += values[p];
343           var += values[p] * values[p];
344         }
345       }
346       maxHeight = PetscMax(maxHeight, bins[i]);
347     }
348     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
349 
350     PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
351     if (hist->calcStats) {
352       mean /= numValues;
353       if (numValues > 1) var = (var - numValues * mean * mean) / (numValues - 1);
354       else var = 0.0;
355       PetscCall(PetscSNPrintf(title, 256, "Mean: %g  Var: %g", (double)mean, (double)var));
356       PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
357       PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
358     }
359     PetscCall(PetscDrawAxisDraw(hist->axis));
360     PetscDrawCollectiveBegin(draw);
361     if (rank == 0) { /* Draw bins */
362       for (i = 0; i < numBins; i++) {
363         binLeft  = xmin + binSize * i;
364         binRight = xmin + binSize * (i + 1);
365         PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[i], bcolor, bcolor, bcolor, bcolor));
366         PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[i], PETSC_DRAW_BLACK));
367         PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[i], PETSC_DRAW_BLACK));
368         PetscCall(PetscDrawLine(draw, binLeft, bins[i], binRight, bins[i], PETSC_DRAW_BLACK));
369         if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++;
370         if (bcolor > PETSC_DRAW_BASIC_COLORS - 1) bcolor = PETSC_DRAW_BLACK + 1;
371       }
372     }
373     PetscDrawCollectiveEnd(draw);
374     PetscCall(PetscDrawHGSetNumberBins(hist, numBinsOld));
375   }
376 
377   PetscCall(PetscDrawFlush(draw));
378   PetscCall(PetscDrawPause(draw));
379   PetscFunctionReturn(0);
380 }
381 
382 /*@
383   PetscDrawHGSave - Saves a drawn image
384 
385   Collective on hg
386 
387   Input Parameter:
388 . hist - The histogram context
389 
390   Level: intermediate
391 
392 .seealso: `PetscDrawSave()`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`
393 @*/
394 PetscErrorCode PetscDrawHGSave(PetscDrawHG hg) {
395   PetscFunctionBegin;
396   PetscValidHeaderSpecific(hg, PETSC_DRAWHG_CLASSID, 1);
397   PetscCall(PetscDrawSave(hg->win));
398   PetscFunctionReturn(0);
399 }
400 
401 /*@
402   PetscDrawHGView - Prints the histogram information to a viewer
403 
404   Not collective
405 
406   Input Parameter:
407 . hist - The histogram context
408 
409   Level: beginner
410 
411 .seealso: `PetscDrawHG`, `PetscViewer`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`
412 @*/
413 PetscErrorCode PetscDrawHGView(PetscDrawHG hist, PetscViewer viewer) {
414   PetscReal xmax, xmin, *bins, *values, binSize, binLeft, binRight, mean, var;
415   PetscInt  numBins, numBinsOld, numValues, initSize, i, p;
416 
417   PetscFunctionBegin;
418   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
419 
420   if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(0);
421   if (hist->numValues < 1) PetscFunctionReturn(0);
422 
423   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist), &viewer));
424   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)hist, viewer));
425   xmax      = hist->xmax;
426   xmin      = hist->xmin;
427   numValues = hist->numValues;
428   values    = hist->values;
429   mean      = 0.0;
430   var       = 0.0;
431   if (xmax == xmin) {
432     /* Calculate number of points in the bin */
433     bins    = hist->bins;
434     bins[0] = 0.;
435     for (p = 0; p < numValues; p++) {
436       if (values[p] == xmin) bins[0]++;
437       mean += values[p];
438       var += values[p] * values[p];
439     }
440     /* Draw bins */
441     PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]));
442   } else {
443     numBins    = hist->numBins;
444     numBinsOld = hist->numBins;
445     if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
446       initSize = (int)((int)xmax - xmin) / numBins;
447       while (initSize * numBins != (int)xmax - xmin) {
448         initSize = PetscMax(initSize - 1, 1);
449         numBins  = (int)((int)xmax - xmin) / initSize;
450         PetscCall(PetscDrawHGSetNumberBins(hist, numBins));
451       }
452     }
453     binSize = (xmax - xmin) / numBins;
454     bins    = hist->bins;
455 
456     /* Calculate number of points in each bin */
457     PetscCall(PetscArrayzero(bins, numBins));
458     for (i = 0; i < numBins; i++) {
459       binLeft  = xmin + binSize * i;
460       binRight = xmin + binSize * (i + 1);
461       for (p = 0; p < numValues; p++) {
462         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
463         /* Handle last bin separately */
464         if ((i == numBins - 1) && (values[p] == binRight)) bins[i]++;
465         if (!i) {
466           mean += values[p];
467           var += values[p] * values[p];
468         }
469       }
470     }
471     /* Draw bins */
472     for (i = 0; i < numBins; i++) {
473       binLeft  = xmin + binSize * i;
474       binRight = xmin + binSize * (i + 1);
475       PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", (int)i, (double)binLeft, (double)binRight, (double)bins[i]));
476     }
477     PetscCall(PetscDrawHGSetNumberBins(hist, numBinsOld));
478   }
479 
480   if (hist->calcStats) {
481     mean /= numValues;
482     if (numValues > 1) var = (var - numValues * mean * mean) / (numValues - 1);
483     else var = 0.0;
484     PetscCall(PetscViewerASCIIPrintf(viewer, "Mean: %g  Var: %g\n", (double)mean, (double)var));
485     PetscCall(PetscViewerASCIIPrintf(viewer, "Total: %" PetscInt_FMT "\n", numValues));
486   }
487   PetscFunctionReturn(0);
488 }
489 
490 /*@
491   PetscDrawHGSetColor - Sets the color the bars will be drawn with.
492 
493   Logically Collective on hist
494 
495   Input Parameters:
496 + hist - The histogram context
497 - color - one of the colors defined in petscdraw.h or `PETSC_DRAW_ROTATE` to make each bar a
498           different color
499 
500   Level: intermediate
501 
502 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
503 @*/
504 PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color) {
505   PetscFunctionBegin;
506   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
507 
508   hist->color = color;
509   PetscFunctionReturn(0);
510 }
511 
512 /*@
513   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
514   points are added after this call, the limits will be adjusted to
515   include those additional points.
516 
517   Logically Collective on hist
518 
519   Input Parameters:
520 + hist - The histogram context
521 - x_min,x_max,y_min,y_max - The limits
522 
523   Level: intermediate
524 
525 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
526 @*/
527 PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max) {
528   PetscFunctionBegin;
529   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
530 
531   hist->xmin = x_min;
532   hist->xmax = x_max;
533   hist->ymin = y_min;
534   hist->ymax = y_max;
535   PetscFunctionReturn(0);
536 }
537 
538 /*@
539   PetscDrawHGCalcStats - Turns on calculation of descriptive statistics associated with the histogram
540 
541   Not collective
542 
543   Input Parameters:
544 + hist - The histogram context
545 - calc - Flag for calculation
546 
547   Level: intermediate
548 
549 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`
550 @*/
551 PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc) {
552   PetscFunctionBegin;
553   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
554 
555   hist->calcStats = calc;
556   PetscFunctionReturn(0);
557 }
558 
559 /*@
560   PetscDrawHGIntegerBins - Turns on integer width bins
561 
562   Not collective
563 
564   Input Parameters:
565 + hist - The histogram context
566 - ints - Flag for integer width bins
567 
568   Level: intermediate
569 
570 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`
571 @*/
572 PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints) {
573   PetscFunctionBegin;
574   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
575 
576   hist->integerBins = ints;
577   PetscFunctionReturn(0);
578 }
579 
580 /*@C
581   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
582   This is useful if one wants to change some axis property, such as
583   labels, color, etc. The axis context should not be destroyed by the
584   application code.
585 
586   Not Collective, axis is parallel if hist is parallel
587 
588   Input Parameter:
589 . hist - The histogram context
590 
591   Output Parameter:
592 . axis - The axis context
593 
594   Level: intermediate
595 
596 .seealso: `PetscDrawHG`, `PetscDrawAxis`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
597 @*/
598 PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis) {
599   PetscFunctionBegin;
600   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
601   PetscValidPointer(axis, 2);
602   *axis = hist->axis;
603   PetscFunctionReturn(0);
604 }
605 
606 /*@C
607   PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
608 
609   Not Collective, draw is parallel if hist is parallel
610 
611   Input Parameter:
612 . hist - The histogram context
613 
614   Output Parameter:
615 . draw  - The draw context
616 
617   Level: intermediate
618 
619 .seealso: `PetscDraw`, `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
620 @*/
621 PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *draw) {
622   PetscFunctionBegin;
623   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
624   PetscValidPointer(draw, 2);
625   *draw = hist->win;
626   PetscFunctionReturn(0);
627 }
628