Actual source code: hists.c
petsc-3.5.4 2015-05-23
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*/
9: PetscClassId PETSC_DRAWHG_CLASSID = 0;
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: };
30: #define CHUNKSIZE 100
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: Concepts: histogram^creating
50: .seealso: PetscDrawHGDestroy()
52: @*/
53: PetscErrorCode PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist)
54: {
55: PetscDrawHG h;
56: MPI_Comm comm;
57: PetscBool isnull;
63: PetscObjectGetComm((PetscObject) draw, &comm);
64: PetscHeaderCreate(h, _p_PetscDrawHG, int, PETSC_DRAWHG_CLASSID, "PetscDrawHG", "Histogram", "Draw", comm, PetscDrawHGDestroy, NULL);
66: h->view = NULL;
67: h->destroy = NULL;
68: h->win = draw;
70: PetscObjectReference((PetscObject) draw);
72: h->color = PETSC_DRAW_GREEN;
73: h->xmin = PETSC_MAX_REAL;
74: h->xmax = PETSC_MIN_REAL;
75: h->ymin = 0.;
76: h->ymax = 1.;
77: h->numBins = bins;
78: h->maxBins = bins;
80: PetscMalloc1(h->maxBins, &h->bins);
82: h->numValues = 0;
83: h->maxValues = CHUNKSIZE;
84: h->calcStats = PETSC_FALSE;
85: h->integerBins = PETSC_FALSE;
87: PetscMalloc1(h->maxValues, &h->values);
88: PetscLogObjectMemory((PetscObject)h, (h->maxBins + h->maxValues)*sizeof(PetscReal));
89: PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
91: if (!isnull) {
92: PetscDrawAxisCreate(draw, &h->axis);
93: PetscLogObjectParent((PetscObject)h, (PetscObject)h->axis);
94: } else h->axis = NULL;
95: *hist = h;
96: return(0);
97: }
101: /*@
102: PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn.
104: Not Collective (ignored except on processor 0 of PetscDrawHG)
106: Input Parameter:
107: + hist - The histogram context.
108: - dim - The number of curves.
110: Level: intermediate
112: Concepts: histogram^setting number of bins
114: @*/
115: PetscErrorCode PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins)
116: {
121: if (hist->maxBins < bins) {
122: PetscFree(hist->bins);
123: PetscMalloc1(bins, &hist->bins);
124: PetscLogObjectMemory((PetscObject)hist, (bins - hist->maxBins) * sizeof(PetscReal));
126: hist->maxBins = bins;
127: }
128: hist->numBins = bins;
129: return(0);
130: }
134: /*@
135: PetscDrawHGReset - Clears histogram to allow for reuse with new data.
137: Not Collective (ignored except on processor 0 of PetscDrawHG)
139: Input Parameter:
140: . hist - The histogram context.
142: Level: intermediate
144: Concepts: histogram^resetting
145: @*/
146: PetscErrorCode PetscDrawHGReset(PetscDrawHG hist)
147: {
150: hist->xmin = PETSC_MAX_REAL;
151: hist->xmax = PETSC_MIN_REAL;
152: hist->ymin = 0.0;
153: hist->ymax = 0.0;
154: hist->numValues = 0;
155: return(0);
156: }
160: /*@C
161: PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
163: Collective over PetscDrawHG
165: Input Parameter:
166: . hist - The histogram context
168: Level: intermediate
170: .seealso: PetscDrawHGCreate()
171: @*/
172: PetscErrorCode PetscDrawHGDestroy(PetscDrawHG *hist)
173: {
177: if (!*hist) return(0);
180: if (--((PetscObject)(*hist))->refct > 0) return(0);
181: PetscDrawAxisDestroy(&(*hist)->axis);
182: PetscDrawDestroy(&(*hist)->win);
183: PetscFree((*hist)->bins);
184: PetscFree((*hist)->values);
185: PetscHeaderDestroy(hist);
186: return(0);
187: }
191: /*@
192: PetscDrawHGAddValue - Adds another value to the histogram.
194: Not Collective (ignored except on processor 0 of PetscDrawHG)
196: Input Parameters:
197: + hist - The histogram
198: - value - The value
200: Level: intermediate
202: Concepts: histogram^adding values
204: .seealso: PetscDrawHGAddValues()
205: @*/
206: PetscErrorCode PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
207: {
210: /* Allocate more memory if necessary */
211: if (hist->numValues >= hist->maxValues) {
212: PetscReal *tmp;
215: PetscMalloc1((hist->maxValues+CHUNKSIZE), &tmp);
216: PetscLogObjectMemory((PetscObject)hist, CHUNKSIZE * sizeof(PetscReal));
217: PetscMemcpy(tmp, hist->values, hist->maxValues * sizeof(PetscReal));
218: PetscFree(hist->values);
220: hist->values = tmp;
221: hist->maxValues += CHUNKSIZE;
222: }
223: /* I disagree with the original Petsc implementation here. There should be no overshoot, but rather the
224: stated convention of using half-open intervals (always the way to go) */
225: if (!hist->numValues) {
226: hist->xmin = value;
227: hist->xmax = value;
228: #if 1
229: } else {
230: /* Update limits */
231: if (value > hist->xmax) hist->xmax = value;
232: if (value < hist->xmin) hist->xmin = value;
233: #else
234: } else if (hist->numValues == 1) {
235: /* Update limits -- We need to overshoot the largest value somewhat */
236: if (value > hist->xmax) hist->xmax = value + 0.001*(value - hist->xmin)/hist->numBins;
237: if (value < hist->xmin) {
238: hist->xmin = value;
239: hist->xmax = hist->xmax + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
240: }
241: } else {
242: /* Update limits -- We need to overshoot the largest value somewhat */
243: if (value > hist->xmax) hist->xmax = value + 0.001*(hist->xmax - hist->xmin)/hist->numBins;
244: if (value < hist->xmin) hist->xmin = value;
245: #endif
246: }
248: hist->values[hist->numValues++] = value;
249: return(0);
250: }
254: /*@
255: PetscDrawHGDraw - Redraws a histogram.
257: Not Collective (ignored except on processor 0 of PetscDrawHG)
259: Input Parameter:
260: . hist - The histogram context
262: Level: intermediate
264: @*/
265: PetscErrorCode PetscDrawHGDraw(PetscDrawHG hist)
266: {
267: PetscDraw draw = hist->win;
268: PetscBool isnull;
269: PetscReal xmin,xmax,ymin,ymax,*bins,*values,binSize,binLeft,binRight,maxHeight,mean,var;
270: char title[256];
271: char xlabel[256];
272: PetscInt numBins,numBinsOld,numValues,initSize,i,p,bcolor,color;
277: PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
278: if (isnull) return(0);
279: if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
280: if (hist->numValues < 1) return(0);
282: #if 0
283: MPI_Comm_rank(PetscObjectComm((PetscObject)hist),&rank);
284: if (rank) return(0);
285: #endif
287: color = hist->color;
288: if (color == PETSC_DRAW_ROTATE) bcolor = 2;
289: else bcolor = color;
291: xmin = hist->xmin;
292: xmax = hist->xmax;
293: ymin = hist->ymin;
294: ymax = hist->ymax;
295: numValues = hist->numValues;
296: values = hist->values;
297: mean = 0.0;
298: var = 0.0;
300: PetscDrawClear(draw);
301: if (xmin == xmax) {
302: /* Calculate number of points in each bin */
303: bins = hist->bins;
304: bins[0] = 0.;
305: for (p = 0; p < numValues; p++) {
306: if (values[p] == xmin) bins[0]++;
307: mean += values[p];
308: var += values[p]*values[p];
309: }
310: maxHeight = bins[0];
311: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
312: xmax = xmin + 1;
313: PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
314: if (hist->calcStats) {
315: mean /= numValues;
316: if (numValues > 1) var = (var - numValues*mean*mean) / (numValues-1);
317: else var = 0.0;
318: PetscSNPrintf(title, 256, "Mean: %g Var: %g", (double)mean, (double)var);
319: PetscSNPrintf(xlabel,256, "Total: %D", numValues);
320: PetscDrawAxisSetLabels(hist->axis, title, xlabel, 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);
328: if (color == PETSC_DRAW_ROTATE && bins[0] != 0.0) bcolor++;
329: if (bcolor > 31) bcolor = 2;
331: PetscDrawLine(draw,binLeft,ymin,binLeft,bins[0],PETSC_DRAW_BLACK);
332: PetscDrawLine(draw,binRight,ymin,binRight,bins[0],PETSC_DRAW_BLACK);
333: PetscDrawLine(draw,binLeft,bins[0],binRight,bins[0],PETSC_DRAW_BLACK);
334: } else {
335: numBins = hist->numBins;
336: numBinsOld = hist->numBins;
337: if (hist->integerBins && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
338: initSize = (int) ((int) xmax - xmin)/numBins;
339: while (initSize*numBins != (int) xmax - xmin) {
340: initSize = PetscMax(initSize - 1, 1);
341: numBins = (int) ((int) xmax - xmin)/initSize;
342: PetscDrawHGSetNumberBins(hist, numBins);
343: }
344: }
345: binSize = (xmax - xmin)/numBins;
346: bins = hist->bins;
348: PetscMemzero(bins, numBins * sizeof(PetscReal));
350: maxHeight = 0.0;
351: for (i = 0; i < numBins; i++) {
352: binLeft = xmin + binSize*i;
353: binRight = xmin + binSize*(i+1);
354: for (p = 0; p < numValues; p++) {
355: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
356: /* Handle last bin separately */
357: if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
358: if (!i) {
359: mean += values[p];
360: var += values[p]*values[p];
361: }
362: }
363: maxHeight = PetscMax(maxHeight, bins[i]);
364: }
365: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
367: PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax);
368: if (hist->calcStats) {
369: mean /= numValues;
370: if (numValues > 1) var = (var - numValues*mean*mean) / (numValues-1);
371: else var = 0.0;
373: PetscSNPrintf(title, 256,"Mean: %g Var: %g", (double)mean, (double)var);
374: PetscSNPrintf(xlabel,256, "Total: %D", numValues);
375: PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL);
376: }
377: PetscDrawAxisDraw(hist->axis);
378: /* Draw bins */
379: for (i = 0; i < numBins; i++) {
380: binLeft = xmin + binSize*i;
381: binRight = xmin + binSize*(i+1);
382: PetscDrawRectangle(draw,binLeft,ymin,binRight,bins[i],bcolor,bcolor,bcolor,bcolor);
383: if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++;
384: if (bcolor > 31) bcolor = 2;
385: PetscDrawLine(draw,binLeft,ymin,binLeft,bins[i],PETSC_DRAW_BLACK);
386: PetscDrawLine(draw,binRight,ymin,binRight,bins[i],PETSC_DRAW_BLACK);
387: PetscDrawLine(draw,binLeft,bins[i],binRight,bins[i],PETSC_DRAW_BLACK);
388: }
389: PetscDrawHGSetNumberBins(hist, numBinsOld);
390: }
391: PetscDrawSynchronizedFlush(draw);
392: PetscDrawPause(draw);
393: return(0);
394: }
398: /*@
399: PetscDrawHGView - Prints the histogram information.
401: Not collective
403: Input Parameter:
404: . hist - The histogram context
406: Level: beginner
408: .keywords: draw, histogram
409: @*/
410: PetscErrorCode PetscDrawHGView(PetscDrawHG hist,PetscViewer viewer)
411: {
412: PetscReal xmax,xmin,*bins,*values,binSize,binLeft,binRight,mean,var;
414: PetscInt numBins,numBinsOld,numValues,initSize,i,p;
418: if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) return(0);
419: if (hist->numValues < 1) return(0);
421: if (!viewer){
422: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist),&viewer);
423: }
424: PetscObjectPrintClassNamePrefixType((PetscObject)hist,viewer);
425: xmax = hist->xmax;
426: xmin = hist->xmin;
427: numValues = hist->numValues;
428: values = hist->values;
429: mean = 0.0;
430: var = 0.0;
431: if (xmax == xmin) {
432: /* Calculate number of points in the bin */
433: bins = hist->bins;
434: bins[0] = 0.;
435: for (p = 0; p < numValues; p++) {
436: if (values[p] == xmin) bins[0]++;
437: mean += values[p];
438: var += values[p]*values[p];
439: }
440: /* Draw bins */
441: PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]);
442: } else {
443: numBins = hist->numBins;
444: numBinsOld = hist->numBins;
445: if (hist->integerBins && (((int) xmax - xmin) + 1.0e-05 > xmax - xmin)) {
446: initSize = (int) ((int) xmax - xmin)/numBins;
447: while (initSize*numBins != (int) xmax - xmin) {
448: initSize = PetscMax(initSize - 1, 1);
449: numBins = (int) ((int) xmax - xmin)/initSize;
450: PetscDrawHGSetNumberBins(hist, numBins);
451: }
452: }
453: binSize = (xmax - xmin)/numBins;
454: bins = hist->bins;
456: /* Calculate number of points in each bin */
457: PetscMemzero(bins, numBins * sizeof(PetscReal));
458: for (i = 0; i < numBins; i++) {
459: binLeft = xmin + binSize*i;
460: binRight = xmin + binSize*(i+1);
461: for (p = 0; p < numValues; p++) {
462: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i]++;
463: /* Handle last bin separately */
464: if ((i == numBins-1) && (values[p] == binRight)) bins[i]++;
465: if (!i) {
466: mean += values[p];
467: var += values[p]*values[p];
468: }
469: }
470: }
471: /* Draw bins */
472: for (i = 0; i < numBins; i++) {
473: binLeft = xmin + binSize*i;
474: binRight = xmin + binSize*(i+1);
475: PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", (int)i, (double)binLeft, (double)binRight, (double)bins[i]);
476: }
477: PetscDrawHGSetNumberBins(hist, numBinsOld);
478: }
480: if (hist->calcStats) {
481: mean /= numValues;
482: if (numValues > 1) var = (var - numValues*mean*mean) / (numValues-1);
483: else var = 0.0;
484: PetscViewerASCIIPrintf(viewer, "Mean: %g Var: %g\n", (double)mean, (double)var);
485: PetscViewerASCIIPrintf(viewer, "Total: %D\n", numValues);
486: }
487: return(0);
488: }
492: /*@
493: PetscDrawHGSetColor - Sets the color the bars will be drawn with.
495: Not Collective (ignored except on processor 0 of PetscDrawHG)
497: Input Parameters:
498: + hist - The histogram context
499: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
500: different color
502: Level: intermediate
504: @*/
505: PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color)
506: {
509: hist->color = color;
510: return(0);
511: }
515: /*@
516: PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
517: points are added after this call, the limits will be adjusted to
518: include those additional points.
520: Not Collective (ignored except on processor 0 of PetscDrawHG)
522: Input Parameters:
523: + hist - The histogram context
524: - x_min,x_max,y_min,y_max - The limits
526: Level: intermediate
528: Concepts: histogram^setting axis
529: @*/
530: PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
531: {
534: hist->xmin = x_min;
535: hist->xmax = x_max;
536: hist->ymin = y_min;
537: hist->ymax = y_max;
538: return(0);
539: }
543: /*@
544: PetscDrawHGCalcStats - Turns on calculation of descriptive statistics
546: Not collective
548: Input Parameters:
549: + hist - The histogram context
550: - calc - Flag for calculation
552: Level: intermediate
554: .keywords: draw, histogram, statistics
556: @*/
557: PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
558: {
561: hist->calcStats = calc;
562: return(0);
563: }
567: /*@
568: PetscDrawHGIntegerBins - Turns on integer width bins
570: Not collective
572: Input Parameters:
573: + hist - The histogram context
574: - ints - Flag for integer width bins
576: Level: intermediate
578: .keywords: draw, histogram, statistics
579: @*/
580: PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
581: {
584: hist->integerBins = ints;
585: return(0);
586: }
590: /*@C
591: PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
592: This is useful if one wants to change some axis property, such as
593: labels, color, etc. The axis context should not be destroyed by the
594: application code.
596: Not Collective (ignored except on processor 0 of PetscDrawHG)
598: Input Parameter:
599: . hist - The histogram context
601: Output Parameter:
602: . axis - The axis context
604: Level: intermediate
606: @*/
607: PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
608: {
612: *axis = hist->axis;
613: return(0);
614: }
618: /*@C
619: PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
621: Not Collective, PetscDraw is parallel if PetscDrawHG is parallel
623: Input Parameter:
624: . hist - The histogram context
626: Output Parameter:
627: . win - The draw context
629: Level: intermediate
631: @*/
632: PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *win)
633: {
637: *win = hist->win;
638: return(0);
639: }