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: /*@C
33: PetscDrawHGCreate - Creates a histogram data structure.
35: Collective over PetscDraw
37: Input Parameters:
38: + draw - The window where the graph will be made
39: - bins - The number of bins to use
41: Output Parameters:
42: . hist - The histogram context
44: Level: intermediate
46: Contributed by: Matthew Knepley
48: Concepts: histogram^creating
50: .seealso: PetscDrawHGDestroy()
52: @*/
53: int PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist) {
54: PetscDrawHG h;
55: MPI_Comm comm;
56: PetscTruth isnull;
57: int ierr;
62: PetscObjectGetComm((PetscObject) draw, &comm);
63: PetscHeaderCreate(h, _p_DrawHG, int, DRAWHG_COOKIE, 0, "PetscDrawHG", comm, PetscDrawHGDestroy, PETSC_NULL);
64: h->view = PETSC_NULL;
65: h->destroy = PETSC_NULL;
66: h->win = draw;
67: PetscObjectReference((PetscObject) draw);
68: h->color = PETSC_DRAW_GREEN;
69: h->xmin = PETSC_MAX;
70: h->xmax = PETSC_MIN;
71: h->ymin = 0.;
72: h->ymax = 1.;
73: h->numBins = bins;
74: h->maxBins = bins;
75: PetscMalloc(h->maxBins * sizeof(PetscReal), &h->bins);
76: h->numValues = 0;
77: h->maxValues = CHUNKSIZE;
78: h->calcStats = PETSC_FALSE;
79: h->integerBins = PETSC_FALSE;
80: PetscMalloc(h->maxValues * sizeof(PetscReal), &h->values);
81: PetscLogObjectMemory(h, (h->maxBins + h->maxValues)*sizeof(PetscReal));
82: PetscTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
83: if (isnull == PETSC_FALSE) {
84: PetscDrawAxisCreate(draw, &h->axis);
85: PetscLogObjectParent(h, h->axis);
86: } else {
87: h->axis = PETSC_NULL;
88: }
89: *hist = h;
90: return(0);
91: }
93: /*@
94: PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn.
96: Not Collective (ignored except on processor 0 of PetscDrawHG)
98: Input Parameter:
99: + hist - The histogram context.
100: - dim - The number of curves.
102: Level: intermediate
104: Contributed by: Matthew Knepley
106: Concepts: histogram^setting number of bins
108: @*/
109: int PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins) {
114: if (hist->maxBins < bins) {
115: PetscFree(hist->bins);
116: PetscMalloc(bins * sizeof(PetscReal), &hist->bins);
117: PetscLogObjectMemory(hist, (bins - hist->maxBins) * sizeof(PetscReal));
118: hist->maxBins = bins;
119: }
120: hist->numBins = bins;
121: return(0);
122: }
124: /*@
125: PetscDrawHGReset - Clears histogram to allow for reuse with new data.
127: Not Collective (ignored except on processor 0 of PetscDrawHG)
129: Input Parameter:
130: . hist - The histogram context.
132: Level: intermediate
134: Contributed by: Matthew Knepley
136: Concepts: histogram^resetting
137: @*/
138: int PetscDrawHGReset(PetscDrawHG hist)
139: {
142: hist->xmin = PETSC_MAX;
143: hist->xmax = PETSC_MIN;
144: hist->ymin = 0;
145: hist->ymax = 0;
146: hist->numValues = 0;
147: return(0);
148: }
150: /*@C
151: PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
153: Collective over PetscDrawHG
155: Input Parameter:
156: . hist - The histogram context
158: Level: intermediate
160: Contributed by: Matthew Knepley
162: .seealso: PetscDrawHGCreate()
163: @*/
164: int PetscDrawHGDestroy(PetscDrawHG hist)
165: {
171: if (--hist->refct > 0) return(0);
172: if (hist->axis != PETSC_NULL) {
173: PetscDrawAxisDestroy(hist->axis);
174: }
175: PetscDrawDestroy(hist->win);
176: PetscFree(hist->bins);
177: PetscFree(hist->values);
178: PetscLogObjectDestroy(hist);
179: PetscHeaderDestroy(hist);
180: return(0);
181: }
183: /*@
184: PetscDrawHGAddValue - Adds another value to the histogram.
186: Not Collective (ignored except on processor 0 of PetscDrawHG)
188: Input Parameters:
189: + hist - The histogram
190: - value - The value
192: Level: intermediate
194: Contributed by: Matthew Knepley
196: Concepts: histogram^adding values
198: .seealso: PetscDrawHGAddValues()
199: @*/
200: int PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
201: {
204: /* Allocate more memory if necessary */
205: if (hist->numValues >= hist->maxValues) {
206: PetscReal *tmp;
207: int ierr;
209: PetscMalloc((hist->maxValues+CHUNKSIZE) * sizeof(PetscReal), &tmp);
210: PetscLogObjectMemory(hist, CHUNKSIZE * sizeof(PetscReal));
211: PetscMemcpy(tmp, hist->values, hist->maxValues * sizeof(PetscReal));
212: PetscFree(hist->values);
213: hist->values = tmp;
214: hist->maxValues += CHUNKSIZE;
215: }
216: /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
217: stated convention of using half-open intervals (always the way to go) */
218: if (!hist->numValues) {
219: hist->xmin = value;
220: hist->xmax = value;
221: #if 1
222: } else {
223: /* Update limits */
224: if (value > hist->xmax)
225: hist->xmax = value;
226: if (value < hist->xmin)
227: hist->xmin = value;
228: #else
229: } else if (hist->numValues == 1) {
230: /* Update limits -- We need to overshoot the largest value somewhat */
231: if (value > hist->xmax) {
232: hist->xmax = value + 0.001*(value - hist->xmin)/hist->numBins;
233: }
234: if (value < hist->xmin) {
235: hist->xmin = value;
236: hist->xmax = hist->xmax + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
237: }
238: } else {
239: /* Update limits -- We need to overshoot the largest value somewhat */
240: if (value > hist->xmax) {
241: hist->xmax = value + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
242: }
243: if (value < hist->xmin) {
244: hist->xmin = value;
245: }
246: #endif
247: }
249: hist->values[hist->numValues++] = value;
250: return(0);
251: }
253: /*@
254: PetscDrawHGDraw - Redraws a histogram.
256: Not Collective (ignored except on processor 0 of PetscDrawHG)
258: Input Parameter:
259: . hist - The histogram context
261: Level: intermediate
263: Contributed by: Matthew Knepley
264: @*/
265: int PetscDrawHGDraw(PetscDrawHG hist)
266: {
267: PetscDraw draw = hist->win;
268: PetscTruth isnull;
269: PetscReal xmin,xmax,ymin,ymax,*bins,*values,binSize,binLeft,binRight,maxHeight,mean,var;
270: char title[256];
271: char xlabel[256];
272: int numBins,numBinsOld,numValues,initSize,i,p,ierr,bcolor,color;
276: PetscTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
277: if (isnull == PETSC_TRUE) return(0);
278: if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
279: if (hist->numValues < 1) return(0);
281: #if 0
282: MPI_Comm_rank(hist->comm,&rank);
283: if (rank) return(0);
284: #endif
286: color = hist->color;
287: if (color == PETSC_DRAW_ROTATE) {bcolor = 2;} else {bcolor = color;}
288: xmin = hist->xmin;
289: xmax = hist->xmax;
290: ymin = hist->ymin;
291: ymax = hist->ymax;
292: numValues = hist->numValues;
293: values = hist->values;
294: mean = 0.0;
295: var = 0.0;
296:
297: PetscDrawClear(draw);
298: if (xmin == xmax) {
299: /* Calculate number of points in each bin */
300: bins = hist->bins;
301: bins[0] = 0;
302: for(p = 0; p < numValues; p++) {
303: if (values[p] == xmin) bins[0]++;
304: mean += values[p];
305: var += values[p]*values[p];
306: }
307: maxHeight = bins[0];
308: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
309: xmax = xmin + 1;
310: PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
311: if (hist->calcStats) {
312: mean /= numValues;
313: if (numValues > 1) {
314: var = (var - numValues*mean*mean) / (numValues-1);
315: } else {
316: var = 0.0;
317: }
318: sprintf(title, "Mean: %g Var: %g", mean, var);
319: sprintf(xlabel, "Total: %d", numValues);
320: ierr = PetscDrawAxisSetLabels(hist->axis, title, xlabel, PETSC_NULL);
321: }
322: PetscDrawAxisDraw(hist->axis);
323: /* Draw bins */
324: binLeft = xmin;
325: binRight = xmax;
326: PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[0],bcolor,bcolor,bcolor,bcolor);
327: if (color == PETSC_DRAW_ROTATE && bins[0]) bcolor++; if (bcolor > 31) bcolor = 2;
328: PetscDrawLine(draw,binLeft,ymin,binLeft,bins[0],PETSC_DRAW_BLACK);
329: PetscDrawLine(draw,binRight,ymin,binRight,bins[0],PETSC_DRAW_BLACK);
330: PetscDrawLine(draw,binLeft,bins[0],binRight,bins[0],PETSC_DRAW_BLACK);
331: } else {
332: numBins = hist->numBins;
333: numBinsOld = hist->numBins;
334: if ((hist->integerBins == PETSC_TRUE) && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
335: initSize = (int) ((int) xmax - xmin)/numBins;
336: while (initSize*numBins != (int) xmax - xmin) {
337: initSize = PetscMax(initSize - 1, 1);
338: numBins = (int) ((int) xmax - xmin)/initSize;
339: ierr = PetscDrawHGSetNumberBins(hist, numBins);
340: }
341: }
342: binSize = (xmax - xmin)/numBins;
343: bins = hist->bins;
345: PetscMemzero(bins, numBins * sizeof(PetscReal));
346: maxHeight = 0;
347: for (i = 0; i < numBins; i++) {
348: binLeft = xmin + binSize*i;
349: binRight = xmin + binSize*(i+1);
350: for(p = 0; p < numValues; p++) {
351: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
352: /* Handle last bin separately */
353: if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
354: if (i == 0) {
355: mean += values[p];
356: var += values[p]*values[p];
357: }
358: }
359: maxHeight = PetscMax(maxHeight, bins[i]);
360: }
361: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
363: PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
364: if (hist->calcStats) {
365: mean /= numValues;
366: if (numValues > 1) {
367: var = (var - numValues*mean*mean) / (numValues-1);
368: } else {
369: var = 0.0;
370: }
371: sprintf(title, "Mean: %g Var: %g", mean, var);
372: sprintf(xlabel, "Total: %d", numValues);
373: ierr = PetscDrawAxisSetLabels(hist->axis, title, xlabel, PETSC_NULL);
374: }
375: PetscDrawAxisDraw(hist->axis);
376: /* Draw bins */
377: for (i = 0; i < numBins; i++) {
378: binLeft = xmin + binSize*i;
379: binRight = xmin + binSize*(i+1);
380: PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[i],bcolor,bcolor,bcolor,bcolor);
381: if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++; if (bcolor > 31) bcolor = 2;
382: PetscDrawLine(draw,binLeft,ymin,binLeft,bins[i],PETSC_DRAW_BLACK);
383: PetscDrawLine(draw,binRight,ymin,binRight,bins[i],PETSC_DRAW_BLACK);
384: PetscDrawLine(draw,binLeft,bins[i],binRight,bins[i],PETSC_DRAW_BLACK);
385: }
386: PetscDrawHGSetNumberBins(hist, numBinsOld);
387: }
388: PetscDrawSynchronizedFlush(draw);
389: PetscDrawPause(draw);
390: return(0);
391: }
393: /*@
394: PetscDrawHGPrint - Prints the histogram information.
396: Not collective
398: Input Parameter:
399: . hist - The histogram context
401: Level: beginner
403: Contributed by: Matthew Knepley
405: .keywords: draw, histogram
406: @*/
407: int PetscDrawHGPrint(PetscDrawHG hist)
408: {
409: PetscReal xmax,xmin,*bins,*values,binSize,binLeft,binRight,mean,var;
410: int numBins,numBinsOld,numValues,initSize,i,p,ierr;
414: if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
415: if (hist->numValues < 1) return(0);
417: xmax = hist->xmax;
418: xmin = hist->xmin;
419: numValues = hist->numValues;
420: values = hist->values;
421: mean = 0.0;
422: var = 0.0;
423: if (xmax == xmin) {
424: /* Calculate number of points in the bin */
425: bins = hist->bins;
426: bins[0] = 0;
427: for(p = 0; p < numValues; p++) {
428: if (values[p] == xmin) bins[0]++;
429: mean += values[p];
430: var += values[p]*values[p];
431: }
432: /* Draw bins */
433: PetscPrintf(hist->comm, "Bin %2d (%6.2g - %6.2g): %.0gn", 0, xmin, xmax, bins[0]);
434: } else {
435: numBins = hist->numBins;
436: numBinsOld = hist->numBins;
437: if ((hist->integerBins == PETSC_TRUE) && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
438: initSize = (int) ((int) xmax - xmin)/numBins;
439: while (initSize*numBins != (int) xmax - xmin) {
440: initSize = PetscMax(initSize - 1, 1);
441: numBins = (int) ((int) xmax - xmin)/initSize;
442: ierr = PetscDrawHGSetNumberBins(hist, numBins);
443: }
444: }
445: binSize = (xmax - xmin)/numBins;
446: bins = hist->bins;
448: /* Calculate number of points in each bin */
449: PetscMemzero(bins, numBins * sizeof(PetscReal));
450: for (i = 0; i < numBins; i++) {
451: binLeft = xmin + binSize*i;
452: binRight = xmin + binSize*(i+1);
453: for(p = 0; p < numValues; p++) {
454: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
455: /* Handle last bin separately */
456: if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
457: if (i == 0) {
458: mean += values[p];
459: var += values[p]*values[p];
460: }
461: }
462: }
463: /* Draw bins */
464: for (i = 0; i < numBins; i++) {
465: binLeft = xmin + binSize*i;
466: binRight = xmin + binSize*(i+1);
467: PetscPrintf(hist->comm, "Bin %2d (%6.2g - %6.2g): %.0gn", i, binLeft, binRight, bins[i]);
468: }
469: PetscDrawHGSetNumberBins(hist, numBinsOld);
470: }
472: if (hist->calcStats) {
473: mean /= numValues;
474: if (numValues > 1) {
475: var = (var - numValues*mean*mean) / (numValues-1);
476: } else {
477: var = 0.0;
478: }
479: PetscPrintf(hist->comm, "Mean: %g Var: %gn", mean, var);
480: PetscPrintf(hist->comm, "Total: %dn", numValues);
481: }
482: return(0);
483: }
484:
485: /*@
486: PetscDrawHGSetColor - Sets the color the bars will be drawn with.
488: Not Collective (ignored except on processor 0 of PetscDrawHG)
490: Input Parameters:
491: + hist - The histogram context
492: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
493: different color
495: Level: intermediate
497: @*/
498: int PetscDrawHGSetColor(PetscDrawHG hist, int color)
499: {
502: hist->color = color;
503: return(0);
504: }
506: /*@
507: PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
508: points are added after this call, the limits will be adjusted to
509: include those additional points.
511: Not Collective (ignored except on processor 0 of PetscDrawHG)
513: Input Parameters:
514: + hist - The histogram context
515: - x_min,x_max,y_min,y_max - The limits
517: Level: intermediate
519: Contributed by: Matthew Knepley
521: Concepts: histogram^setting axis
522: @*/
523: int PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
524: {
527: hist->xmin = x_min;
528: hist->xmax = x_max;
529: hist->ymin = y_min;
530: hist->ymax = y_max;
531: return(0);
532: }
534: /*@
535: PetscDrawHGCalcStats - Turns on calculation of descriptive statistics
537: Not collective
539: Input Parameters:
540: + hist - The histogram context
541: - calc - Flag for calculation
543: Level: intermediate
545: Contributed by: Matthew Knepley
547: .keywords: draw, histogram, statistics
549: @*/
550: int PetscDrawHGCalcStats(PetscDrawHG hist, PetscTruth calc)
551: {
554: hist->calcStats = calc;
555: return(0);
556: }
558: /*@
559: PetscDrawHGIntegerBins - Turns on integer width bins
561: Not collective
563: Input Parameters:
564: + hist - The histogram context
565: - ints - Flag for integer width bins
567: Level: intermediate
569: Contributed by: Matthew Knepley
571: .keywords: draw, histogram, statistics
572: @*/
573: int PetscDrawHGIntegerBins(PetscDrawHG hist, PetscTruth ints)
574: {
577: hist->integerBins = ints;
578: return(0);
579: }
581: /*@C
582: PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
583: This is useful if one wants to change some axis property, such as
584: labels, color, etc. The axis context should not be destroyed by the
585: application code.
587: Not Collective (ignored except on processor 0 of PetscDrawHG)
589: Input Parameter:
590: . hist - The histogram context
592: Output Parameter:
593: . axis - The axis context
595: Level: intermediate
597: Contributed by: Matthew Knepley
598: @*/
599: int PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
600: {
603: *axis = hist->axis;
604: return(0);
605: }
607: /*@C
608: PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
610: Not Collective, PetscDraw is parallel if PetscDrawHG is parallel
612: Input Parameter:
613: . hist - The histogram context
615: Output Parameter:
616: . win - The draw context
618: Level: intermediate
620: Contributed by: Matthew Knepley
621: @*/
622: int PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *win)
623: {
626: *win = hist->win;
627: return(0);
628: }