Actual source code: bars.c
petsc-3.10.5 2019-03-28
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 http://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: Concepts: bar graph^creating
52: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarDestroy(), PetscDrawBarSetData(),
53: PetscDrawBar, PetscDrawBarDraw(), PetscDrawBarSave(), PetscDrawBarSetColor(), PetscDrawBarSort(), PetscDrawBarSetLimits(), PetscDrawBarGetAxis(), PetscDrawAxis,
54: PetscDrawBarGetDraw(), PetscDrawBarSetFromOptions()
55: @*/
56: PetscErrorCode PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
57: {
58: PetscDrawBar h;
65: PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
66: PetscLogObjectParent((PetscObject)draw,(PetscObject)h);
68: PetscObjectReference((PetscObject)draw);
69: h->win = draw;
71: h->view = NULL;
72: h->destroy = NULL;
73: h->color = PETSC_DRAW_GREEN;
74: h->ymin = 0.; /* if user has not set these then they are determined from the data */
75: h->ymax = 0.;
76: h->numBins = 0;
78: PetscDrawAxisCreate(draw,&h->axis);
79: h->axis->xticks = NULL;
81: *bar = h;
82: return(0);
83: }
85: /*@C
86: PetscDrawBarSetData
88: Logically Collective on PetscDrawBar
90: Input Parameter:
91: + bar - The bar graph context.
92: . bins - number of items
93: . values - values of each item
94: - labels - optional label for each bar, NULL terminated array of strings
96: Level: intermediate
98: Notes:
99: Call PetscDrawBarDraw() after this call to display the new plot
101: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw()
103: @*/
104: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
105: {
111: if (bar->numBins != bins) {
112: PetscFree(bar->values);
113: PetscMalloc1(bins, &bar->values);
114: bar->numBins = bins;
115: }
116: PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));
117: bar->numBins = bins;
118: if (labels) {
119: PetscStrArrayallocpy(labels,&bar->labels);
120: }
121: return(0);
122: }
124: /*@C
125: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
127: Collective over PetscDrawBar
129: Input Parameter:
130: . bar - The bar graph context
132: Level: intermediate
134: .seealso: PetscDrawBarCreate()
135: @*/
136: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
137: {
141: if (!*bar) return(0);
143: if (--((PetscObject)(*bar))->refct > 0) return(0);
145: PetscFree((*bar)->values);
146: PetscStrArrayDestroy(&(*bar)->labels);
147: PetscDrawAxisDestroy(&(*bar)->axis);
148: PetscDrawDestroy(&(*bar)->win);
149: PetscHeaderDestroy(bar);
150: return(0);
151: }
153: /*@
154: PetscDrawBarDraw - Redraws a bar graph.
156: Collective on PetscDrawBar
158: Input Parameter:
159: . bar - The bar graph context
161: Level: intermediate
163: .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData()
165: @*/
166: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
167: {
168: PetscDraw draw;
169: PetscBool isnull;
170: PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight;
171: PetscInt numValues,i,bcolor,color,idx,*perm,nplot;
172: PetscMPIInt rank;
174: char **labels;
178: PetscDrawIsNull(bar->win,&isnull);
179: if (isnull) return(0);
180: MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);
182: if (bar->numBins < 1) return(0);
184: color = bar->color;
185: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
186: else bcolor = color;
188: numValues = bar->numBins;
189: values = bar->values;
190: if (bar->ymin == bar->ymax) {
191: /* user has not set bounds on bars so set them based on the data */
192: ymin = PETSC_MAX_REAL;
193: ymax = PETSC_MIN_REAL;
194: for (i=0; i<numValues; i++) {
195: ymin = PetscMin(ymin,values[i]);
196: ymax = PetscMax(ymax,values[i]);
197: }
198: } else {
199: ymin = bar->ymin;
200: ymax = bar->ymax;
201: }
202: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
203: xmin = 0.0;
204: xmax = nplot;
205: labels = bar->labels;
207: if (bar->sort) {
208: PetscMalloc1(numValues,&perm);
209: for (i=0; i<numValues;i++) perm[i] = i;
210: PetscSortRealWithPermutation(numValues,values,perm);
211: if (bar->sorttolerance) {
212: for (i=0; i<numValues;i++) {
213: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
214: nplot = i;
215: break;
216: }
217: }
218: }
219: }
221: draw = bar->win;
222: PetscDrawCheckResizedWindow(draw);
223: PetscDrawClear(draw);
225: PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
226: PetscDrawAxisDraw(bar->axis);
228: PetscDrawCollectiveBegin(draw);
229: if (!rank) { /* Draw bins */
230: for (i=0; i<nplot; i++) {
231: idx = (bar->sort ? perm[numValues - i - 1] : i);
232: binLeft = xmin + i;
233: binRight = xmin + i + 1;
234: PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
235: PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
236: PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
237: PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
238: if (labels) {
239: PetscReal h;
240: PetscDrawStringGetSize(draw,NULL,&h);
241: PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
242: }
243: if (color == PETSC_DRAW_ROTATE) bcolor++;
244: if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
245: }
246: }
247: PetscDrawCollectiveEnd(draw);
248: if (bar->sort) {PetscFree(perm);}
250: PetscDrawFlush(draw);
251: PetscDrawPause(draw);
252: return(0);
253: }
255: /*@
256: PetscDrawBarSave - Saves a drawn image
258: Collective on PetscDrawBar
260: Input Parameters:
261: . bar - The bar graph context
263: Level: intermediate
265: Concepts: bar graph^saving
267: .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
268: @*/
269: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
270: {
275: PetscDrawSave(bar->win);
276: return(0);
277: }
279: /*@
280: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
282: Logically Collective on PetscDrawBar
284: Input Parameters:
285: + bar - The bar graph context
286: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
287: different color
289: Level: intermediate
291: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
293: @*/
294: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
295: {
298: bar->color = color;
299: return(0);
300: }
302: /*@
303: PetscDrawBarSort - Sorts the values before drawing the bar chart
305: Logically Collective on PetscDrawBar
307: Input Parameters:
308: + bar - The bar graph context
309: . sort - PETSC_TRUE to sort the values
310: . tolerance - discard values less than tolerance
312: Level: intermediate
314: Concepts: bar graph^setting axis
316: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
317: @*/
318: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
319: {
322: bar->sort = sort;
323: bar->sorttolerance = tolerance;
324: return(0);
325: }
327: /*@
328: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
329: points are added after this call, the limits will be adjusted to
330: include those additional points.
332: Logically Collective on PetscDrawBar
334: Input Parameters:
335: + bar - The bar graph context
336: - y_min,y_max - The limits
338: Level: intermediate
340: Concepts: bar graph^setting axis
342: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
343: @*/
344: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
345: {
348: bar->ymin = y_min;
349: bar->ymax = y_max;
350: return(0);
351: }
353: /*@C
354: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
355: This is useful if one wants to change some axis property, such as
356: labels, color, etc. The axis context should not be destroyed by the
357: application code.
359: Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel
361: Input Parameter:
362: . bar - The bar graph context
364: Output Parameter:
365: . axis - The axis context
367: Level: intermediate
369: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
370: @*/
371: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
372: {
376: *axis = bar->axis;
377: return(0);
378: }
380: /*@C
381: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
383: Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
385: Input Parameter:
386: . bar - The bar graph context
388: Output Parameter:
389: . draw - The draw context
391: Level: intermediate
393: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
394: @*/
395: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
396: {
400: *draw = bar->win;
401: return(0);
402: }
404: /*@
405: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
407: Collective over PetscDrawBar
409: Options Database:
410: . -bar_sort - sort the entries before drawing the bar graph
412: Level: intermediate
415: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
416: @*/
417: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
418: {
420: PetscBool set;
425: PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
426: if (set) {
427: PetscReal tol = bar->sorttolerance;
428: PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
429: PetscDrawBarSort(bar,PETSC_TRUE,tol);
430: }
431: return(0);
432: }