Actual source code: hists.c
1: /*$Id: hists.c,v 1.26 2001/04/10 19:34:23 bsmith Exp $*/
3: /*
4: Contains the data structure for plotting a histogram in a window with an axis.
5: */
7: #include petsc.h
9: int DRAWHG_COOKIE;
11: struct _p_DrawHG {
12: PETSCHEADER(int)
13: int (*destroy)(PetscDrawSP);
14: int (*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: PetscTruth calcStats;
27: PetscTruth integerBins;
28: };
30: #define CHUNKSIZE 100
32: #undef __FUNCT__
34: /*@C
35: PetscDrawHGCreate - Creates a histogram data structure.
37: Collective over PetscDraw
39: Input Parameters:
40: + draw - The window where the graph will be made
41: - bins - The number of bins to use
43: Output Parameters:
44: . hist - The histogram context
46: Level: intermediate
48: Contributed by: Matthew Knepley
50: Concepts: histogram^creating
52: .seealso: PetscDrawHGDestroy()
54: @*/
55: int PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist) {
56: PetscDrawHG h;
57: MPI_Comm comm;
58: PetscTruth isnull;
59: int ierr;
64: PetscObjectGetComm((PetscObject) draw, &comm);
65: PetscHeaderCreate(h, _p_DrawHG, int, DRAWHG_COOKIE, 0, "PetscDrawHG", comm, PetscDrawHGDestroy, PETSC_NULL);
66: h->view = PETSC_NULL;
67: h->destroy = PETSC_NULL;
68: h->win = draw;
69: PetscObjectReference((PetscObject) draw);
70: h->color = PETSC_DRAW_GREEN;
71: h->xmin = PETSC_MAX;
72: h->xmax = PETSC_MIN;
73: h->ymin = 0.;
74: h->ymax = 1.;
75: h->numBins = bins;
76: h->maxBins = bins;
77: PetscMalloc(h->maxBins * sizeof(PetscReal), &h->bins);
78: h->numValues = 0;
79: h->maxValues = CHUNKSIZE;
80: h->calcStats = PETSC_FALSE;
81: h->integerBins = PETSC_FALSE;
82: PetscMalloc(h->maxValues * sizeof(PetscReal), &h->values);
83: PetscLogObjectMemory(h, (h->maxBins + h->maxValues)*sizeof(PetscReal));
84: PetscTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
85: if (isnull == PETSC_FALSE) {
86: PetscDrawAxisCreate(draw, &h->axis);
87: PetscLogObjectParent(h, h->axis);
88: } else {
89: h->axis = PETSC_NULL;
90: }
91: *hist = h;
92: return(0);
93: }
95: #undef __FUNCT__
97: /*@
98: PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn.
100: Not Collective (ignored except on processor 0 of PetscDrawHG)
102: Input Parameter:
103: + hist - The histogram context.
104: - dim - The number of curves.
106: Level: intermediate
108: Contributed by: Matthew Knepley
110: Concepts: histogram^setting number of bins
112: @*/
113: int PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins) {
118: if (hist->maxBins < bins) {
119: PetscFree(hist->bins);
120: PetscMalloc(bins * sizeof(PetscReal), &hist->bins);
121: PetscLogObjectMemory(hist, (bins - hist->maxBins) * sizeof(PetscReal));
122: hist->maxBins = bins;
123: }
124: hist->numBins = bins;
125: return(0);
126: }
128: #undef __FUNCT__
130: /*@
131: PetscDrawHGReset - Clears histogram to allow for reuse with new data.
133: Not Collective (ignored except on processor 0 of PetscDrawHG)
135: Input Parameter:
136: . hist - The histogram context.
138: Level: intermediate
140: Contributed by: Matthew Knepley
142: Concepts: histogram^resetting
143: @*/
144: int PetscDrawHGReset(PetscDrawHG hist)
145: {
148: hist->xmin = PETSC_MAX;
149: hist->xmax = PETSC_MIN;
150: hist->ymin = 0;
151: hist->ymax = 0;
152: hist->numValues = 0;
153: return(0);
154: }
156: #undef __FUNCT__
158: /*@C
159: PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
161: Collective over PetscDrawHG
163: Input Parameter:
164: . hist - The histogram context
166: Level: intermediate
168: Contributed by: Matthew Knepley
170: .seealso: PetscDrawHGCreate()
171: @*/
172: int PetscDrawHGDestroy(PetscDrawHG hist)
173: {
179: if (--hist->refct > 0) return(0);
180: if (hist->axis != PETSC_NULL) {
181: PetscDrawAxisDestroy(hist->axis);
182: }
183: PetscDrawDestroy(hist->win);
184: PetscFree(hist->bins);
185: PetscFree(hist->values);
186: PetscLogObjectDestroy(hist);
187: PetscHeaderDestroy(hist);
188: return(0);
189: }
191: #undef __FUNCT__
193: /*@
194: PetscDrawHGAddValue - Adds another value to the histogram.
196: Not Collective (ignored except on processor 0 of PetscDrawHG)
198: Input Parameters:
199: + hist - The histogram
200: - value - The value
202: Level: intermediate
204: Contributed by: Matthew Knepley
206: Concepts: histogram^adding values
208: .seealso: PetscDrawHGAddValues()
209: @*/
210: int PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
211: {
214: /* Allocate more memory if necessary */
215: if (hist->numValues >= hist->maxValues) {
216: PetscReal *tmp;
217: int ierr;
219: PetscMalloc((hist->maxValues+CHUNKSIZE) * sizeof(PetscReal), &tmp);
220: PetscLogObjectMemory(hist, CHUNKSIZE * sizeof(PetscReal));
221: PetscMemcpy(tmp, hist->values, hist->maxValues * sizeof(PetscReal));
222: PetscFree(hist->values);
223: hist->values = tmp;
224: hist->maxValues += CHUNKSIZE;
225: }
226: /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
227: stated convention of using half-open intervals (always the way to go) */
228: if (!hist->numValues) {
229: hist->xmin = value;
230: hist->xmax = value;
231: #if 1
232: } else {
233: /* Update limits */
234: if (value > hist->xmax)
235: hist->xmax = value;
236: if (value < hist->xmin)
237: hist->xmin = value;
238: #else
239: } else if (hist->numValues == 1) {
240: /* Update limits -- We need to overshoot the largest value somewhat */
241: if (value > hist->xmax) {
242: hist->xmax = value + 0.001*(value - hist->xmin)/hist->numBins;
243: }
244: if (value < hist->xmin) {
245: hist->xmin = value;
246: hist->xmax = hist->xmax + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
247: }
248: } else {
249: /* Update limits -- We need to overshoot the largest value somewhat */
250: if (value > hist->xmax) {
251: hist->xmax = value + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
252: }
253: if (value < hist->xmin) {
254: hist->xmin = value;
255: }
256: #endif
257: }
259: hist->values[hist->numValues++] = value;
260: return(0);
261: }
263: #undef __FUNCT__
265: /*@
266: PetscDrawHGDraw - Redraws a histogram.
268: Not Collective (ignored except on processor 0 of PetscDrawHG)
270: Input Parameter:
271: . hist - The histogram context
273: Level: intermediate
275: Contributed by: Matthew Knepley
276: @*/
277: int PetscDrawHGDraw(PetscDrawHG hist)
278: {
279: PetscDraw draw = hist->win;
280: PetscTruth isnull;
281: PetscReal xmin,xmax,ymin,ymax,*bins,*values,binSize,binLeft,binRight,maxHeight,mean,var;
282: char title[256];
283: char xlabel[256];
284: int numBins,numBinsOld,numValues,initSize,i,p,ierr,bcolor,color;
288: PetscTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
289: if (isnull == PETSC_TRUE) return(0);
290: if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
291: if (hist->numValues < 1) return(0);
293: #if 0
294: MPI_Comm_rank(hist->comm,&rank);
295: if (rank) return(0);
296: #endif
298: color = hist->color;
299: if (color == PETSC_DRAW_ROTATE) {bcolor = 2;} else {bcolor = color;}
300: xmin = hist->xmin;
301: xmax = hist->xmax;
302: ymin = hist->ymin;
303: ymax = hist->ymax;
304: numValues = hist->numValues;
305: values = hist->values;
306: mean = 0.0;
307: var = 0.0;
308:
309: PetscDrawClear(draw);
310: if (xmin == xmax) {
311: /* Calculate number of points in each bin */
312: bins = hist->bins;
313: bins[0] = 0;
314: for(p = 0; p < numValues; p++) {
315: if (values[p] == xmin) bins[0]++;
316: mean += values[p];
317: var += values[p]*values[p];
318: }
319: maxHeight = bins[0];
320: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
321: xmax = xmin + 1;
322: PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
323: if (hist->calcStats) {
324: mean /= numValues;
325: if (numValues > 1) {
326: var = (var - numValues*mean*mean) / (numValues-1);
327: } else {
328: var = 0.0;
329: }
330: sprintf(title, "Mean: %g Var: %g", mean, var);
331: sprintf(xlabel, "Total: %d", numValues);
332: ierr = PetscDrawAxisSetLabels(hist->axis, title, xlabel, PETSC_NULL);
333: }
334: PetscDrawAxisDraw(hist->axis);
335: /* Draw bins */
336: binLeft = xmin;
337: binRight = xmax;
338: PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[0],bcolor,bcolor,bcolor,bcolor);
339: if (color == PETSC_DRAW_ROTATE && bins[0]) bcolor++; if (bcolor > 31) bcolor = 2;
340: PetscDrawLine(draw,binLeft,ymin,binLeft,bins[0],PETSC_DRAW_BLACK);
341: PetscDrawLine(draw,binRight,ymin,binRight,bins[0],PETSC_DRAW_BLACK);
342: PetscDrawLine(draw,binLeft,bins[0],binRight,bins[0],PETSC_DRAW_BLACK);
343: } else {
344: numBins = hist->numBins;
345: numBinsOld = hist->numBins;
346: if ((hist->integerBins == PETSC_TRUE) && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
347: initSize = (int) ((int) xmax - xmin)/numBins;
348: while (initSize*numBins != (int) xmax - xmin) {
349: initSize = PetscMax(initSize - 1, 1);
350: numBins = (int) ((int) xmax - xmin)/initSize;
351: ierr = PetscDrawHGSetNumberBins(hist, numBins);
352: }
353: }
354: binSize = (xmax - xmin)/numBins;
355: bins = hist->bins;
357: PetscMemzero(bins, numBins * sizeof(PetscReal));
358: maxHeight = 0;
359: for (i = 0; i < numBins; i++) {
360: binLeft = xmin + binSize*i;
361: binRight = xmin + binSize*(i+1);
362: for(p = 0; p < numValues; p++) {
363: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
364: /* Handle last bin separately */
365: if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
366: if (i == 0) {
367: mean += values[p];
368: var += values[p]*values[p];
369: }
370: }
371: maxHeight = PetscMax(maxHeight, bins[i]);
372: }
373: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
375: PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
376: if (hist->calcStats) {
377: mean /= numValues;
378: if (numValues > 1) {
379: var = (var - numValues*mean*mean) / (numValues-1);
380: } else {
381: var = 0.0;
382: }
383: sprintf(title, "Mean: %g Var: %g", mean, var);
384: sprintf(xlabel, "Total: %d", numValues);
385: ierr = PetscDrawAxisSetLabels(hist->axis, title, xlabel, PETSC_NULL);
386: }
387: PetscDrawAxisDraw(hist->axis);
388: /* Draw bins */
389: for (i = 0; i < numBins; i++) {
390: binLeft = xmin + binSize*i;
391: binRight = xmin + binSize*(i+1);
392: PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[i],bcolor,bcolor,bcolor,bcolor);
393: if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++; if (bcolor > 31) bcolor = 2;
394: PetscDrawLine(draw,binLeft,ymin,binLeft,bins[i],PETSC_DRAW_BLACK);
395: PetscDrawLine(draw,binRight,ymin,binRight,bins[i],PETSC_DRAW_BLACK);
396: PetscDrawLine(draw,binLeft,bins[i],binRight,bins[i],PETSC_DRAW_BLACK);
397: }
398: PetscDrawHGSetNumberBins(hist, numBinsOld);
399: }
400: PetscDrawSynchronizedFlush(draw);
401: PetscDrawPause(draw);
402: return(0);
403: }
405: #undef __FUNCT__
407: /*@
408: PetscDrawHGPrint - Prints the histogram information.
410: Not collective
412: Input Parameter:
413: . hist - The histogram context
415: Level: beginner
417: Contributed by: Matthew Knepley
419: .keywords: draw, histogram
420: @*/
421: int PetscDrawHGPrint(PetscDrawHG hist)
422: {
423: PetscReal xmax,xmin,*bins,*values,binSize,binLeft,binRight,mean,var;
424: int numBins,numBinsOld,numValues,initSize,i,p,ierr;
428: if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
429: if (hist->numValues < 1) return(0);
431: xmax = hist->xmax;
432: xmin = hist->xmin;
433: numValues = hist->numValues;
434: values = hist->values;
435: mean = 0.0;
436: var = 0.0;
437: if (xmax == xmin) {
438: /* Calculate number of points in the bin */
439: bins = hist->bins;
440: bins[0] = 0;
441: for(p = 0; p < numValues; p++) {
442: if (values[p] == xmin) bins[0]++;
443: mean += values[p];
444: var += values[p]*values[p];
445: }
446: /* Draw bins */
447: PetscPrintf(hist->comm, "Bin %2d (%6.2g - %6.2g): %.0gn", 0, xmin, xmax, bins[0]);
448: } else {
449: numBins = hist->numBins;
450: numBinsOld = hist->numBins;
451: if ((hist->integerBins == PETSC_TRUE) && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
452: initSize = (int) ((int) xmax - xmin)/numBins;
453: while (initSize*numBins != (int) xmax - xmin) {
454: initSize = PetscMax(initSize - 1, 1);
455: numBins = (int) ((int) xmax - xmin)/initSize;
456: ierr = PetscDrawHGSetNumberBins(hist, numBins);
457: }
458: }
459: binSize = (xmax - xmin)/numBins;
460: bins = hist->bins;
462: /* Calculate number of points in each bin */
463: PetscMemzero(bins, numBins * sizeof(PetscReal));
464: for (i = 0; i < numBins; i++) {
465: binLeft = xmin + binSize*i;
466: binRight = xmin + binSize*(i+1);
467: for(p = 0; p < numValues; p++) {
468: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
469: /* Handle last bin separately */
470: if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
471: if (i == 0) {
472: mean += values[p];
473: var += values[p]*values[p];
474: }
475: }
476: }
477: /* Draw bins */
478: for (i = 0; i < numBins; i++) {
479: binLeft = xmin + binSize*i;
480: binRight = xmin + binSize*(i+1);
481: PetscPrintf(hist->comm, "Bin %2d (%6.2g - %6.2g): %.0gn", i, binLeft, binRight, bins[i]);
482: }
483: PetscDrawHGSetNumberBins(hist, numBinsOld);
484: }
486: if (hist->calcStats) {
487: mean /= numValues;
488: if (numValues > 1) {
489: var = (var - numValues*mean*mean) / (numValues-1);
490: } else {
491: var = 0.0;
492: }
493: PetscPrintf(hist->comm, "Mean: %g Var: %gn", mean, var);
494: PetscPrintf(hist->comm, "Total: %dn", numValues);
495: }
496: return(0);
497: }
498:
499: #undef __FUNCT__
501: /*@
502: PetscDrawHGSetColor - Sets the color the bars will be drawn with.
504: Not Collective (ignored except on processor 0 of PetscDrawHG)
506: Input Parameters:
507: + hist - The histogram context
508: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
509: different color
511: Level: intermediate
513: @*/
514: int PetscDrawHGSetColor(PetscDrawHG hist, int color)
515: {
518: hist->color = color;
519: return(0);
520: }
522: #undef __FUNCT__
524: /*@
525: PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
526: points are added after this call, the limits will be adjusted to
527: include those additional points.
529: Not Collective (ignored except on processor 0 of PetscDrawHG)
531: Input Parameters:
532: + hist - The histogram context
533: - x_min,x_max,y_min,y_max - The limits
535: Level: intermediate
537: Contributed by: Matthew Knepley
539: Concepts: histogram^setting axis
540: @*/
541: int PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
542: {
545: hist->xmin = x_min;
546: hist->xmax = x_max;
547: hist->ymin = y_min;
548: hist->ymax = y_max;
549: return(0);
550: }
552: #undef __FUNCT__
554: /*@
555: PetscDrawHGCalcStats - Turns on calculation of descriptive statistics
557: Not collective
559: Input Parameters:
560: + hist - The histogram context
561: - calc - Flag for calculation
563: Level: intermediate
565: Contributed by: Matthew Knepley
567: .keywords: draw, histogram, statistics
569: @*/
570: int PetscDrawHGCalcStats(PetscDrawHG hist, PetscTruth calc)
571: {
574: hist->calcStats = calc;
575: return(0);
576: }
578: #undef __FUNCT__
580: /*@
581: PetscDrawHGIntegerBins - Turns on integer width bins
583: Not collective
585: Input Parameters:
586: + hist - The histogram context
587: - ints - Flag for integer width bins
589: Level: intermediate
591: Contributed by: Matthew Knepley
593: .keywords: draw, histogram, statistics
594: @*/
595: int PetscDrawHGIntegerBins(PetscDrawHG hist, PetscTruth ints)
596: {
599: hist->integerBins = ints;
600: return(0);
601: }
603: #undef __FUNCT__
605: /*@C
606: PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
607: This is useful if one wants to change some axis property, such as
608: labels, color, etc. The axis context should not be destroyed by the
609: application code.
611: Not Collective (ignored except on processor 0 of PetscDrawHG)
613: Input Parameter:
614: . hist - The histogram context
616: Output Parameter:
617: . axis - The axis context
619: Level: intermediate
621: Contributed by: Matthew Knepley
622: @*/
623: int PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
624: {
627: *axis = hist->axis;
628: return(0);
629: }
631: #undef __FUNCT__
633: /*@C
634: PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
636: Not Collective, PetscDraw is parallel if PetscDrawHG is parallel
638: Input Parameter:
639: . hist - The histogram context
641: Output Parameter:
642: . win - The draw context
644: Level: intermediate
646: Contributed by: Matthew Knepley
647: @*/
648: int PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *win)
649: {
652: *win = hist->win;
653: return(0);
654: }