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