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 PetscDraw
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 process in the communicator. All MPI processes in the communicator must call PetscDrawBarDraw() to display the updated graph.
30: Level: intermediate
32: .seealso: 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;
45: PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
46: PetscLogObjectParent((PetscObject)draw,(PetscObject)h);
48: PetscObjectReference((PetscObject)draw);
49: h->win = draw;
51: h->view = NULL;
52: h->destroy = NULL;
53: h->color = PETSC_DRAW_GREEN;
54: h->ymin = 0.; /* if user has not set these then they are determined from the data */
55: h->ymax = 0.;
56: h->numBins = 0;
58: PetscDrawAxisCreate(draw,&h->axis);
59: h->axis->xticks = NULL;
61: *bar = h;
62: return(0);
63: }
65: /*@C
66: PetscDrawBarSetData
68: Logically Collective on PetscDrawBar
70: Input Parameters:
71: + bar - The bar graph context.
72: . bins - number of items
73: . values - values of each item
74: - labels - optional label for each bar, NULL terminated array of strings
76: Level: intermediate
78: Notes:
79: Call PetscDrawBarDraw() after this call to display the new plot
81: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw()
83: @*/
84: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
85: {
91: if (bar->numBins != bins) {
92: PetscFree(bar->values);
93: PetscMalloc1(bins, &bar->values);
94: bar->numBins = bins;
95: }
96: PetscArraycpy(bar->values,data,bins);
97: bar->numBins = bins;
98: if (labels) {
99: PetscStrArrayallocpy(labels,&bar->labels);
100: }
101: return(0);
102: }
104: /*@C
105: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
107: Collective over PetscDrawBar
109: Input Parameter:
110: . bar - The bar graph context
112: Level: intermediate
114: .seealso: PetscDrawBarCreate()
115: @*/
116: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
117: {
121: if (!*bar) return(0);
123: if (--((PetscObject)(*bar))->refct > 0) return(0);
125: PetscFree((*bar)->values);
126: PetscStrArrayDestroy(&(*bar)->labels);
127: PetscDrawAxisDestroy(&(*bar)->axis);
128: PetscDrawDestroy(&(*bar)->win);
129: PetscHeaderDestroy(bar);
130: return(0);
131: }
133: /*@
134: PetscDrawBarDraw - Redraws a bar graph.
136: Collective on PetscDrawBar
138: Input Parameter:
139: . bar - The bar graph context
141: Level: intermediate
143: .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData()
145: @*/
146: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
147: {
148: PetscDraw draw;
149: PetscBool isnull;
150: PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight;
151: PetscInt numValues,i,bcolor,color,idx,*perm,nplot;
152: PetscMPIInt rank;
154: char **labels;
158: PetscDrawIsNull(bar->win,&isnull);
159: if (isnull) return(0);
160: MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);
162: if (bar->numBins < 1) return(0);
164: color = bar->color;
165: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
166: else bcolor = color;
168: numValues = bar->numBins;
169: values = bar->values;
170: if (bar->ymin == bar->ymax) {
171: /* user has not set bounds on bars so set them based on the data */
172: ymin = PETSC_MAX_REAL;
173: ymax = PETSC_MIN_REAL;
174: for (i=0; i<numValues; i++) {
175: ymin = PetscMin(ymin,values[i]);
176: ymax = PetscMax(ymax,values[i]);
177: }
178: } else {
179: ymin = bar->ymin;
180: ymax = bar->ymax;
181: }
182: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
183: xmin = 0.0;
184: xmax = nplot;
185: labels = bar->labels;
187: if (bar->sort) {
188: PetscMalloc1(numValues,&perm);
189: for (i=0; i<numValues;i++) perm[i] = i;
190: PetscSortRealWithPermutation(numValues,values,perm);
191: if (bar->sorttolerance) {
192: for (i=0; i<numValues;i++) {
193: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
194: nplot = i;
195: break;
196: }
197: }
198: }
199: }
201: draw = bar->win;
202: PetscDrawCheckResizedWindow(draw);
203: PetscDrawClear(draw);
205: PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
206: PetscDrawAxisDraw(bar->axis);
208: PetscDrawCollectiveBegin(draw);
209: if (rank == 0) { /* Draw bins */
210: for (i=0; i<nplot; i++) {
211: idx = (bar->sort ? perm[numValues - i - 1] : i);
212: binLeft = xmin + i;
213: binRight = xmin + i + 1;
214: PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
215: PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
216: PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
217: PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
218: if (labels) {
219: PetscReal h;
220: PetscDrawStringGetSize(draw,NULL,&h);
221: PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
222: }
223: if (color == PETSC_DRAW_ROTATE) bcolor++;
224: if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
225: }
226: }
227: PetscDrawCollectiveEnd(draw);
228: if (bar->sort) {PetscFree(perm);}
230: PetscDrawFlush(draw);
231: PetscDrawPause(draw);
232: return(0);
233: }
235: /*@
236: PetscDrawBarSave - Saves a drawn image
238: Collective on PetscDrawBar
240: Input Parameters:
241: . bar - The bar graph context
243: Level: intermediate
245: .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
246: @*/
247: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
248: {
253: PetscDrawSave(bar->win);
254: return(0);
255: }
257: /*@
258: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
260: Logically Collective on PetscDrawBar
262: Input Parameters:
263: + bar - The bar graph context
264: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
265: different color
267: Level: intermediate
269: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
271: @*/
272: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
273: {
276: bar->color = color;
277: return(0);
278: }
280: /*@
281: PetscDrawBarSort - Sorts the values before drawing the bar chart
283: Logically Collective on PetscDrawBar
285: Input Parameters:
286: + bar - The bar graph context
287: . sort - PETSC_TRUE to sort the values
288: - tolerance - discard values less than tolerance
290: Level: intermediate
292: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
293: @*/
294: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
295: {
298: bar->sort = sort;
299: bar->sorttolerance = tolerance;
300: return(0);
301: }
303: /*@
304: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
305: points are added after this call, the limits will be adjusted to
306: include those additional points.
308: Logically Collective on PetscDrawBar
310: Input Parameters:
311: + bar - The bar graph context
312: - y_min,y_max - The limits
314: Level: intermediate
316: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
317: @*/
318: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
319: {
322: bar->ymin = y_min;
323: bar->ymax = y_max;
324: return(0);
325: }
327: /*@C
328: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
329: This is useful if one wants to change some axis property, such as
330: labels, color, etc. The axis context should not be destroyed by the
331: application code.
333: Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel
335: Input Parameter:
336: . bar - The bar graph context
338: Output Parameter:
339: . axis - The axis context
341: Level: intermediate
343: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
344: @*/
345: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
346: {
350: *axis = bar->axis;
351: return(0);
352: }
354: /*@C
355: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
357: Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
359: Input Parameter:
360: . bar - The bar graph context
362: Output Parameter:
363: . draw - The draw context
365: Level: intermediate
367: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
368: @*/
369: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
370: {
374: *draw = bar->win;
375: return(0);
376: }
378: /*@
379: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
381: Collective over PetscDrawBar
383: Options Database:
384: . -bar_sort - sort the entries before drawing the bar graph
386: Level: intermediate
388: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
389: @*/
390: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
391: {
393: PetscBool set;
398: PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
399: if (set) {
400: PetscReal tol = bar->sorttolerance;
401: PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
402: PetscDrawBarSort(bar,PETSC_TRUE,tol);
403: }
404: return(0);
405: }