Actual source code: bars.c
petsc-3.9.4 2018-09-11
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: Call PetscDrawBarSetData() to provide the bins to be plotted and then PetscDrawBarDraw() to display the new plot
42: The difference between a bar chart, PetscDrawBar, and a histogram, PetscDrawHG, is explained here http://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP
44: 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
45: zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawBarDraw() to display the updated graph.
47: Level: intermediate
49: Concepts: bar graph^creating
51: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarDestroy(), PetscDrawBarSetData(),
52: PetscDrawBar, PetscDrawBarDraw(), PetscDrawBarSave(), PetscDrawBarSetColor(), PetscDrawBarSort(), PetscDrawBarSetLimits(), PetscDrawBarGetAxis(), PetscDrawAxis,
53: PetscDrawBarGetDraw(), PetscDrawBarSetFromOptions()
54: @*/
55: PetscErrorCode PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
56: {
57: PetscDrawBar h;
64: PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
65: PetscLogObjectParent((PetscObject)draw,(PetscObject)h);
67: PetscObjectReference((PetscObject)draw);
68: h->win = draw;
70: h->view = NULL;
71: h->destroy = NULL;
72: h->color = PETSC_DRAW_GREEN;
73: h->ymin = 0.; /* if user has not set these then they are determined from the data */
74: h->ymax = 0.;
75: h->numBins = 0;
77: PetscDrawAxisCreate(draw,&h->axis);
78: h->axis->xticks = NULL;
80: *bar = h;
81: return(0);
82: }
84: /*@C
85: PetscDrawBarSetData
87: Logically Collective on PetscDrawBar
89: Input Parameter:
90: + bar - The bar graph context.
91: . bins - number of items
92: . values - values of each item
93: - labels - optional label for each bar, NULL terminated array of strings
95: Level: intermediate
97: Notes: 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: PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));
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: Concepts: bar graph^saving
265: .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
266: @*/
267: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
268: {
273: PetscDrawSave(bar->win);
274: return(0);
275: }
277: /*@
278: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
280: Logically Collective on PetscDrawBar
282: Input Parameters:
283: + bar - The bar graph context
284: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
285: different color
287: Level: intermediate
289: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
291: @*/
292: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
293: {
296: bar->color = color;
297: return(0);
298: }
300: /*@
301: PetscDrawBarSort - Sorts the values before drawing the bar chart
303: Logically Collective on PetscDrawBar
305: Input Parameters:
306: + bar - The bar graph context
307: . sort - PETSC_TRUE to sort the values
308: . tolerance - discard values less than tolerance
310: Level: intermediate
312: Concepts: bar graph^setting axis
314: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
315: @*/
316: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
317: {
320: bar->sort = sort;
321: bar->sorttolerance = tolerance;
322: return(0);
323: }
325: /*@
326: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
327: points are added after this call, the limits will be adjusted to
328: include those additional points.
330: Logically Collective on PetscDrawBar
332: Input Parameters:
333: + bar - The bar graph context
334: - y_min,y_max - The limits
336: Level: intermediate
338: Concepts: bar graph^setting axis
340: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
341: @*/
342: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
343: {
346: bar->ymin = y_min;
347: bar->ymax = y_max;
348: return(0);
349: }
351: /*@C
352: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
353: This is useful if one wants to change some axis property, such as
354: labels, color, etc. The axis context should not be destroyed by the
355: application code.
357: Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel
359: Input Parameter:
360: . bar - The bar graph context
362: Output Parameter:
363: . axis - The axis context
365: Level: intermediate
367: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
368: @*/
369: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
370: {
374: *axis = bar->axis;
375: return(0);
376: }
378: /*@C
379: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
381: Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
383: Input Parameter:
384: . bar - The bar graph context
386: Output Parameter:
387: . draw - The draw context
389: Level: intermediate
391: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
392: @*/
393: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
394: {
398: *draw = bar->win;
399: return(0);
400: }
402: /*@
403: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
405: Collective over PetscDrawBar
407: Options Database:
408: . -bar_sort - sort the entries before drawing the bar graph
410: Level: intermediate
413: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
414: @*/
415: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
416: {
418: PetscBool set;
423: PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
424: if (set) {
425: PetscReal tol = bar->sorttolerance;
426: PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
427: PetscDrawBarSort(bar,PETSC_TRUE,tol);
428: }
429: return(0);
430: }