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>
6: #include <petscviewer.h>
8: PetscClassId PETSC_DRAWHG_CLASSID = 0;
10: struct _p_PetscDrawHG {
11: PETSCHEADER(int);
12: PetscErrorCode (*destroy)(PetscDrawSP);
13: PetscErrorCode (*view)(PetscDrawSP, PetscViewer);
14: PetscDraw win;
15: PetscDrawAxis axis;
16: PetscReal xmin, xmax;
17: PetscReal ymin, ymax;
18: int numBins;
19: int maxBins;
20: PetscReal *bins;
21: int numValues;
22: int maxValues;
23: PetscReal *values;
24: PetscReal *weights;
25: int color;
26: PetscBool calcStats;
27: PetscBool integerBins;
28: };
30: #define CHUNKSIZE 100
32: /*@
33: PetscDrawHGCreate - Creates a histogram data structure.
35: Collective
37: Input Parameters:
38: + draw - The window where the graph will be made
39: - bins - The number of bins to use
41: Output Parameter:
42: . hist - The histogram context
44: Level: intermediate
46: Notes:
47: The difference between a bar chart, `PetscDrawBar`, and a histogram, `PetscDrawHG`, is explained here <https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP>
49: The histogram is only displayed when `PetscDrawHGDraw()` is called.
51: 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
52: zeroth MPI process in the communicator. All MPI processes in the communicator must call `PetscDrawHGDraw()` to display the updated graph.
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: PetscErrorCode PetscDrawHGCreate(PetscDraw draw, int bins, PetscDrawHG *hist)
59: {
60: PetscDrawHG h;
62: PetscFunctionBegin;
65: PetscAssertPointer(hist, 3);
67: PetscCall(PetscHeaderCreate(h, PETSC_DRAWHG_CLASSID, "DrawHG", "Histogram", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawHGDestroy, NULL));
68: PetscCall(PetscObjectReference((PetscObject)draw));
69: h->win = draw;
70: h->view = NULL;
71: h->destroy = NULL;
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.e-6;
77: h->numBins = bins;
78: h->maxBins = bins;
79: PetscCall(PetscMalloc1(h->maxBins, &h->bins));
80: h->numValues = 0;
81: h->maxValues = CHUNKSIZE;
82: h->calcStats = PETSC_FALSE;
83: h->integerBins = PETSC_FALSE;
84: PetscCall(PetscMalloc2(h->maxValues, &h->values, h->maxValues, &h->weights));
85: PetscCall(PetscDrawAxisCreate(draw, &h->axis));
86: *hist = h;
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: /*@
91: PetscDrawHGSetNumberBins - Change the number of bins that are to be drawn in the histogram
93: Logically Collective
95: Input Parameters:
96: + hist - The histogram context.
97: - bins - The number of bins.
99: Level: intermediate
101: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGIntegerBins()`
102: @*/
103: PetscErrorCode PetscDrawHGSetNumberBins(PetscDrawHG hist, int bins)
104: {
105: PetscFunctionBegin;
109: if (hist->maxBins < bins) {
110: PetscCall(PetscFree(hist->bins));
111: PetscCall(PetscMalloc1(bins, &hist->bins));
112: hist->maxBins = bins;
113: }
114: hist->numBins = bins;
115: PetscFunctionReturn(PETSC_SUCCESS);
116: }
118: /*@
119: PetscDrawHGReset - Clears histogram to allow for reuse with new data.
121: Logically Collective
123: Input Parameter:
124: . hist - The histogram context.
126: Level: intermediate
128: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGAddValue()`
129: @*/
130: PetscErrorCode PetscDrawHGReset(PetscDrawHG hist)
131: {
132: PetscFunctionBegin;
135: hist->xmin = PETSC_MAX_REAL;
136: hist->xmax = PETSC_MIN_REAL;
137: hist->ymin = 0.0;
138: hist->ymax = 1.e-6;
139: hist->numValues = 0;
140: PetscFunctionReturn(PETSC_SUCCESS);
141: }
143: /*@
144: PetscDrawHGDestroy - Frees all space taken up by histogram data structure.
146: Collective
148: Input Parameter:
149: . hist - The histogram context
151: Level: intermediate
153: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`
154: @*/
155: PetscErrorCode PetscDrawHGDestroy(PetscDrawHG *hist)
156: {
157: PetscFunctionBegin;
158: if (!*hist) PetscFunctionReturn(PETSC_SUCCESS);
160: if (--((PetscObject)*hist)->refct > 0) {
161: *hist = NULL;
162: PetscFunctionReturn(PETSC_SUCCESS);
163: }
165: PetscCall(PetscFree((*hist)->bins));
166: PetscCall(PetscFree2((*hist)->values, (*hist)->weights));
167: PetscCall(PetscDrawAxisDestroy(&(*hist)->axis));
168: PetscCall(PetscDrawDestroy(&(*hist)->win));
169: PetscCall(PetscHeaderDestroy(hist));
170: PetscFunctionReturn(PETSC_SUCCESS);
171: }
173: /*@
174: PetscDrawHGAddValue - Adds another value to the histogram.
176: Logically Collective
178: Input Parameters:
179: + hist - The histogram
180: - value - The value
182: Level: intermediate
184: Note:
185: 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.
187: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGReset()`, `PetscDrawHGAddWeightedValue()`
188: @*/
189: PetscErrorCode PetscDrawHGAddValue(PetscDrawHG hist, PetscReal value)
190: {
191: PetscFunctionBegin;
194: /* Allocate more memory if necessary */
195: if (hist->numValues >= hist->maxValues) {
196: PetscReal *tmp, *tmpw;
198: PetscCall(PetscMalloc2(hist->maxValues + CHUNKSIZE, &tmp, hist->maxValues + CHUNKSIZE, &tmpw));
199: PetscCall(PetscArraycpy(tmp, hist->values, hist->maxValues));
200: PetscCall(PetscArraycpy(tmpw, hist->weights, hist->maxValues));
201: PetscCall(PetscFree2(hist->values, hist->weights));
203: hist->values = tmp;
204: hist->weights = tmpw;
205: hist->maxValues += CHUNKSIZE;
206: }
207: /* I disagree with the original PETSc implementation here. There should be no overshoot, but rather the
208: stated convention of using half-open intervals (always the way to go) */
209: if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
210: hist->xmin = value;
211: hist->xmax = value;
212: #if 1
213: } else {
214: /* Update limits */
215: if (value > hist->xmax) hist->xmax = value;
216: if (value < hist->xmin) hist->xmin = value;
217: #else
218: } else if (hist->numValues == 1) {
219: /* Update limits -- We need to overshoot the largest value somewhat */
220: if (value > hist->xmax) hist->xmax = value + 0.001 * (value - hist->xmin) / (PetscReal)hist->numBins;
221: if (value < hist->xmin) {
222: hist->xmin = value;
223: hist->xmax = hist->xmax + 0.001 * (hist->xmax - hist->xmin) / (PetscReal)hist->numBins;
224: }
225: } else {
226: /* Update limits -- We need to overshoot the largest value somewhat */
227: if (value > hist->xmax) hist->xmax = value + 0.001 * (hist->xmax - hist->xmin) / (PetscReal)hist->numBins;
228: if (value < hist->xmin) hist->xmin = value;
229: #endif
230: }
232: hist->values[hist->numValues] = value;
233: hist->weights[hist->numValues] = 1.;
234: ++hist->numValues;
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: /*@
239: PetscDrawHGAddWeightedValue - Adds another value to the histogram with a weight.
241: Logically Collective
243: Input Parameters:
244: + hist - The histogram
245: . value - The value
246: - weight - The value weight
248: Level: intermediate
250: Notes:
251: 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.
253: 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.
255: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGDraw()`, `PetscDrawHGReset()`, `PetscDrawHGAddValue()`
256: @*/
257: PetscErrorCode PetscDrawHGAddWeightedValue(PetscDrawHG hist, PetscReal value, PetscReal weight)
258: {
259: PetscFunctionBegin;
262: /* Allocate more memory if necessary */
263: if (hist->numValues >= hist->maxValues) {
264: PetscReal *tmp, *tmpw;
266: PetscCall(PetscMalloc2(hist->maxValues + CHUNKSIZE, &tmp, hist->maxValues + CHUNKSIZE, &tmpw));
267: PetscCall(PetscArraycpy(tmp, hist->values, hist->maxValues));
268: PetscCall(PetscArraycpy(tmpw, hist->weights, hist->maxValues));
269: PetscCall(PetscFree2(hist->values, hist->weights));
271: hist->values = tmp;
272: hist->weights = tmpw;
273: hist->maxValues += CHUNKSIZE;
274: }
275: /* I disagree with the original PETSc implementation here. There should be no overshoot, but rather the
276: stated convention of using half-open intervals (always the way to go) */
277: if (!hist->numValues && (hist->xmin == PETSC_MAX_REAL) && (hist->xmax == PETSC_MIN_REAL)) {
278: hist->xmin = value;
279: hist->xmax = value;
280: } else {
281: /* Update limits */
282: if (value > hist->xmax) hist->xmax = value;
283: if (value < hist->xmin) hist->xmin = value;
284: }
286: hist->values[hist->numValues] = value;
287: hist->weights[hist->numValues] = weight;
288: ++hist->numValues;
289: PetscFunctionReturn(PETSC_SUCCESS);
290: }
292: /*@
293: PetscDrawHGDraw - Redraws a histogram.
295: Collective
297: Input Parameter:
298: . hist - The histogram context
300: Level: intermediate
302: .seealso: `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawHGAddValue()`, `PetscDrawHGReset()`
303: @*/
304: PetscErrorCode PetscDrawHGDraw(PetscDrawHG hist)
305: {
306: PetscDraw draw;
307: PetscBool isnull, usewt = PETSC_FALSE;
308: PetscReal xmin, xmax, ymin, ymax, *bins, *values, *weights, binSize, binLeft, binRight, maxHeight, mean, var, totwt = 0.;
309: char title[256];
310: char xlabel[256];
311: PetscInt numValues, initSize, i, p;
312: int bcolor, color, numBins, numBinsOld;
313: PetscMPIInt rank;
315: PetscFunctionBegin;
317: PetscCall(PetscDrawIsNull(hist->win, &isnull));
318: if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
319: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)hist), &rank));
321: if ((hist->xmin >= hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(PETSC_SUCCESS);
322: if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
324: color = hist->color;
325: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK + 1;
326: else bcolor = color;
328: xmin = hist->xmin;
329: xmax = hist->xmax;
330: ymin = hist->ymin;
331: ymax = hist->ymax;
332: numValues = hist->numValues;
333: values = hist->values;
334: weights = hist->weights;
335: mean = 0.0;
336: var = 0.0;
338: draw = hist->win;
339: PetscCall(PetscDrawCheckResizedWindow(draw));
340: PetscCall(PetscDrawClear(draw));
342: if (xmin == xmax) {
343: /* Calculate number of points in each bin */
344: bins = hist->bins;
345: bins[0] = 0.;
346: for (p = 0; p < numValues; p++) {
347: if (values[p] == xmin) bins[0] += weights[0];
348: mean += values[p] * weights[p];
349: var += values[p] * values[p] * weights[p];
350: totwt += weights[p];
351: if (weights[p] != 1.) usewt = PETSC_TRUE;
352: }
353: maxHeight = bins[0];
354: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
355: xmax = xmin + 1;
356: PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
357: if (hist->calcStats) {
358: if (usewt) {
359: mean /= totwt;
360: var = (var - totwt * mean * mean) / totwt;
362: PetscCall(PetscSNPrintf(xlabel, 256, "Total Weight: %g", (double)totwt));
363: } else {
364: mean /= numValues;
365: if (numValues > 1) var = (var - numValues * mean * mean) / (PetscReal)(numValues - 1);
366: else var = 0.0;
368: PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
369: }
370: PetscCall(PetscSNPrintf(title, 256, "Mean: %g Var: %g", (double)mean, (double)var));
371: PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
372: }
373: PetscCall(PetscDrawAxisDraw(hist->axis));
374: PetscDrawCollectiveBegin(draw);
375: if (rank == 0) { /* Draw bins */
376: binLeft = xmin;
377: binRight = xmax;
378: PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[0], bcolor, bcolor, bcolor, bcolor));
379: PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[0], PETSC_DRAW_BLACK));
380: PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[0], PETSC_DRAW_BLACK));
381: PetscCall(PetscDrawLine(draw, binLeft, bins[0], binRight, bins[0], PETSC_DRAW_BLACK));
382: }
383: PetscDrawCollectiveEnd(draw);
384: } else {
385: numBins = hist->numBins;
386: numBinsOld = hist->numBins;
387: if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
388: initSize = ((int)(xmax - xmin)) / numBins;
389: while (initSize * numBins != (int)xmax - xmin) {
390: initSize = PetscMax(initSize - 1, 1);
391: numBins = ((int)(xmax - xmin)) / initSize;
392: PetscCall(PetscDrawHGSetNumberBins(hist, numBins));
393: }
394: }
395: binSize = (xmax - xmin) / (PetscReal)numBins;
396: bins = hist->bins;
398: PetscCall(PetscArrayzero(bins, numBins));
400: maxHeight = 0.0;
401: for (i = 0; i < numBins; i++) {
402: binLeft = xmin + binSize * i;
403: binRight = xmin + binSize * (i + 1);
404: for (p = 0; p < numValues; p++) {
405: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i] += weights[p];
406: /* Handle last bin separately */
407: if ((i == numBins - 1) && (values[p] == binRight)) bins[i] += weights[p];
408: if (!i) {
409: mean += values[p] * weights[p];
410: var += values[p] * values[p] * weights[p];
411: totwt += weights[p];
412: if (weights[p] != 1.) usewt = PETSC_TRUE;
413: }
414: }
415: maxHeight = PetscMax(maxHeight, bins[i]);
416: }
417: if (maxHeight > ymax) ymax = hist->ymax = maxHeight;
419: PetscCall(PetscDrawAxisSetLimits(hist->axis, xmin, xmax, ymin, ymax));
420: if (hist->calcStats) {
421: if (usewt) {
422: mean /= totwt;
423: var = (var - totwt * mean * mean) / totwt;
425: PetscCall(PetscSNPrintf(xlabel, 256, "Total Weight: %g", (double)totwt));
426: } else {
427: mean /= numValues;
428: if (numValues > 1) var = (var - numValues * mean * mean) / (PetscReal)(numValues - 1);
429: else var = 0.0;
431: PetscCall(PetscSNPrintf(xlabel, 256, "Total: %" PetscInt_FMT, numValues));
432: }
433: PetscCall(PetscSNPrintf(title, 256, "Mean: %g Var: %g", (double)mean, (double)var));
434: PetscCall(PetscDrawAxisSetLabels(hist->axis, title, xlabel, NULL));
435: }
436: PetscCall(PetscDrawAxisDraw(hist->axis));
437: PetscDrawCollectiveBegin(draw);
438: if (rank == 0) { /* Draw bins */
439: for (i = 0; i < numBins; i++) {
440: binLeft = xmin + binSize * i;
441: binRight = xmin + binSize * (i + 1);
442: PetscCall(PetscDrawRectangle(draw, binLeft, ymin, binRight, bins[i], bcolor, bcolor, bcolor, bcolor));
443: PetscCall(PetscDrawLine(draw, binLeft, ymin, binLeft, bins[i], PETSC_DRAW_BLACK));
444: PetscCall(PetscDrawLine(draw, binRight, ymin, binRight, bins[i], PETSC_DRAW_BLACK));
445: PetscCall(PetscDrawLine(draw, binLeft, bins[i], binRight, bins[i], PETSC_DRAW_BLACK));
446: if (color == PETSC_DRAW_ROTATE && bins[i]) bcolor++;
447: if (bcolor > PETSC_DRAW_BASIC_COLORS - 1) bcolor = PETSC_DRAW_BLACK + 1;
448: }
449: }
450: PetscDrawCollectiveEnd(draw);
451: PetscCall(PetscDrawHGSetNumberBins(hist, numBinsOld));
452: }
454: PetscCall(PetscDrawFlush(draw));
455: PetscCall(PetscDrawPause(draw));
456: PetscFunctionReturn(PETSC_SUCCESS);
457: }
459: /*@
460: PetscDrawHGSave - Saves a drawn image
462: Collective
464: Input Parameter:
465: . hg - The histogram context
467: Level: intermediate
469: .seealso: `PetscDrawSave()`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawHGDraw()`
470: @*/
471: PetscErrorCode PetscDrawHGSave(PetscDrawHG hg)
472: {
473: PetscFunctionBegin;
475: PetscCall(PetscDrawSave(hg->win));
476: PetscFunctionReturn(PETSC_SUCCESS);
477: }
479: /*@
480: PetscDrawHGView - Prints the histogram information to a viewer
482: Not Collective
484: Input Parameters:
485: + hist - The histogram context
486: - viewer - The viewer to view it with
488: Level: beginner
490: .seealso: `PetscDrawHG`, `PetscViewer`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`
491: @*/
492: PetscErrorCode PetscDrawHGView(PetscDrawHG hist, PetscViewer viewer)
493: {
494: PetscReal xmax, xmin, *bins, *values, *weights, binSize, binLeft, binRight, mean, var, totwt = 0.;
495: PetscInt numBins, numBinsOld, numValues, initSize, i, p;
496: PetscBool usewt = PETSC_FALSE;
497: int inumBins;
499: PetscFunctionBegin;
502: if ((hist->xmin > hist->xmax) || (hist->ymin >= hist->ymax)) PetscFunctionReturn(PETSC_SUCCESS);
503: if (hist->numValues < 1) PetscFunctionReturn(PETSC_SUCCESS);
505: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)hist), &viewer));
506: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)hist, viewer));
507: xmax = hist->xmax;
508: xmin = hist->xmin;
509: numValues = hist->numValues;
510: values = hist->values;
511: weights = hist->weights;
512: mean = 0.0;
513: var = 0.0;
514: if (xmax == xmin) {
515: /* Calculate number of points in the bin */
516: bins = hist->bins;
517: bins[0] = 0.;
518: for (p = 0; p < numValues; p++) {
519: if (values[p] == xmin) bins[0] += weights[0];
520: mean += values[p] * weights[p];
521: var += values[p] * values[p] * weights[p];
522: totwt += weights[p];
523: if (weights[p] != 1.) usewt = PETSC_TRUE;
524: }
525: /* Draw bins */
526: PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2d (%6.2g - %6.2g): %.0g\n", 0, (double)xmin, (double)xmax, (double)bins[0]));
527: } else {
528: numBins = hist->numBins;
529: numBinsOld = hist->numBins;
530: if (hist->integerBins && (((int)xmax - xmin) + 1.0e-05 > xmax - xmin)) {
531: initSize = (int)((int)xmax - xmin) / numBins;
532: while (initSize * numBins != (int)xmax - xmin) {
533: initSize = PetscMax(initSize - 1, 1);
534: numBins = (int)((int)xmax - xmin) / initSize;
535: PetscCall(PetscCIntCast(numBins, &inumBins));
536: PetscCall(PetscDrawHGSetNumberBins(hist, inumBins));
537: }
538: }
539: binSize = (xmax - xmin) / numBins;
540: bins = hist->bins;
542: /* Calculate number of points in each bin */
543: PetscCall(PetscArrayzero(bins, numBins));
544: for (i = 0; i < numBins; i++) {
545: binLeft = xmin + binSize * i;
546: binRight = xmin + binSize * (i + 1);
547: for (p = 0; p < numValues; p++) {
548: if ((values[p] >= binLeft) && (values[p] < binRight)) bins[i] += weights[p];
549: /* Handle last bin separately */
550: if ((i == numBins - 1) && (values[p] == binRight)) bins[i] += weights[p];
551: if (!i) {
552: mean += values[p] * weights[p];
553: var += values[p] * values[p] * weights[p];
554: totwt += weights[p];
555: if (weights[p] != 1.) usewt = PETSC_TRUE;
556: }
557: }
558: }
559: /* Draw bins */
560: for (i = 0; i < numBins; i++) {
561: binLeft = xmin + binSize * i;
562: binRight = xmin + binSize * (i + 1);
563: PetscCall(PetscViewerASCIIPrintf(viewer, "Bin %2" PetscInt_FMT " (%6.2g - %6.2g): %.0g\n", i, (double)binLeft, (double)binRight, (double)bins[i]));
564: }
565: PetscCall(PetscCIntCast(numBinsOld, &inumBins));
566: PetscCall(PetscDrawHGSetNumberBins(hist, inumBins));
567: }
569: if (hist->calcStats) {
570: if (usewt) {
571: mean /= totwt;
572: var = (var - totwt * mean * mean) / totwt;
574: PetscCall(PetscViewerASCIIPrintf(viewer, "Total Weight: %g\n", (double)totwt));
575: } else {
576: mean /= numValues;
577: if (numValues > 1) var = (var - numValues * mean * mean) / (PetscReal)(numValues - 1);
578: else var = 0.0;
580: PetscCall(PetscViewerASCIIPrintf(viewer, "Total: %" PetscInt_FMT "\n", numValues));
581: }
582: PetscCall(PetscViewerASCIIPrintf(viewer, "Mean: %g Var: %g\n", (double)mean, (double)var));
583: }
584: PetscFunctionReturn(PETSC_SUCCESS);
585: }
587: /*@
588: PetscDrawHGSetColor - Sets the color the bars will be drawn with.
590: Logically Collective
592: Input Parameters:
593: + hist - The histogram context
594: - color - one of the colors defined in petscdraw.h or `PETSC_DRAW_ROTATE` to make each bar a different color
596: Level: intermediate
598: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
599: @*/
600: PetscErrorCode PetscDrawHGSetColor(PetscDrawHG hist, int color)
601: {
602: PetscFunctionBegin;
605: hist->color = color;
606: PetscFunctionReturn(PETSC_SUCCESS);
607: }
609: /*@
610: PetscDrawHGSetLimits - Sets the axis limits for a histogram. If more
611: points are added after this call, the limits will be adjusted to
612: include those additional points.
614: Logically Collective
616: Input Parameters:
617: + hist - The histogram context
618: . x_min - the horizontal lower limit
619: . x_max - the horizontal upper limit
620: . y_min - the vertical lower limit
621: - y_max - the vertical upper limit
623: Level: intermediate
625: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawHGDraw()`, `PetscDrawHGGetAxis()`
626: @*/
627: PetscErrorCode PetscDrawHGSetLimits(PetscDrawHG hist, PetscReal x_min, PetscReal x_max, int y_min, int y_max)
628: {
629: PetscFunctionBegin;
632: hist->xmin = x_min;
633: hist->xmax = x_max;
634: hist->ymin = y_min;
635: hist->ymax = y_max;
636: PetscFunctionReturn(PETSC_SUCCESS);
637: }
639: /*@
640: PetscDrawHGCalcStats - Turns on calculation of descriptive statistics associated with the histogram
642: Not Collective
644: Input Parameters:
645: + hist - The histogram context
646: - calc - Flag for calculation
648: Level: intermediate
650: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`
651: @*/
652: PetscErrorCode PetscDrawHGCalcStats(PetscDrawHG hist, PetscBool calc)
653: {
654: PetscFunctionBegin;
657: hist->calcStats = calc;
658: PetscFunctionReturn(PETSC_SUCCESS);
659: }
661: /*@
662: PetscDrawHGIntegerBins - Turns on integer width bins
664: Not Collective
666: Input Parameters:
667: + hist - The histogram context
668: - ints - Flag for integer width bins
670: Level: intermediate
672: .seealso: `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`
673: @*/
674: PetscErrorCode PetscDrawHGIntegerBins(PetscDrawHG hist, PetscBool ints)
675: {
676: PetscFunctionBegin;
679: hist->integerBins = ints;
680: PetscFunctionReturn(PETSC_SUCCESS);
681: }
683: /*@
684: PetscDrawHGGetAxis - Gets the axis context associated with a histogram.
685: This is useful if one wants to change some axis property, such as
686: labels, color, etc. The axis context should not be destroyed by the
687: application code.
689: Not Collective, axis is parallel if hist is parallel
691: Input Parameter:
692: . hist - The histogram context
694: Output Parameter:
695: . axis - The axis context
697: Level: intermediate
699: .seealso: `PetscDrawHG`, `PetscDrawAxis`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawHGSetLimits()`
700: @*/
701: PetscErrorCode PetscDrawHGGetAxis(PetscDrawHG hist, PetscDrawAxis *axis)
702: {
703: PetscFunctionBegin;
705: PetscAssertPointer(axis, 2);
706: *axis = hist->axis;
707: PetscFunctionReturn(PETSC_SUCCESS);
708: }
710: /*@
711: PetscDrawHGGetDraw - Gets the draw context associated with a histogram.
713: Not Collective, draw is parallel if hist is parallel
715: Input Parameter:
716: . hist - The histogram context
718: Output Parameter:
719: . draw - The draw context
721: Level: intermediate
723: .seealso: `PetscDraw`, `PetscDrawHG`, `PetscDrawHGCreate()`, `PetscDrawHGAddValue()`, `PetscDrawHGView()`, `PetscDrawHGDraw()`, `PetscDrawHGSetColor()`, `PetscDrawAxis`, `PetscDrawHGSetLimits()`
724: @*/
725: PetscErrorCode PetscDrawHGGetDraw(PetscDrawHG hist, PetscDraw *draw)
726: {
727: PetscFunctionBegin;
729: PetscAssertPointer(draw, 2);
730: *draw = hist->win;
731: PetscFunctionReturn(PETSC_SUCCESS);
732: }