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