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