xref: /petsc/src/sys/classes/draw/utils/hists.c (revision bcd3bd92eda2d5998e2f14c4bbfb33bd936bdc3e)
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 Parameter:
42 . hist - The histogram context
43 
44   Level: intermediate
45 
46   Notes:
47   The difference between a bar chart, `PetscDrawBar`, and a histogram, `PetscDrawHG`, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP
48 
49   The histogram is only displayed when `PetscDrawHGDraw()` is called.
50 
51   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
52   zeroth MPI process in the communicator. All MPI ranks in the communicator must call `PetscDrawHGDraw()` to display the updated graph.
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   PetscAssertPointer(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 . hg - The histogram context
389 
390   Level: intermediate
391 
392 .seealso: `PetscDrawSave()`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `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 Parameters:
408 + hist   - The histogram context
409 - viewer - The viewer to view it with
410 
411   Level: beginner
412 
413 .seealso: `PetscDrawHG`, `PetscViewer`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`
414 @*/
415 PetscErrorCode PetscDrawHGView(PetscDrawHG hist, PetscViewer viewer)
416 {
417   PetscReal xmax, xmin, *bins, *values, binSize, binLeft, binRight, mean, var;
418   PetscInt  numBins, numBinsOld, numValues, initSize, i, p;
419 
420   PetscFunctionBegin;
421   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
422 
423   if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(PETSC_SUCCESS);
424   if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
425 
426   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist), &viewer));
427   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)hist, viewer));
428   xmax      = hist->xmax;
429   xmin      = hist->xmin;
430   numValues = hist->numValues;
431   values    = hist->values;
432   mean      = 0.0;
433   var       = 0.0;
434   if (xmax == xmin) {
435     /* Calculate number of points in the bin */
436     bins    = hist->bins;
437     bins[0] = 0.;
438     for (p = 0; p < numValues; p++) {
439       if (values[p] == xmin) bins[0]++;
440       mean += values[p];
441       var += values[p] * values[p];
442     }
443     /* Draw bins */
444     PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]));
445   } else {
446     numBins    = hist->numBins;
447     numBinsOld = hist->numBins;
448     if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
449       initSize = (int)((int)xmax - xmin) / numBins;
450       while (initSize * numBins != (int)xmax - xmin) {
451         initSize = PetscMax(initSize - 1, 1);
452         numBins  = (int)((int)xmax - xmin) / initSize;
453         PetscCall(PetscDrawHGSetNumberBins(hist, numBins));
454       }
455     }
456     binSize = (xmax - xmin) / numBins;
457     bins    = hist->bins;
458 
459     /* Calculate number of points in each bin */
460     PetscCall(PetscArrayzero(bins, numBins));
461     for (i = 0; i < numBins; i++) {
462       binLeft  = xmin + binSize * i;
463       binRight = xmin + binSize * (i + 1);
464       for (p = 0; p < numValues; p++) {
465         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
466         /* Handle last bin separately */
467         if ((i == numBins - 1) && (values[p] == binRight)) bins[i]++;
468         if (!i) {
469           mean += values[p];
470           var += values[p] * values[p];
471         }
472       }
473     }
474     /* Draw bins */
475     for (i = 0; i < numBins; i++) {
476       binLeft  = xmin + binSize * i;
477       binRight = xmin + binSize * (i + 1);
478       PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", (int)i, (double)binLeft, (double)binRight, (double)bins[i]));
479     }
480     PetscCall(PetscDrawHGSetNumberBins(hist, numBinsOld));
481   }
482 
483   if (hist->calcStats) {
484     mean /= numValues;
485     if (numValues > 1) var = (var - numValues * mean * mean) / (numValues - 1);
486     else var = 0.0;
487     PetscCall(PetscViewerASCIIPrintf(viewer, "Mean: %g  Var: %g\n", (double)mean, (double)var));
488     PetscCall(PetscViewerASCIIPrintf(viewer, "Total: %" PetscInt_FMT "\n", numValues));
489   }
490   PetscFunctionReturn(PETSC_SUCCESS);
491 }
492 
493 /*@
494   PetscDrawHGSetColor - Sets the color the bars will be drawn with.
495 
496   Logically Collective
497 
498   Input Parameters:
499 + hist  - The histogram context
500 - color - one of the colors defined in petscdraw.h or `PETSC_DRAW_ROTATE` to make each bar a 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 - the horizontal lower limit
525 . x_max - the horizontal upper limit
526 . y_min - the vertical lower limit
527 - y_max - the vertical upper limit
528 
529   Level: intermediate
530 
531 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
532 @*/
533 PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
534 {
535   PetscFunctionBegin;
536   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
537 
538   hist->xmin = x_min;
539   hist->xmax = x_max;
540   hist->ymin = y_min;
541   hist->ymax = y_max;
542   PetscFunctionReturn(PETSC_SUCCESS);
543 }
544 
545 /*@
546   PetscDrawHGCalcStats - Turns on calculation of descriptive statistics associated with the histogram
547 
548   Not Collective
549 
550   Input Parameters:
551 + hist - The histogram context
552 - calc - Flag for calculation
553 
554   Level: intermediate
555 
556 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`
557 @*/
558 PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
559 {
560   PetscFunctionBegin;
561   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
562 
563   hist->calcStats = calc;
564   PetscFunctionReturn(PETSC_SUCCESS);
565 }
566 
567 /*@
568   PetscDrawHGIntegerBins - Turns on integer width bins
569 
570   Not Collective
571 
572   Input Parameters:
573 + hist - The histogram context
574 - ints - Flag for integer width bins
575 
576   Level: intermediate
577 
578 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`
579 @*/
580 PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
581 {
582   PetscFunctionBegin;
583   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
584 
585   hist->integerBins = ints;
586   PetscFunctionReturn(PETSC_SUCCESS);
587 }
588 
589 /*@C
590   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
591   This is useful if one wants to change some axis property, such as
592   labels, color, etc. The axis context should not be destroyed by the
593   application code.
594 
595   Not Collective, axis is parallel if hist is parallel
596 
597   Input Parameter:
598 . hist - The histogram context
599 
600   Output Parameter:
601 . axis - The axis context
602 
603   Level: intermediate
604 
605 .seealso: `PetscDrawHG`, `PetscDrawAxis`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawHGSetLimits()`
606 @*/
607 PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
608 {
609   PetscFunctionBegin;
610   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
611   PetscAssertPointer(axis, 2);
612   *axis = hist->axis;
613   PetscFunctionReturn(PETSC_SUCCESS);
614 }
615 
616 /*@C
617   PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
618 
619   Not Collective, draw is parallel if hist is parallel
620 
621   Input Parameter:
622 . hist - The histogram context
623 
624   Output Parameter:
625 . draw - The draw context
626 
627   Level: intermediate
628 
629 .seealso: `PetscDraw`, `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
630 @*/
631 PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *draw)
632 {
633   PetscFunctionBegin;
634   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
635   PetscAssertPointer(draw, 2);
636   *draw = hist->win;
637   PetscFunctionReturn(PETSC_SUCCESS);
638 }
639