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