Actual source code: bars.c
petsc-3.13.6 2020-09-29
2: /*
3: Contains the data structure for plotting a bargraph in a window with an axis.
4: */
5: #include <petscdraw.h>
6: #include <petsc/private/petscimpl.h>
7: #include <petscviewer.h>
8: #include <../src/sys/classes/draw/utils/axisimpl.h>
10: PetscClassId PETSC_DRAWBAR_CLASSID = 0;
12: struct _p_PetscDrawBar {
13: PETSCHEADER(int);
14: PetscErrorCode (*destroy)(PetscDrawSP);
15: PetscErrorCode (*view)(PetscDrawSP,PetscViewer);
16: PetscDraw win;
17: PetscDrawAxis axis;
18: PetscReal ymin,ymax;
19: int numBins;
20: PetscReal *values;
21: int color;
22: char **labels;
23: PetscBool sort;
24: PetscReal sorttolerance;
25: };
27: #define CHUNKSIZE 100
29: /*@C
30: PetscDrawBarCreate - Creates a bar graph data structure.
32: Collective over PetscDraw
34: Input Parameters:
35: . draw - The window where the graph will be made
37: Output Parameters:
38: . bar - The bar graph context
40: Notes:
41: Call PetscDrawBarSetData() to provide the bins to be plotted and then PetscDrawBarDraw() to display the new plot
43: The difference between a bar chart, PetscDrawBar, and a histogram, PetscDrawHG, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP
45: 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
46: zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawBarDraw() to display the updated graph.
48: Level: intermediate
50: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarDestroy(), PetscDrawBarSetData(),
51: PetscDrawBar, PetscDrawBarDraw(), PetscDrawBarSave(), PetscDrawBarSetColor(), PetscDrawBarSort(), PetscDrawBarSetLimits(), PetscDrawBarGetAxis(), PetscDrawAxis,
52: PetscDrawBarGetDraw(), PetscDrawBarSetFromOptions()
53: @*/
54: PetscErrorCode PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
55: {
56: PetscDrawBar h;
63: PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
64: PetscLogObjectParent((PetscObject)draw,(PetscObject)h);
66: PetscObjectReference((PetscObject)draw);
67: h->win = draw;
69: h->view = NULL;
70: h->destroy = NULL;
71: h->color = PETSC_DRAW_GREEN;
72: h->ymin = 0.; /* if user has not set these then they are determined from the data */
73: h->ymax = 0.;
74: h->numBins = 0;
76: PetscDrawAxisCreate(draw,&h->axis);
77: h->axis->xticks = NULL;
79: *bar = h;
80: return(0);
81: }
83: /*@C
84: PetscDrawBarSetData
86: Logically Collective on PetscDrawBar
88: Input Parameter:
89: + bar - The bar graph context.
90: . bins - number of items
91: . values - values of each item
92: - labels - optional label for each bar, NULL terminated array of strings
94: Level: intermediate
96: Notes:
97: Call PetscDrawBarDraw() after this call to display the new plot
99: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw()
101: @*/
102: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
103: {
109: if (bar->numBins != bins) {
110: PetscFree(bar->values);
111: PetscMalloc1(bins, &bar->values);
112: bar->numBins = bins;
113: }
114: PetscArraycpy(bar->values,data,bins);
115: bar->numBins = bins;
116: if (labels) {
117: PetscStrArrayallocpy(labels,&bar->labels);
118: }
119: return(0);
120: }
122: /*@C
123: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
125: Collective over PetscDrawBar
127: Input Parameter:
128: . bar - The bar graph context
130: Level: intermediate
132: .seealso: PetscDrawBarCreate()
133: @*/
134: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
135: {
139: if (!*bar) return(0);
141: if (--((PetscObject)(*bar))->refct > 0) return(0);
143: PetscFree((*bar)->values);
144: PetscStrArrayDestroy(&(*bar)->labels);
145: PetscDrawAxisDestroy(&(*bar)->axis);
146: PetscDrawDestroy(&(*bar)->win);
147: PetscHeaderDestroy(bar);
148: return(0);
149: }
151: /*@
152: PetscDrawBarDraw - Redraws a bar graph.
154: Collective on PetscDrawBar
156: Input Parameter:
157: . bar - The bar graph context
159: Level: intermediate
161: .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData()
163: @*/
164: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
165: {
166: PetscDraw draw;
167: PetscBool isnull;
168: PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight;
169: PetscInt numValues,i,bcolor,color,idx,*perm,nplot;
170: PetscMPIInt rank;
172: char **labels;
176: PetscDrawIsNull(bar->win,&isnull);
177: if (isnull) return(0);
178: MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);
180: if (bar->numBins < 1) return(0);
182: color = bar->color;
183: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
184: else bcolor = color;
186: numValues = bar->numBins;
187: values = bar->values;
188: if (bar->ymin == bar->ymax) {
189: /* user has not set bounds on bars so set them based on the data */
190: ymin = PETSC_MAX_REAL;
191: ymax = PETSC_MIN_REAL;
192: for (i=0; i<numValues; i++) {
193: ymin = PetscMin(ymin,values[i]);
194: ymax = PetscMax(ymax,values[i]);
195: }
196: } else {
197: ymin = bar->ymin;
198: ymax = bar->ymax;
199: }
200: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
201: xmin = 0.0;
202: xmax = nplot;
203: labels = bar->labels;
205: if (bar->sort) {
206: PetscMalloc1(numValues,&perm);
207: for (i=0; i<numValues;i++) perm[i] = i;
208: PetscSortRealWithPermutation(numValues,values,perm);
209: if (bar->sorttolerance) {
210: for (i=0; i<numValues;i++) {
211: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
212: nplot = i;
213: break;
214: }
215: }
216: }
217: }
219: draw = bar->win;
220: PetscDrawCheckResizedWindow(draw);
221: PetscDrawClear(draw);
223: PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
224: PetscDrawAxisDraw(bar->axis);
226: PetscDrawCollectiveBegin(draw);
227: if (!rank) { /* Draw bins */
228: for (i=0; i<nplot; i++) {
229: idx = (bar->sort ? perm[numValues - i - 1] : i);
230: binLeft = xmin + i;
231: binRight = xmin + i + 1;
232: PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
233: PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
234: PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
235: PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
236: if (labels) {
237: PetscReal h;
238: PetscDrawStringGetSize(draw,NULL,&h);
239: PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
240: }
241: if (color == PETSC_DRAW_ROTATE) bcolor++;
242: if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
243: }
244: }
245: PetscDrawCollectiveEnd(draw);
246: if (bar->sort) {PetscFree(perm);}
248: PetscDrawFlush(draw);
249: PetscDrawPause(draw);
250: return(0);
251: }
253: /*@
254: PetscDrawBarSave - Saves a drawn image
256: Collective on PetscDrawBar
258: Input Parameters:
259: . bar - The bar graph context
261: Level: intermediate
263: .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
264: @*/
265: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
266: {
271: PetscDrawSave(bar->win);
272: return(0);
273: }
275: /*@
276: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
278: Logically Collective on PetscDrawBar
280: Input Parameters:
281: + bar - The bar graph context
282: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
283: different color
285: Level: intermediate
287: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
289: @*/
290: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
291: {
294: bar->color = color;
295: return(0);
296: }
298: /*@
299: PetscDrawBarSort - Sorts the values before drawing the bar chart
301: Logically Collective on PetscDrawBar
303: Input Parameters:
304: + bar - The bar graph context
305: . sort - PETSC_TRUE to sort the values
306: - tolerance - discard values less than tolerance
308: Level: intermediate
310: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
311: @*/
312: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
313: {
316: bar->sort = sort;
317: bar->sorttolerance = tolerance;
318: return(0);
319: }
321: /*@
322: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
323: points are added after this call, the limits will be adjusted to
324: include those additional points.
326: Logically Collective on PetscDrawBar
328: Input Parameters:
329: + bar - The bar graph context
330: - y_min,y_max - The limits
332: Level: intermediate
334: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
335: @*/
336: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
337: {
340: bar->ymin = y_min;
341: bar->ymax = y_max;
342: return(0);
343: }
345: /*@C
346: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
347: This is useful if one wants to change some axis property, such as
348: labels, color, etc. The axis context should not be destroyed by the
349: Section 1.5 Writing Application Codes with PETSc code.
351: Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel
353: Input Parameter:
354: . bar - The bar graph context
356: Output Parameter:
357: . axis - The axis context
359: Level: intermediate
361: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
362: @*/
363: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
364: {
368: *axis = bar->axis;
369: return(0);
370: }
372: /*@C
373: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
375: Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
377: Input Parameter:
378: . bar - The bar graph context
380: Output Parameter:
381: . draw - The draw context
383: Level: intermediate
385: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
386: @*/
387: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
388: {
392: *draw = bar->win;
393: return(0);
394: }
396: /*@
397: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
399: Collective over PetscDrawBar
401: Options Database:
402: . -bar_sort - sort the entries before drawing the bar graph
404: Level: intermediate
407: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
408: @*/
409: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
410: {
412: PetscBool set;
417: PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
418: if (set) {
419: PetscReal tol = bar->sorttolerance;
420: PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
421: PetscDrawBarSort(bar,PETSC_TRUE,tol);
422: }
423: return(0);
424: }