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