xref: /petsc/src/sys/classes/draw/utils/hists.c (revision 2827ebad7ef18d4ed3f6d7633d71fb685bb29d6f)
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   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 different color
500 
501   Level: intermediate
502 
503 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
504 @*/
505 PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color)
506 {
507   PetscFunctionBegin;
508   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
509 
510   hist->color = color;
511   PetscFunctionReturn(PETSC_SUCCESS);
512 }
513 
514 /*@
515   PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
516   points are added after this call, the limits will be adjusted to
517   include those additional points.
518 
519   Logically Collective
520 
521   Input Parameters:
522 + hist - The histogram context
523 . x_min - the horizontal lower limit
524 . x_max - the horizontal upper limit
525 . y_min - the vertical lower limit
526 - y_max - the vertical upper limit
527 
528   Level: intermediate
529 
530 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
531 @*/
532 PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
533 {
534   PetscFunctionBegin;
535   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
536 
537   hist->xmin = x_min;
538   hist->xmax = x_max;
539   hist->ymin = y_min;
540   hist->ymax = y_max;
541   PetscFunctionReturn(PETSC_SUCCESS);
542 }
543 
544 /*@
545   PetscDrawHGCalcStats - Turns on calculation of descriptive statistics associated with the histogram
546 
547   Not Collective
548 
549   Input Parameters:
550 + hist - The histogram context
551 - calc - Flag for calculation
552 
553   Level: intermediate
554 
555 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`
556 @*/
557 PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
558 {
559   PetscFunctionBegin;
560   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
561 
562   hist->calcStats = calc;
563   PetscFunctionReturn(PETSC_SUCCESS);
564 }
565 
566 /*@
567   PetscDrawHGIntegerBins - Turns on integer width bins
568 
569   Not Collective
570 
571   Input Parameters:
572 + hist - The histogram context
573 - ints - Flag for integer width bins
574 
575   Level: intermediate
576 
577 .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`
578 @*/
579 PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
580 {
581   PetscFunctionBegin;
582   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
583 
584   hist->integerBins = ints;
585   PetscFunctionReturn(PETSC_SUCCESS);
586 }
587 
588 /*@C
589   PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
590   This is useful if one wants to change some axis property, such as
591   labels, color, etc. The axis context should not be destroyed by the
592   application code.
593 
594   Not Collective, axis is parallel if hist is parallel
595 
596   Input Parameter:
597 . hist - The histogram context
598 
599   Output Parameter:
600 . axis - The axis context
601 
602   Level: intermediate
603 
604 .seealso: `PetscDrawHG`, `PetscDrawAxis`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
605 @*/
606 PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
607 {
608   PetscFunctionBegin;
609   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
610   PetscValidPointer(axis, 2);
611   *axis = hist->axis;
612   PetscFunctionReturn(PETSC_SUCCESS);
613 }
614 
615 /*@C
616   PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
617 
618   Not Collective, draw is parallel if hist is parallel
619 
620   Input Parameter:
621 . hist - The histogram context
622 
623   Output Parameter:
624 . draw  - The draw context
625 
626   Level: intermediate
627 
628 .seealso: `PetscDraw`, `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
629 @*/
630 PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *draw)
631 {
632   PetscFunctionBegin;
633   PetscValidHeaderSpecific(hist, PETSC_DRAWHG_CLASSID, 1);
634   PetscValidPointer(draw, 2);
635   *draw = hist->win;
636   PetscFunctionReturn(PETSC_SUCCESS);
637 }
638