Actual source code: hists.c
1: /*
2: Contains the data structure for plotting a histogram in a window with an axis.
3: */
4: #include <petscdraw.h>
5: #include <petsc/private/petscimpl.h>
7: PetscClassId PETSC_DRAWHG_CLASSID = 0;
9: struct _p_PetscDrawHG {
10: PETSCHEADER(int);
11: PetscErrorCode (*destroy)(PetscDrawSP);
12: PetscErrorCode (*view)(PetscDrawSP, PetscViewer);
13: PetscDraw win;
14: PetscDrawAxis axis;
15: PetscReal xmin, xmax;
16: PetscReal ymin, ymax;
17: int numBins;
18: int maxBins;
19: PetscReal *bins;
20: int numValues;
21: int maxValues;
22: PetscReal *values;
23: PetscReal *weights;
24: int color;
25: PetscBool calcStats;
26: PetscBool integerBins;
27: };
29: #define CHUNKSIZE 100
31: /*@
32: PetscDrawHGCreate - Creates a histogram data structure.
34: Collective
36: Input Parameters:
37: + draw - The window where the graph will be made
38: - bins - The number of bins to use
40: Output Parameter:
41: . hist - The histogram context
43: Level: intermediate
45: Notes:
46: The difference between a bar chart, `PetscDrawBar`, and a histogram, `PetscDrawHG`, is explained here <https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP>
48: The histogram is only displayed when `PetscDrawHGDraw()` is called.
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.
53: .seealso: `PetscDrawHGDestroy()`, `PetscDrawHG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawSPCreate()`, `PetscDrawSP`,
54: `PetscDrawHGSetNumberBins()`, `PetscDrawHGReset()`, `PetscDrawHGAddValue()`, `PetscDrawHGDraw()`, `PetscDrawHGSave()`, `PetscDrawHGView()`, `PetscDrawHGSetColor()`,
55: `PetscDrawHGSetLimits()`, `PetscDrawHGCalcStats()`, `PetscDrawHGIntegerBins()`, `PetscDrawHGGetAxis()`, `PetscDrawAxis`, `PetscDrawHGGetDraw()`
56: @*/
57: PetscErrorCode PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist)
58: {
59: PetscDrawHG h;
61: PetscFunctionBegin;
64: PetscAssertPointer(hist, 3);
66: PetscCall(PetscHeaderCreate(h, PETSC_DRAWHG_CLASSID, "DrawHG", "Histogram", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawHGDestroy, NULL));
67: PetscCall(PetscObjectReference((PetscObject)draw));
68: h->win = draw;
69: h->view = NULL;
70: h->destroy = NULL;
71: h->color = PETSC_DRAW_GREEN;
72: h->xmin = PETSC_MAX_REAL;
73: h->xmax = PETSC_MIN_REAL;
74: h->ymin = 0.;
75: h->ymax = 1.e-6;
76: h->numBins = bins;
77: h->maxBins = bins;
78: PetscCall(PetscMalloc1(h->maxBins, &h->bins));
79: h->numValues = 0;
80: h->maxValues = CHUNKSIZE;
81: h->calcStats = PETSC_FALSE;
82: h->integerBins = PETSC_FALSE;
83: PetscCall(PetscMalloc2(h->maxValues, &h->values, h->maxValues, &h->weights));
84: PetscCall(PetscDrawAxisCreate(draw, &h->axis));
85: *hist = h;
86: PetscFunctionReturn(PETSC_SUCCESS);
87: }
89: /*@
90: PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn in the histogram
92: Logically Collective
94: Input Parameters:
95: + hist - The histogram context.
96: - bins - The number of bins.
98: Level: intermediate
100: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGIntegerBins()`
101: @*/
102: PetscErrorCode PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins)
103: {
104: PetscFunctionBegin;
108: if (hist->maxBins < bins) {
109: PetscCall(PetscFree(hist->bins));
110: PetscCall(PetscMalloc1(bins, &hist->bins));
111: hist->maxBins = bins;
112: }
113: hist->numBins = bins;
114: PetscFunctionReturn(PETSC_SUCCESS);
115: }
117: /*@
118: PetscDrawHGReset - Clears histogram to allow for reuse with new data.
120: Logically Collective
122: Input Parameter:
123: . hist - The histogram context.
125: Level: intermediate
127: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`
128: @*/
129: PetscErrorCode PetscDrawHGReset(PetscDrawHG hist)
130: {
131: PetscFunctionBegin;
134: hist->xmin = PETSC_MAX_REAL;
135: hist->xmax = PETSC_MIN_REAL;
136: hist->ymin = 0.0;
137: hist->ymax = 1.e-6;
138: hist->numValues = 0;
139: PetscFunctionReturn(PETSC_SUCCESS);
140: }
142: /*@
143: PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
145: Collective
147: Input Parameter:
148: . hist - The histogram context
150: Level: intermediate
152: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`
153: @*/
154: PetscErrorCode PetscDrawHGDestroy(PetscDrawHG *hist)
155: {
156: PetscFunctionBegin;
157: if (!*hist) PetscFunctionReturn(PETSC_SUCCESS);
159: if (--((PetscObject)*hist)->refct > 0) {
160: *hist = NULL;
161: PetscFunctionReturn(PETSC_SUCCESS);
162: }
164: PetscCall(PetscFree((*hist)->bins));
165: PetscCall(PetscFree2((*hist)->values, (*hist)->weights));
166: PetscCall(PetscDrawAxisDestroy(&(*hist)->axis));
167: PetscCall(PetscDrawDestroy(&(*hist)->win));
168: PetscCall(PetscHeaderDestroy(hist));
169: PetscFunctionReturn(PETSC_SUCCESS);
170: }
172: /*@
173: PetscDrawHGAddValue - Adds another value to the histogram.
175: Logically Collective
177: Input Parameters:
178: + hist - The histogram
179: - value - The value
181: Level: intermediate
183: Note:
184: Calls to this function are used to create a standard histogram with integer bin heights. Use calls to `PetscDrawHGAddWeightedValue()` to create a histogram with non-integer bin heights.
186: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGReset()`, `PetscDrawHGAddWeightedValue()`
187: @*/
188: PetscErrorCode PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
189: {
190: PetscFunctionBegin;
193: /* Allocate more memory if necessary */
194: if (hist->numValues >= hist->maxValues) {
195: PetscReal *tmp, *tmpw;
197: PetscCall(PetscMalloc2(hist->maxValues + CHUNKSIZE, &tmp, hist->maxValues + CHUNKSIZE, &tmpw));
198: PetscCall(PetscArraycpy(tmp, hist->values, hist->maxValues));
199: PetscCall(PetscArraycpy(tmpw, hist->weights, hist->maxValues));
200: PetscCall(PetscFree2(hist->values, hist->weights));
202: hist->values = tmp;
203: hist->weights = tmpw;
204: hist->maxValues += CHUNKSIZE;
205: }
206: /* I disagree with the original PETSc implementation here. There should be no overshoot, but rather the
207: stated convention of using half-open intervals (always the way to go) */
208: if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
209: hist->xmin = value;
210: hist->xmax = value;
211: #if 1
212: } else {
213: /* Update limits */
214: if (value > hist->xmax) hist->xmax = value;
215: if (value < hist->xmin) hist->xmin = value;
216: #else
217: } else if (hist->numValues == 1) {
218: /* Update limits -- We need to overshoot the largest value somewhat */
219: if (value > hist->xmax) hist->xmax = value + 0.001 * (value - hist->xmin) / (PetscReal)hist->numBins;
220: if (value < hist->xmin) {
221: hist->xmin = value;
222: hist->xmax = hist->xmax + 0.001 * (hist->xmax - hist->xmin) / (PetscReal)hist->numBins;
223: }
224: } else {
225: /* Update limits -- We need to overshoot the largest value somewhat */
226: if (value > hist->xmax) hist->xmax = value + 0.001 * (hist->xmax - hist->xmin) / (PetscReal)hist->numBins;
227: if (value < hist->xmin) hist->xmin = value;
228: #endif
229: }
231: hist->values[hist->numValues] = value;
232: hist->weights[hist->numValues] = 1.;
233: ++hist->numValues;
234: PetscFunctionReturn(PETSC_SUCCESS);
235: }
237: /*@
238: PetscDrawHGAddWeightedValue - Adds another value to the histogram with a weight.
240: Logically Collective
242: Input Parameters:
243: + hist - The histogram
244: . value - The value
245: - weight - The value weight
247: Level: intermediate
249: Notes:
250: Calls to this function are used to create a histogram with non-integer bin heights. Use calls to `PetscDrawHGAddValue()` to create a standard histogram with integer bin heights.
252: This allows us to histogram frequency and probability distributions (<https://learnche.org/pid/univariate-review/histograms-and-probability-distributions>). We can use this to look at particle weight distributions in Particle-in-Cell (PIC) methods, for example.
254: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGReset()`, `PetscDrawHGAddValue()`
255: @*/
256: PetscErrorCode PetscDrawHGAddWeightedValue(PetscDrawHG hist, PetscReal value, PetscReal weight)
257: {
258: PetscFunctionBegin;
261: /* Allocate more memory if necessary */
262: if (hist->numValues >= hist->maxValues) {
263: PetscReal *tmp, *tmpw;
265: PetscCall(PetscMalloc2(hist->maxValues + CHUNKSIZE, &tmp, hist->maxValues + CHUNKSIZE, &tmpw));
266: PetscCall(PetscArraycpy(tmp, hist->values, hist->maxValues));
267: PetscCall(PetscArraycpy(tmpw, hist->weights, hist->maxValues));
268: PetscCall(PetscFree2(hist->values, hist->weights));
270: hist->values = tmp;
271: hist->weights = tmpw;
272: hist->maxValues += CHUNKSIZE;
273: }
274: /* I disagree with the original PETSc implementation here. There should be no overshoot, but rather the
275: stated convention of using half-open intervals (always the way to go) */
276: if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
277: hist->xmin = value;
278: hist->xmax = value;
279: } else {
280: /* Update limits */
281: if (value > hist->xmax) hist->xmax = value;
282: if (value < hist->xmin) hist->xmin = value;
283: }
285: hist->values[hist->numValues] = value;
286: hist->weights[hist->numValues] = weight;
287: ++hist->numValues;
288: PetscFunctionReturn(PETSC_SUCCESS);
289: }
291: /*@
292: PetscDrawHGDraw - Redraws a histogram.
294: Collective
296: Input Parameter:
297: . hist - The histogram context
299: Level: intermediate
301: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGAddValue()`, `PetscDrawHGReset()`
302: @*/
303: PetscErrorCode PetscDrawHGDraw(PetscDrawHG hist)
304: {
305: PetscDraw draw;
306: PetscBool isnull, usewt = PETSC_FALSE;
307: PetscReal xmin, xmax, ymin, ymax, *bins, *values, *weights, binSize, binLeft, binRight, maxHeight, mean, var, totwt = 0.;
308: char title[256];
309: char xlabel[256];
310: PetscInt numValues, initSize, i, p;
311: int bcolor, color, numBins, numBinsOld;
312: PetscMPIInt rank;
314: PetscFunctionBegin;
316: PetscCall(PetscDrawIsNull(hist->win, &isnull));
317: if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
318: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)hist), &rank));
320: if (hist->xmin >= hist->xmax || hist->ymin >= hist->ymax) PetscFunctionReturn(PETSC_SUCCESS);
321: if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
323: color = hist->color;
324: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK + 1;
325: else bcolor = color;
327: xmin = hist->xmin;
328: xmax = hist->xmax;
329: ymin = hist->ymin;
330: ymax = hist->ymax;
331: numValues = hist->numValues;
332: values = hist->values;
333: weights = hist->weights;
334: mean = 0.0;
335: var = 0.0;
337: draw = hist->win;
338: PetscCall(PetscDrawCheckResizedWindow(draw));
339: PetscCall(PetscDrawClear(draw));
341: if (xmin == xmax) {
342: /* Calculate number of points in each bin */
343: bins = hist->bins;
344: bins[0] = 0.;
345: for (p = 0; p < numValues; p++) {
346: if (values[p] == xmin) bins[0] += weights[0];
347: mean += values[p] * weights[p];
348: var += values[p] * values[p] * weights[p];
349: totwt += weights[p];
350: if (weights[p] != 1.) usewt = PETSC_TRUE;
351: }
352: maxHeight = bins[0];
353: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
354: xmax = xmin + 1;
355: PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
356: if (hist->calcStats) {
357: if (usewt) {
358: mean /= totwt;
359: var = (var - totwt * mean * mean) / totwt;
361: PetscCall(PetscSNPrintf(xlabel, 256, "Total Weight: %g", (double)totwt));
362: } else {
363: mean /= numValues;
364: if (numValues > 1) var = (var - numValues * mean * mean) / (PetscReal)(numValues - 1);
365: else var = 0.0;
367: PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
368: }
369: PetscCall(PetscSNPrintf(title, 256, "Mean: %g Var: %g", (double)mean, (double)var));
370: PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
371: }
372: PetscCall(PetscDrawAxisDraw(hist->axis));
373: PetscDrawCollectiveBegin(draw);
374: if (rank == 0) { /* Draw bins */
375: binLeft = xmin;
376: binRight = xmax;
377: PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[0], bcolor, bcolor, bcolor, bcolor));
378: PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[0], PETSC_DRAW_BLACK));
379: PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[0], PETSC_DRAW_BLACK));
380: PetscCall(PetscDrawLine(draw, binLeft, bins[0], binRight, bins[0], PETSC_DRAW_BLACK));
381: }
382: PetscDrawCollectiveEnd(draw);
383: } else {
384: numBins = hist->numBins;
385: numBinsOld = hist->numBins;
386: if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
387: initSize = ((int)(xmax - xmin)) / numBins;
388: while (initSize * numBins != (int)xmax - xmin) {
389: initSize = PetscMax(initSize - 1, 1);
390: numBins = ((int)(xmax - xmin)) / initSize;
391: PetscCall(PetscDrawHGSetNumberBins(hist, numBins));
392: }
393: }
394: binSize = (xmax - xmin) / (PetscReal)numBins;
395: bins = hist->bins;
397: PetscCall(PetscArrayzero(bins, numBins));
399: maxHeight = 0.0;
400: for (i = 0; i < numBins; i++) {
401: binLeft = xmin + binSize * i;
402: binRight = xmin + binSize * (i + 1);
403: for (p = 0; p < numValues; p++) {
404: if (values[p] >= binLeft && values[p] < binRight) bins[i] += weights[p];
405: /* Handle last bin separately */
406: if (i == numBins - 1 && values[p] == binRight) bins[i] += weights[p];
407: if (!i) {
408: mean += values[p] * weights[p];
409: var += values[p] * values[p] * weights[p];
410: totwt += weights[p];
411: if (weights[p] != 1.) usewt = PETSC_TRUE;
412: }
413: }
414: maxHeight = PetscMax(maxHeight, bins[i]);
415: }
416: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
418: PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
419: if (hist->calcStats) {
420: if (usewt) {
421: mean /= totwt;
422: var = (var - totwt * mean * mean) / totwt;
424: PetscCall(PetscSNPrintf(xlabel, 256, "Total Weight: %g", (double)totwt));
425: } else {
426: mean /= numValues;
427: if (numValues > 1) var = (var - numValues * mean * mean) / (PetscReal)(numValues - 1);
428: else var = 0.0;
430: PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
431: }
432: PetscCall(PetscSNPrintf(title, 256, "Mean: %g Var: %g", (double)mean, (double)var));
433: PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
434: }
435: PetscCall(PetscDrawAxisDraw(hist->axis));
436: PetscDrawCollectiveBegin(draw);
437: if (rank == 0) { /* Draw bins */
438: for (i = 0; i < numBins; i++) {
439: binLeft = xmin + binSize * i;
440: binRight = xmin + binSize * (i + 1);
441: PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[i], bcolor, bcolor, bcolor, bcolor));
442: PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[i], PETSC_DRAW_BLACK));
443: PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[i], PETSC_DRAW_BLACK));
444: PetscCall(PetscDrawLine(draw, binLeft, bins[i], binRight, bins[i], PETSC_DRAW_BLACK));
445: if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++;
446: if (bcolor > PETSC_DRAW_BASIC_COLORS - 1) bcolor = PETSC_DRAW_BLACK + 1;
447: }
448: }
449: PetscDrawCollectiveEnd(draw);
450: PetscCall(PetscDrawHGSetNumberBins(hist, numBinsOld));
451: }
453: PetscCall(PetscDrawFlush(draw));
454: PetscCall(PetscDrawPause(draw));
455: PetscFunctionReturn(PETSC_SUCCESS);
456: }
458: /*@
459: PetscDrawHGSave - Saves a drawn image
461: Collective
463: Input Parameter:
464: . hg - The histogram context
466: Level: intermediate
468: .seealso: `PetscDrawSave()`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawHGDraw()`
469: @*/
470: PetscErrorCode PetscDrawHGSave(PetscDrawHG hg)
471: {
472: PetscFunctionBegin;
474: PetscCall(PetscDrawSave(hg->win));
475: PetscFunctionReturn(PETSC_SUCCESS);
476: }
478: /*@
479: PetscDrawHGView - Prints the histogram information to a viewer
481: Not Collective
483: Input Parameters:
484: + hist - The histogram context
485: - viewer - The viewer to view it with
487: Level: beginner
489: .seealso: `PetscDrawHG`, `PetscViewer`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`
490: @*/
491: PetscErrorCode PetscDrawHGView(PetscDrawHG hist, PetscViewer viewer)
492: {
493: PetscReal xmax, xmin, *bins, *values, *weights, binSize, binLeft, binRight, mean, var, totwt = 0.;
494: PetscInt numBins, numBinsOld, numValues, initSize, i, p;
495: PetscBool usewt = PETSC_FALSE;
496: int inumBins;
498: PetscFunctionBegin;
501: if (hist->xmin > hist->xmax || hist->ymin >= hist->ymax) PetscFunctionReturn(PETSC_SUCCESS);
502: if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
504: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist), &viewer));
505: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)hist, viewer));
506: xmax = hist->xmax;
507: xmin = hist->xmin;
508: numValues = hist->numValues;
509: values = hist->values;
510: weights = hist->weights;
511: mean = 0.0;
512: var = 0.0;
513: if (xmax == xmin) {
514: /* Calculate number of points in the bin */
515: bins = hist->bins;
516: bins[0] = 0.;
517: for (p = 0; p < numValues; p++) {
518: if (values[p] == xmin) bins[0] += weights[0];
519: mean += values[p] * weights[p];
520: var += values[p] * values[p] * weights[p];
521: totwt += weights[p];
522: if (weights[p] != 1.) usewt = PETSC_TRUE;
523: }
524: /* Draw bins */
525: PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]));
526: } else {
527: numBins = hist->numBins;
528: numBinsOld = hist->numBins;
529: if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
530: initSize = (int)((int)xmax - xmin) / numBins;
531: while (initSize * numBins != (int)xmax - xmin) {
532: initSize = PetscMax(initSize - 1, 1);
533: numBins = (int)((int)xmax - xmin) / initSize;
534: PetscCall(PetscCIntCast(numBins, &inumBins));
535: PetscCall(PetscDrawHGSetNumberBins(hist, inumBins));
536: }
537: }
538: binSize = (xmax - xmin) / numBins;
539: bins = hist->bins;
541: /* Calculate number of points in each bin */
542: PetscCall(PetscArrayzero(bins, numBins));
543: for (i = 0; i < numBins; i++) {
544: binLeft = xmin + binSize * i;
545: binRight = xmin + binSize * (i + 1);
546: for (p = 0; p < numValues; p++) {
547: if (values[p] >= binLeft && values[p] < binRight) bins[i] += weights[p];
548: /* Handle last bin separately */
549: if (i == numBins - 1 && values[p] == binRight) bins[i] += weights[p];
550: if (!i) {
551: mean += values[p] * weights[p];
552: var += values[p] * values[p] * weights[p];
553: totwt += weights[p];
554: if (weights[p] != 1.) usewt = PETSC_TRUE;
555: }
556: }
557: }
558: /* Draw bins */
559: for (i = 0; i < numBins; i++) {
560: binLeft = xmin + binSize * i;
561: binRight = xmin + binSize * (i + 1);
562: PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2" PetscInt_FMT " (%6.2g - %6.2g): %.0g\n", i, (double)binLeft, (double)binRight, (double)bins[i]));
563: }
564: PetscCall(PetscCIntCast(numBinsOld, &inumBins));
565: PetscCall(PetscDrawHGSetNumberBins(hist, inumBins));
566: }
568: if (hist->calcStats) {
569: if (usewt) {
570: mean /= totwt;
571: var = (var - totwt * mean * mean) / totwt;
573: PetscCall(PetscViewerASCIIPrintf(viewer, "Total Weight: %g\n", (double)totwt));
574: } else {
575: mean /= numValues;
576: if (numValues > 1) var = (var - numValues * mean * mean) / (PetscReal)(numValues - 1);
577: else var = 0.0;
579: PetscCall(PetscViewerASCIIPrintf(viewer, "Total: %" PetscInt_FMT "\n", numValues));
580: }
581: PetscCall(PetscViewerASCIIPrintf(viewer, "Mean: %g Var: %g\n", (double)mean, (double)var));
582: }
583: PetscFunctionReturn(PETSC_SUCCESS);
584: }
586: /*@
587: PetscDrawHGSetColor - Sets the color the bars will be drawn with.
589: Logically Collective
591: Input Parameters:
592: + hist - The histogram context
593: - color - one of the colors defined in petscdraw.h or `PETSC_DRAW_ROTATE` to make each bar a different color
595: Level: intermediate
597: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
598: @*/
599: PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color)
600: {
601: PetscFunctionBegin;
604: hist->color = color;
605: PetscFunctionReturn(PETSC_SUCCESS);
606: }
608: /*@
609: PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
610: points are added after this call, the limits will be adjusted to
611: include those additional points.
613: Logically Collective
615: Input Parameters:
616: + hist - The histogram context
617: . x_min - the horizontal lower limit
618: . x_max - the horizontal upper limit
619: . y_min - the vertical lower limit
620: - y_max - the vertical upper limit
622: Level: intermediate
624: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
625: @*/
626: PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
627: {
628: PetscFunctionBegin;
631: hist->xmin = x_min;
632: hist->xmax = x_max;
633: hist->ymin = y_min;
634: hist->ymax = y_max;
635: PetscFunctionReturn(PETSC_SUCCESS);
636: }
638: /*@
639: PetscDrawHGCalcStats - Turns on calculation of descriptive statistics associated with the histogram
641: Not Collective
643: Input Parameters:
644: + hist - The histogram context
645: - calc - Flag for calculation
647: Level: intermediate
649: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`
650: @*/
651: PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
652: {
653: PetscFunctionBegin;
656: hist->calcStats = calc;
657: PetscFunctionReturn(PETSC_SUCCESS);
658: }
660: /*@
661: PetscDrawHGIntegerBins - Turns on integer width bins
663: Not Collective
665: Input Parameters:
666: + hist - The histogram context
667: - ints - Flag for integer width bins
669: Level: intermediate
671: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`
672: @*/
673: PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
674: {
675: PetscFunctionBegin;
678: hist->integerBins = ints;
679: PetscFunctionReturn(PETSC_SUCCESS);
680: }
682: /*@
683: PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
684: This is useful if one wants to change some axis property, such as
685: labels, color, etc. The axis context should not be destroyed by the
686: application code.
688: Not Collective, axis is parallel if hist is parallel
690: Input Parameter:
691: . hist - The histogram context
693: Output Parameter:
694: . axis - The axis context
696: Level: intermediate
698: .seealso: `PetscDrawHG`, `PetscDrawAxis`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawHGSetLimits()`
699: @*/
700: PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
701: {
702: PetscFunctionBegin;
704: PetscAssertPointer(axis, 2);
705: *axis = hist->axis;
706: PetscFunctionReturn(PETSC_SUCCESS);
707: }
709: /*@
710: PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
712: Not Collective, draw is parallel if hist is parallel
714: Input Parameter:
715: . hist - The histogram context
717: Output Parameter:
718: . draw - The draw context
720: Level: intermediate
722: .seealso: `PetscDraw`, `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
723: @*/
724: PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *draw)
725: {
726: PetscFunctionBegin;
728: PetscAssertPointer(draw, 2);
729: *draw = hist->win;
730: PetscFunctionReturn(PETSC_SUCCESS);
731: }