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