Actual source code: bars.c
2: /*
3: Contains the data structure for plotting a bargraph in a window with an axis.
4: */
6: #include <petsc/private/drawimpl.h>
7: #include <petscviewer.h>
9: PetscClassId PETSC_DRAWBAR_CLASSID = 0;
11: /*@C
12: PetscDrawBarCreate - Creates a bar graph data structure.
14: Collective over draw
16: Input Parameters:
17: . draw - The window where the graph will be made
19: Output Parameters:
20: . bar - The bar graph context
22: Notes:
23: Call `PetscDrawBarSetData()` to provide the bins to be plotted and then `PetscDrawBarDraw()` to display the new plot
25: The difference between a bar chart, `PetscDrawBar`, and a histogram, `PetscDrawHG`, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP
27: The MPI communicator that owns the `PetscDraw` owns this `PetscDrawBar`, but the calls to set options and add data are ignored on all processes except the
28: zeroth MPI rank in the communicator. All MPI ranks in the communicator must call `PetscDrawBarDraw()` to display the updated graph.
30: Level: intermediate
32: .seealso: `PetscDrawBar`, `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawBarDestroy()`, `PetscDrawBarSetData()`,
33: `PetscDrawBar`, `PetscDrawBarDraw()`, `PetscDrawBarSave()`, `PetscDrawBarSetColor()`, `PetscDrawBarSort()`, `PetscDrawBarSetLimits()`, `PetscDrawBarGetAxis()`, `PetscDrawAxis`,
34: `PetscDrawBarGetDraw()`, `PetscDrawBarSetFromOptions()`
35: @*/
36: PetscErrorCode PetscDrawBarCreate(PetscDraw draw, PetscDrawBar *bar)
37: {
38: PetscDrawBar h;
43: PetscHeaderCreate(h, PETSC_DRAWBAR_CLASSID, "DrawBar", "Bar Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawBarDestroy, NULL);
45: PetscObjectReference((PetscObject)draw);
46: h->win = draw;
48: h->view = NULL;
49: h->destroy = NULL;
50: h->color = PETSC_DRAW_GREEN;
51: h->ymin = 0.; /* if user has not set these then they are determined from the data */
52: h->ymax = 0.;
53: h->numBins = 0;
55: PetscDrawAxisCreate(draw, &h->axis);
56: h->axis->xticks = NULL;
58: *bar = h;
59: return 0;
60: }
62: /*@C
63: PetscDrawBarSetData
65: Logically Collective
67: Input Parameters:
68: + bar - The bar graph context.
69: . bins - number of items
70: . values - values of each item
71: - labels - optional label for each bar, NULL terminated array of strings
73: Level: intermediate
75: Notes:
76: Call `PetscDrawBarDraw()` after this call to display the new plot
78: The data is ignored on all ranks except zero
80: .seealso: `PetscDrawBar`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawBarDraw()`
81: @*/
82: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar, PetscInt bins, const PetscReal data[], const char *const *labels)
83: {
86: if (bar->numBins != bins) {
87: PetscFree(bar->values);
88: PetscMalloc1(bins, &bar->values);
89: bar->numBins = bins;
90: }
91: PetscArraycpy(bar->values, data, bins);
92: bar->numBins = bins;
93: if (labels) PetscStrArrayallocpy(labels, &bar->labels);
94: return 0;
95: }
97: /*@C
98: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
100: Collective over bar
102: Input Parameter:
103: . bar - The bar graph context
105: Level: intermediate
107: .seealso: `PetscDrawBar`, `PetscDrawBarCreate()`
108: @*/
109: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
110: {
111: if (!*bar) return 0;
113: if (--((PetscObject)(*bar))->refct > 0) return 0;
115: PetscFree((*bar)->values);
116: PetscStrArrayDestroy(&(*bar)->labels);
117: PetscDrawAxisDestroy(&(*bar)->axis);
118: PetscDrawDestroy(&(*bar)->win);
119: PetscHeaderDestroy(bar);
120: return 0;
121: }
123: /*@
124: PetscDrawBarDraw - Redraws a bar graph.
126: Collective
128: Input Parameter:
129: . bar - The bar graph context
131: Level: intermediate
133: .seealso: `PetscDrawBar`, `PetscDrawBarCreate()`, `PetscDrawBarSetData()`
134: @*/
135: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
136: {
137: PetscDraw draw;
138: PetscBool isnull;
139: PetscReal xmin, xmax, ymin, ymax, *values, binLeft, binRight;
140: PetscInt numValues, i, bcolor, color, idx, *perm, nplot;
141: PetscMPIInt rank;
142: char **labels;
145: PetscDrawIsNull(bar->win, &isnull);
146: if (isnull) return 0;
147: MPI_Comm_rank(PetscObjectComm((PetscObject)bar), &rank);
149: if (bar->numBins < 1) return 0;
151: color = bar->color;
152: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK + 1;
153: else bcolor = color;
155: numValues = bar->numBins;
156: values = bar->values;
157: if (bar->ymin == bar->ymax) {
158: /* user has not set bounds on bars so set them based on the data */
159: ymin = PETSC_MAX_REAL;
160: ymax = PETSC_MIN_REAL;
161: for (i = 0; i < numValues; i++) {
162: ymin = PetscMin(ymin, values[i]);
163: ymax = PetscMax(ymax, values[i]);
164: }
165: } else {
166: ymin = bar->ymin;
167: ymax = bar->ymax;
168: }
169: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
170: xmin = 0.0;
171: xmax = nplot;
172: labels = bar->labels;
174: if (bar->sort) {
175: PetscMalloc1(numValues, &perm);
176: for (i = 0; i < numValues; i++) perm[i] = i;
177: PetscSortRealWithPermutation(numValues, values, perm);
178: if (bar->sorttolerance) {
179: for (i = 0; i < numValues; i++) {
180: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
181: nplot = i;
182: break;
183: }
184: }
185: }
186: }
188: draw = bar->win;
189: PetscDrawCheckResizedWindow(draw);
190: PetscDrawClear(draw);
192: PetscDrawAxisSetLimits(bar->axis, xmin, xmax, ymin, ymax);
193: PetscDrawAxisDraw(bar->axis);
195: PetscDrawCollectiveBegin(draw);
196: if (rank == 0) { /* Draw bins */
197: for (i = 0; i < nplot; i++) {
198: idx = (bar->sort ? perm[numValues - i - 1] : i);
199: binLeft = xmin + i;
200: binRight = xmin + i + 1;
201: PetscDrawRectangle(draw, binLeft, ymin, binRight, values[idx], bcolor, bcolor, bcolor, bcolor);
202: PetscDrawLine(draw, binLeft, ymin, binLeft, values[idx], PETSC_DRAW_BLACK);
203: PetscDrawLine(draw, binRight, ymin, binRight, values[idx], PETSC_DRAW_BLACK);
204: PetscDrawLine(draw, binLeft, values[idx], binRight, values[idx], PETSC_DRAW_BLACK);
205: if (labels) {
206: PetscReal h;
207: PetscDrawStringGetSize(draw, NULL, &h);
208: PetscDrawStringCentered(draw, .5 * (binLeft + binRight), ymin - 1.5 * h, bcolor, labels[idx]);
209: }
210: if (color == PETSC_DRAW_ROTATE) bcolor++;
211: if (bcolor > PETSC_DRAW_BASIC_COLORS - 1) bcolor = PETSC_DRAW_BLACK + 1;
212: }
213: }
214: PetscDrawCollectiveEnd(draw);
215: if (bar->sort) PetscFree(perm);
217: PetscDrawFlush(draw);
218: PetscDrawPause(draw);
219: return 0;
220: }
222: /*@
223: PetscDrawBarSave - Saves a drawn bar graph
225: Collective
227: Input Parameters:
228: . bar - The bar graph context
230: Level: intermediate
232: .seealso: `PetscDrawSave()`, `PetscDrawBar`, `PetscDrawBarCreate()`, `PetscDrawBarGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`, `PetscDrawBarSetData()`
233: @*/
234: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
235: {
237: PetscDrawSave(bar->win);
238: return 0;
239: }
241: /*@
242: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
244: Logically Collective
246: Input Parameters:
247: + bar - The bar graph context
248: - color - one of the colors defined in petscdraw.h or `PETSC_DRAW_ROTATE` to make each bar a
249: different color
251: Level: intermediate
253: .seealso: `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawBarSetData()`, `PetscDrawBarDraw()`, `PetscDrawBarGetAxis()`
254: @*/
255: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
256: {
258: bar->color = color;
259: return 0;
260: }
262: /*@
263: PetscDrawBarSort - Sorts the values before drawing the bar chart, the bars will be in ascending order from left to right
265: Logically Collective
267: Input Parameters:
268: + bar - The bar graph context
269: . sort - `PETSC_TRUE` to sort the values
270: - tolerance - discard values less than tolerance
272: Level: intermediate
274: .seealso: `PetscDrawBar`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawBarSetData()`, `PetscDrawBarSetColor()`, `PetscDrawBarDraw()`, `PetscDrawBarGetAxis()`
275: @*/
276: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
277: {
279: bar->sort = sort;
280: bar->sorttolerance = tolerance;
281: return 0;
282: }
284: /*@
285: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
286: points are added after this call, the limits will be adjusted to
287: include those additional points.
289: Logically Collective
291: Input Parameters:
292: + bar - The bar graph context
293: - y_min,y_max - The limits
295: Level: intermediate
297: .seealso: `PetscDrawBar`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawBarGetAxis()`, `PetscDrawBarSetData()`, `PetscDrawBarDraw()`
298: @*/
299: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
300: {
302: bar->ymin = y_min;
303: bar->ymax = y_max;
304: return 0;
305: }
307: /*@C
308: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
309: This is useful if one wants to change some axis property, such as
310: labels, color, etc. The axis context should not be destroyed by the
311: application code.
313: Not Collective, axis is parallel if bar is parallel
315: Input Parameter:
316: . bar - The bar graph context
318: Output Parameter:
319: . axis - The axis context
321: Level: intermediate
323: .seealso: `PetscDrawBar`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawAxis`, `PetscDrawAxisCreate()`
324: @*/
325: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis)
326: {
329: *axis = bar->axis;
330: return 0;
331: }
333: /*@C
334: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
336: Not Collective, draw is parallel if bar is parallel
338: Input Parameter:
339: . bar - The bar graph context
341: Output Parameter:
342: . draw - The draw context
344: Level: intermediate
346: .seealso: `PetscDrawBar`, `PetscDraw`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawBarDraw()`, `PetscDraw`
347: @*/
348: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *draw)
349: {
352: *draw = bar->win;
353: return 0;
354: }
356: /*@
357: PetscDrawBarSetFromOptions - Sets options related to the display of the `PetscDrawBar`
359: Collective over bar
361: Options Database Key:
362: . -bar_sort - sort the entries before drawing the bar graph
364: Level: intermediate
366: Note:
367: Does not set options related to the underlying `PetscDraw` or `PetscDrawAxis`
369: .seealso: `PetscDrawBar`, `PetscDrawBarDestroy()`, `PetscDrawBarCreate()`, `PetscDrawBarSort()`
370: @*/
371: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
372: {
373: PetscBool set;
377: PetscOptionsHasName(((PetscObject)bar)->options, ((PetscObject)bar)->prefix, "-bar_sort", &set);
378: if (set) {
379: PetscReal tol = bar->sorttolerance;
380: PetscOptionsGetReal(((PetscObject)bar)->options, ((PetscObject)bar)->prefix, "-bar_sort", &tol, NULL);
381: PetscDrawBarSort(bar, PETSC_TRUE, tol);
382: }
383: return 0;
384: }