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