xref: /petsc/src/sys/classes/draw/utils/hists.c (revision df4cd43f92eaa320656440c40edb1046daee8f75)
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
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 {
60   PetscDrawHG h;
61 
62   PetscFunctionBegin;
63   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
64   PetscValidLogicalCollectiveInt(draw, bins, 2);
65   PetscValidPointer(hist, 3);
66 
67   PetscCall(PetscHeaderCreate(h, PETSC_DRAWHG_CLASSID, "DrawHG", "Histogram", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawHGDestroy, NULL));
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(PetscDrawAxisCreate(draw, &h->axis));
91 
92   *hist = h;
93   PetscFunctionReturn(PETSC_SUCCESS);
94 }
95 
96 /*@
97    PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn in the histogram
98 
99    Logically Collective
100 
101    Input Parameters:
102 +  hist - The histogram context.
103 -  bins  - The number of bins.
104 
105    Level: intermediate
106 
107 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGIntegerBins()`
108 @*/
109 PetscErrorCode PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins)
110 {
111   PetscFunctionBegin;
112   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
113   PetscValidLogicalCollectiveInt(hist, bins, 2);
114 
115   if (hist->maxBins < bins) {
116     PetscCall(PetscFree(hist->bins));
117     PetscCall(PetscMalloc1(bins, &hist->bins));
118     hist->maxBins = bins;
119   }
120   hist->numBins = bins;
121   PetscFunctionReturn(PETSC_SUCCESS);
122 }
123 
124 /*@
125   PetscDrawHGReset - Clears histogram to allow for reuse with new data.
126 
127   Logically Collective
128 
129   Input Parameter:
130 . hist - The histogram context.
131 
132   Level: intermediate
133 
134 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`
135 @*/
136 PetscErrorCode PetscDrawHGReset(PetscDrawHG hist)
137 {
138   PetscFunctionBegin;
139   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
140 
141   hist->xmin      = PETSC_MAX_REAL;
142   hist->xmax      = PETSC_MIN_REAL;
143   hist->ymin      = 0.0;
144   hist->ymax      = 1.0;
145   hist->numValues = 0;
146   PetscFunctionReturn(PETSC_SUCCESS);
147 }
148 
149 /*@C
150   PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
151 
152   Collective
153 
154   Input Parameter:
155 . hist - The histogram context
156 
157   Level: intermediate
158 
159 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`
160 @*/
161 PetscErrorCode PetscDrawHGDestroy(PetscDrawHG *hist)
162 {
163   PetscFunctionBegin;
164   if (!*hist) PetscFunctionReturn(PETSC_SUCCESS);
165   PetscValidHeaderSpecific(*hist, PETSC_DRAWHG_CLASSID, 1);
166   if (--((PetscObject)(*hist))->refct > 0) {
167     *hist = NULL;
168     PetscFunctionReturn(PETSC_SUCCESS);
169   }
170 
171   PetscCall(PetscFree((*hist)->bins));
172   PetscCall(PetscFree((*hist)->values));
173   PetscCall(PetscDrawAxisDestroy(&(*hist)->axis));
174   PetscCall(PetscDrawDestroy(&(*hist)->win));
175   PetscCall(PetscHeaderDestroy(hist));
176   PetscFunctionReturn(PETSC_SUCCESS);
177 }
178 
179 /*@
180   PetscDrawHGAddValue - Adds another value to the histogram.
181 
182   Logically Collective
183 
184   Input Parameters:
185 + hist  - The histogram
186 - value - The value
187 
188   Level: intermediate
189 
190 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`, `PetscDrawHGReset()`
191 @*/
192 PetscErrorCode PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
193 {
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(PetscArraycpy(tmp, hist->values, hist->maxValues));
203     PetscCall(PetscFree(hist->values));
204 
205     hist->values = tmp;
206     hist->maxValues += CHUNKSIZE;
207   }
208   /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
209      stated convention of using half-open intervals (always the way to go) */
210   if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
211     hist->xmin = value;
212     hist->xmax = value;
213 #if 1
214   } else {
215     /* Update limits */
216     if (value > hist->xmax) hist->xmax = value;
217     if (value < hist->xmin) hist->xmin = value;
218 #else
219   } else if (hist->numValues == 1) {
220     /* Update limits -- We need to overshoot the largest value somewhat */
221     if (value > hist->xmax) hist->xmax = value + 0.001 * (value - hist->xmin) / hist->numBins;
222     if (value < hist->xmin) {
223       hist->xmin = value;
224       hist->xmax = hist->xmax + 0.001 * (hist->xmax - hist->xmin) / hist->numBins;
225     }
226   } else {
227     /* Update limits -- We need to overshoot the largest value somewhat */
228     if (value > hist->xmax) hist->xmax = value + 0.001 * (hist->xmax - hist->xmin) / hist->numBins;
229     if (value < hist->xmin) hist->xmin = value;
230 #endif
231   }
232 
233   hist->values[hist->numValues++] = value;
234   PetscFunctionReturn(PETSC_SUCCESS);
235 }
236 
237 /*@
238   PetscDrawHGDraw - Redraws a histogram.
239 
240   Collective
241 
242   Input Parameter:
243 . hist - The histogram context
244 
245   Level: intermediate
246 
247 .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`, `PetscDrawHGReset()`
248 @*/
249 PetscErrorCode PetscDrawHGDraw(PetscDrawHG hist)
250 {
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(PETSC_SUCCESS);
263   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)hist), &rank));
264 
265   if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(PETSC_SUCCESS);
266   if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
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(PETSC_SUCCESS);
380 }
381 
382 /*@
383   PetscDrawHGSave - Saves a drawn image
384 
385   Collective
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 {
396   PetscFunctionBegin;
397   PetscValidHeaderSpecific(hg, PETSC_DRAWHG_CLASSID, 1);
398   PetscCall(PetscDrawSave(hg->win));
399   PetscFunctionReturn(PETSC_SUCCESS);
400 }
401 
402 /*@
403   PetscDrawHGView - Prints the histogram information to a viewer
404 
405   Not collective
406 
407   Input Parameter:
408 . hist - The histogram context
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
500           different color
501 
502   Level: intermediate
503 
504 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
505 @*/
506 PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color)
507 {
508   PetscFunctionBegin;
509   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
510 
511   hist->color = color;
512   PetscFunctionReturn(PETSC_SUCCESS);
513 }
514 
515 /*@
516   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
517   points are added after this call, the limits will be adjusted to
518   include those additional points.
519 
520   Logically Collective
521 
522   Input Parameters:
523 + hist - The histogram context
524 - x_min,x_max,y_min,y_max - The limits
525 
526   Level: intermediate
527 
528 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
529 @*/
530 PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
531 {
532   PetscFunctionBegin;
533   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
534 
535   hist->xmin = x_min;
536   hist->xmax = x_max;
537   hist->ymin = y_min;
538   hist->ymax = y_max;
539   PetscFunctionReturn(PETSC_SUCCESS);
540 }
541 
542 /*@
543   PetscDrawHGCalcStats - Turns on calculation of descriptive statistics associated with the histogram
544 
545   Not collective
546 
547   Input Parameters:
548 + hist - The histogram context
549 - calc - Flag for calculation
550 
551   Level: intermediate
552 
553 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`
554 @*/
555 PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
556 {
557   PetscFunctionBegin;
558   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
559 
560   hist->calcStats = calc;
561   PetscFunctionReturn(PETSC_SUCCESS);
562 }
563 
564 /*@
565   PetscDrawHGIntegerBins - Turns on integer width bins
566 
567   Not collective
568 
569   Input Parameters:
570 + hist - The histogram context
571 - ints - Flag for integer width bins
572 
573   Level: intermediate
574 
575 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`
576 @*/
577 PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
578 {
579   PetscFunctionBegin;
580   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
581 
582   hist->integerBins = ints;
583   PetscFunctionReturn(PETSC_SUCCESS);
584 }
585 
586 /*@C
587   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
588   This is useful if one wants to change some axis property, such as
589   labels, color, etc. The axis context should not be destroyed by the
590   application code.
591 
592   Not Collective, axis is parallel if hist is parallel
593 
594   Input Parameter:
595 . hist - The histogram context
596 
597   Output Parameter:
598 . axis - The axis context
599 
600   Level: intermediate
601 
602 .seealso: `PetscDrawHG`, `PetscDrawAxis`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
603 @*/
604 PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
605 {
606   PetscFunctionBegin;
607   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
608   PetscValidPointer(axis, 2);
609   *axis = hist->axis;
610   PetscFunctionReturn(PETSC_SUCCESS);
611 }
612 
613 /*@C
614   PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
615 
616   Not Collective, draw is parallel if hist is parallel
617 
618   Input Parameter:
619 . hist - The histogram context
620 
621   Output Parameter:
622 . draw  - The draw context
623 
624   Level: intermediate
625 
626 .seealso: `PetscDraw`, `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
627 @*/
628 PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *draw)
629 {
630   PetscFunctionBegin;
631   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
632   PetscValidPointer(draw, 2);
633   *draw = hist->win;
634   PetscFunctionReturn(PETSC_SUCCESS);
635 }
636