xref: /petsc/src/sys/classes/draw/utils/hists.c (revision b9d635d7b5c3ee5434768b771e5fbf76581fe7bc)
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) / (PetscReal)hist->numBins;
215     if (value < hist->xmin) {
216       hist->xmin = value;
217       hist->xmax = hist->xmax + 0.001 * (hist->xmax - hist->xmin) / (PetscReal)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) / (PetscReal)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    numValues, initSize, i, p;
250   int         bcolor, color, numBins, numBinsOld;
251   PetscMPIInt rank;
252 
253   PetscFunctionBegin;
254   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
255   PetscCall(PetscDrawIsNull(hist->win, &isnull));
256   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
257   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)hist), &rank));
258 
259   if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(PETSC_SUCCESS);
260   if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
261 
262   color = hist->color;
263   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK + 1;
264   else bcolor = color;
265 
266   xmin      = hist->xmin;
267   xmax      = hist->xmax;
268   ymin      = hist->ymin;
269   ymax      = hist->ymax;
270   numValues = hist->numValues;
271   values    = hist->values;
272   mean      = 0.0;
273   var       = 0.0;
274 
275   draw = hist->win;
276   PetscCall(PetscDrawCheckResizedWindow(draw));
277   PetscCall(PetscDrawClear(draw));
278 
279   if (xmin == xmax) {
280     /* Calculate number of points in each bin */
281     bins    = hist->bins;
282     bins[0] = 0.;
283     for (p = 0; p < numValues; p++) {
284       if (values[p] == xmin) bins[0]++;
285       mean += values[p];
286       var += values[p] * values[p];
287     }
288     maxHeight = bins[0];
289     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
290     xmax = xmin + 1;
291     PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
292     if (hist->calcStats) {
293       mean /= (PetscReal)numValues;
294       if (numValues > 1) var = (var - ((PetscReal)numValues) * mean * mean) / ((PetscReal)numValues - 1);
295       else var = 0.0;
296       PetscCall(PetscSNPrintf(title, 256, "Mean: %g  Var: %g", (double)mean, (double)var));
297       PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
298       PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
299     }
300     PetscCall(PetscDrawAxisDraw(hist->axis));
301     PetscDrawCollectiveBegin(draw);
302     if (rank == 0) { /* Draw bins */
303       binLeft  = xmin;
304       binRight = xmax;
305       PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[0], bcolor, bcolor, bcolor, bcolor));
306       PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[0], PETSC_DRAW_BLACK));
307       PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[0], PETSC_DRAW_BLACK));
308       PetscCall(PetscDrawLine(draw, binLeft, bins[0], binRight, bins[0], PETSC_DRAW_BLACK));
309     }
310     PetscDrawCollectiveEnd(draw);
311   } else {
312     numBins    = hist->numBins;
313     numBinsOld = hist->numBins;
314     if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
315       initSize = ((int)(xmax - xmin)) / numBins;
316       while (initSize * numBins != (int)xmax - xmin) {
317         initSize = PetscMax(initSize - 1, 1);
318         numBins  = ((int)(xmax - xmin)) / initSize;
319         PetscCall(PetscDrawHGSetNumberBins(hist, numBins));
320       }
321     }
322     binSize = (xmax - xmin) / (PetscReal)numBins;
323     bins    = hist->bins;
324 
325     PetscCall(PetscArrayzero(bins, numBins));
326 
327     maxHeight = 0.0;
328     for (i = 0; i < numBins; i++) {
329       binLeft  = xmin + binSize * i;
330       binRight = xmin + binSize * (i + 1);
331       for (p = 0; p < numValues; p++) {
332         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
333         /* Handle last bin separately */
334         if ((i == numBins - 1) && (values[p] == binRight)) bins[i]++;
335         if (!i) {
336           mean += values[p];
337           var += values[p] * values[p];
338         }
339       }
340       maxHeight = PetscMax(maxHeight, bins[i]);
341     }
342     if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
343 
344     PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
345     if (hist->calcStats) {
346       mean /= numValues;
347       if (numValues > 1) var = (var - numValues * mean * mean) / (numValues - 1);
348       else var = 0.0;
349       PetscCall(PetscSNPrintf(title, 256, "Mean: %g  Var: %g", (double)mean, (double)var));
350       PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
351       PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
352     }
353     PetscCall(PetscDrawAxisDraw(hist->axis));
354     PetscDrawCollectiveBegin(draw);
355     if (rank == 0) { /* Draw bins */
356       for (i = 0; i < numBins; i++) {
357         binLeft  = xmin + binSize * i;
358         binRight = xmin + binSize * (i + 1);
359         PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[i], bcolor, bcolor, bcolor, bcolor));
360         PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[i], PETSC_DRAW_BLACK));
361         PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[i], PETSC_DRAW_BLACK));
362         PetscCall(PetscDrawLine(draw, binLeft, bins[i], binRight, bins[i], PETSC_DRAW_BLACK));
363         if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++;
364         if (bcolor > PETSC_DRAW_BASIC_COLORS - 1) bcolor = PETSC_DRAW_BLACK + 1;
365       }
366     }
367     PetscDrawCollectiveEnd(draw);
368     PetscCall(PetscDrawHGSetNumberBins(hist, numBinsOld));
369   }
370 
371   PetscCall(PetscDrawFlush(draw));
372   PetscCall(PetscDrawPause(draw));
373   PetscFunctionReturn(PETSC_SUCCESS);
374 }
375 
376 /*@
377   PetscDrawHGSave - Saves a drawn image
378 
379   Collective
380 
381   Input Parameter:
382 . hg - The histogram context
383 
384   Level: intermediate
385 
386 .seealso: `PetscDrawSave()`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawHGDraw()`
387 @*/
388 PetscErrorCode PetscDrawHGSave(PetscDrawHG hg)
389 {
390   PetscFunctionBegin;
391   PetscValidHeaderSpecific(hg, PETSC_DRAWHG_CLASSID, 1);
392   PetscCall(PetscDrawSave(hg->win));
393   PetscFunctionReturn(PETSC_SUCCESS);
394 }
395 
396 /*@
397   PetscDrawHGView - Prints the histogram information to a viewer
398 
399   Not Collective
400 
401   Input Parameters:
402 + hist   - The histogram context
403 - viewer - The viewer to view it with
404 
405   Level: beginner
406 
407 .seealso: `PetscDrawHG`, `PetscViewer`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`
408 @*/
409 PetscErrorCode PetscDrawHGView(PetscDrawHG hist, PetscViewer viewer)
410 {
411   PetscReal xmax, xmin, *bins, *values, binSize, binLeft, binRight, mean, var;
412   PetscInt  numBins, numBinsOld, numValues, initSize, i, p;
413   int       inumBins;
414 
415   PetscFunctionBegin;
416   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
417 
418   if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(PETSC_SUCCESS);
419   if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
420 
421   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist), &viewer));
422   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)hist, viewer));
423   xmax      = hist->xmax;
424   xmin      = hist->xmin;
425   numValues = hist->numValues;
426   values    = hist->values;
427   mean      = 0.0;
428   var       = 0.0;
429   if (xmax == xmin) {
430     /* Calculate number of points in the bin */
431     bins    = hist->bins;
432     bins[0] = 0.;
433     for (p = 0; p < numValues; p++) {
434       if (values[p] == xmin) bins[0]++;
435       mean += values[p];
436       var += values[p] * values[p];
437     }
438     /* Draw bins */
439     PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]));
440   } else {
441     numBins    = hist->numBins;
442     numBinsOld = hist->numBins;
443     if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
444       initSize = (int)((int)xmax - xmin) / numBins;
445       while (initSize * numBins != (int)xmax - xmin) {
446         initSize = PetscMax(initSize - 1, 1);
447         numBins  = (int)((int)xmax - xmin) / initSize;
448         PetscCall(PetscCIntCast(numBins, &inumBins));
449         PetscCall(PetscDrawHGSetNumberBins(hist, inumBins));
450       }
451     }
452     binSize = (xmax - xmin) / numBins;
453     bins    = hist->bins;
454 
455     /* Calculate number of points in each bin */
456     PetscCall(PetscArrayzero(bins, numBins));
457     for (i = 0; i < numBins; i++) {
458       binLeft  = xmin + binSize * i;
459       binRight = xmin + binSize * (i + 1);
460       for (p = 0; p < numValues; p++) {
461         if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
462         /* Handle last bin separately */
463         if ((i == numBins - 1) && (values[p] == binRight)) bins[i]++;
464         if (!i) {
465           mean += values[p];
466           var += values[p] * values[p];
467         }
468       }
469     }
470     /* Draw bins */
471     for (i = 0; i < numBins; i++) {
472       binLeft  = xmin + binSize * i;
473       binRight = xmin + binSize * (i + 1);
474       PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2" PetscInt_FMT " (%6.2g - %6.2g): %.0g\n", i, (double)binLeft, (double)binRight, (double)bins[i]));
475     }
476     PetscCall(PetscCIntCast(numBinsOld, &inumBins));
477     PetscCall(PetscDrawHGSetNumberBins(hist, inumBins));
478   }
479 
480   if (hist->calcStats) {
481     mean /= numValues;
482     if (numValues > 1) var = (var - numValues * mean * mean) / (numValues - 1);
483     else var = 0.0;
484     PetscCall(PetscViewerASCIIPrintf(viewer, "Mean: %g  Var: %g\n", (double)mean, (double)var));
485     PetscCall(PetscViewerASCIIPrintf(viewer, "Total: %" PetscInt_FMT "\n", numValues));
486   }
487   PetscFunctionReturn(PETSC_SUCCESS);
488 }
489 
490 /*@
491   PetscDrawHGSetColor - Sets the color the bars will be drawn with.
492 
493   Logically Collective
494 
495   Input Parameters:
496 + hist  - The histogram context
497 - color - one of the colors defined in petscdraw.h or `PETSC_DRAW_ROTATE` to make each bar a different color
498 
499   Level: intermediate
500 
501 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
502 @*/
503 PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color)
504 {
505   PetscFunctionBegin;
506   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
507 
508   hist->color = color;
509   PetscFunctionReturn(PETSC_SUCCESS);
510 }
511 
512 /*@
513   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
514   points are added after this call, the limits will be adjusted to
515   include those additional points.
516 
517   Logically Collective
518 
519   Input Parameters:
520 + hist  - The histogram context
521 . x_min - the horizontal lower limit
522 . x_max - the horizontal upper limit
523 . y_min - the vertical lower limit
524 - y_max - the vertical upper limit
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 /*@
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()`, `PetscDrawHGSetLimits()`
603 @*/
604 PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
605 {
606   PetscFunctionBegin;
607   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
608   PetscAssertPointer(axis, 2);
609   *axis = hist->axis;
610   PetscFunctionReturn(PETSC_SUCCESS);
611 }
612 
613 /*@
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   PetscAssertPointer(draw, 2);
633   *draw = hist->win;
634   PetscFunctionReturn(PETSC_SUCCESS);
635 }
636