Actual source code: bars.c
petsc-3.7.7 2017-09-25
2: /*
3: Contains the data structure for plotting a bargraph in a window with an axis.
4: */
5: #include <petscdraw.h> /*I "petscdraw.h" I*/
6: #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
7: #include <petscviewer.h> /*I "petscviewer.h" I*/
8: #include <../src/sys/classes/draw/utils/axisimpl.h> /* so we can directly modify axis xticks */
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
31: /*@C
32: PetscDrawBarCreate - Creates a bar graph data structure.
34: Collective over PetscDraw
36: Input Parameters:
37: . draw - The window where the graph will be made
39: Output Parameters:
40: . bar - The bar graph context
42: Level: intermediate
44: Concepts: bar graph^creating
46: .seealso: PetscDrawBarDestroy()
48: @*/
49: PetscErrorCode PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
50: {
51: PetscDrawBar h;
58: PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
59: PetscLogObjectParent((PetscObject)draw,(PetscObject)h);
61: PetscObjectReference((PetscObject)draw);
62: h->win = draw;
64: h->view = NULL;
65: h->destroy = NULL;
66: h->color = PETSC_DRAW_GREEN;
67: h->ymin = 0.; /* if user has not set these then they are determined from the data */
68: h->ymax = 0.;
69: h->numBins = 0;
71: PetscDrawAxisCreate(draw,&h->axis);
72: h->axis->xticks = NULL;
74: *bar = h;
75: return(0);
76: }
80: /*@C
81: PetscDrawBarSetData
83: Logically Collective on PetscDrawBar
85: Input Parameter:
86: + bar - The bar graph context.
87: . bins - number of items
88: . values - values of each item
89: - labels - optional label for each bar, NULL terminated array of strings
91: Level: intermediate
94: @*/
95: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
96: {
102: if (bar->numBins != bins) {
103: PetscFree(bar->values);
104: PetscMalloc1(bins, &bar->values);
105: bar->numBins = bins;
106: }
107: PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));
108: bar->numBins = bins;
109: if (labels) {
110: PetscStrArrayallocpy(labels,&bar->labels);
111: }
112: return(0);
113: }
117: /*@C
118: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
120: Collective over PetscDrawBar
122: Input Parameter:
123: . bar - The bar graph context
125: Level: intermediate
127: .seealso: PetscDrawBarCreate()
128: @*/
129: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
130: {
134: if (!*bar) return(0);
136: if (--((PetscObject)(*bar))->refct > 0) return(0);
138: PetscFree((*bar)->values);
139: PetscStrArrayDestroy(&(*bar)->labels);
140: PetscDrawAxisDestroy(&(*bar)->axis);
141: PetscDrawDestroy(&(*bar)->win);
142: PetscHeaderDestroy(bar);
143: return(0);
144: }
148: /*@
149: PetscDrawBarDraw - Redraws a bar graph.
151: Collective on PetscDrawBar
153: Input Parameter:
154: . bar - The bar graph context
156: Level: intermediate
158: @*/
159: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
160: {
161: PetscDraw draw;
162: PetscBool isnull;
163: PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight;
164: PetscInt numValues,i,bcolor,color,idx,*perm,nplot;
165: PetscMPIInt rank;
167: char **labels;
171: PetscDrawIsNull(bar->win,&isnull);
172: if (isnull) return(0);
173: MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);
175: if (bar->numBins < 1) return(0);
177: color = bar->color;
178: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
179: else bcolor = color;
181: numValues = bar->numBins;
182: values = bar->values;
183: if (bar->ymin == bar->ymax) {
184: /* user has not set bounds on bars so set them based on the data */
185: ymin = PETSC_MAX_REAL;
186: ymax = PETSC_MIN_REAL;
187: for (i=0; i<numValues; i++) {
188: ymin = PetscMin(ymin,values[i]);
189: ymax = PetscMax(ymax,values[i]);
190: }
191: } else {
192: ymin = bar->ymin;
193: ymax = bar->ymax;
194: }
195: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
196: xmin = 0.0;
197: xmax = nplot;
198: labels = bar->labels;
200: if (bar->sort) {
201: PetscMalloc1(numValues,&perm);
202: for (i=0; i<numValues;i++) perm[i] = i;
203: PetscSortRealWithPermutation(numValues,values,perm);
204: if (bar->sorttolerance) {
205: for (i=0; i<numValues;i++) {
206: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
207: nplot = i;
208: break;
209: }
210: }
211: }
212: }
214: draw = bar->win;
215: PetscDrawCheckResizedWindow(draw);
216: PetscDrawClear(draw);
218: PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
219: PetscDrawAxisDraw(bar->axis);
221: PetscDrawCollectiveBegin(draw);
222: if (!rank) { /* Draw bins */
223: for (i=0; i<nplot; i++) {
224: idx = (bar->sort ? perm[numValues - i - 1] : i);
225: binLeft = xmin + i;
226: binRight = xmin + i + 1;
227: PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
228: PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
229: PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
230: PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
231: if (labels) {
232: PetscReal h;
233: PetscDrawStringGetSize(draw,NULL,&h);
234: PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
235: }
236: if (color == PETSC_DRAW_ROTATE) bcolor++;
237: if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
238: }
239: }
240: PetscDrawCollectiveEnd(draw);
241: if (bar->sort) {PetscFree(perm);}
243: PetscDrawFlush(draw);
244: PetscDrawPause(draw);
245: return(0);
246: }
250: /*@
251: PetscDrawBarSave - Saves a drawn image
253: Collective on PetscDrawBar
255: Input Parameters:
256: . bar - The bar graph context
258: Level: intermediate
260: Concepts: bar graph^saving
262: .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave()
263: @*/
264: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
265: {
270: PetscDrawSave(bar->win);
271: return(0);
272: }
276: /*@
277: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
279: Logically Collective on PetscDrawBar
281: Input Parameters:
282: + bar - The bar graph context
283: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
284: different color
286: Level: intermediate
288: @*/
289: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
290: {
293: bar->color = color;
294: return(0);
295: }
299: /*@
300: PetscDrawBarSort - Sorts the values before drawing the bar chart
302: Logically Collective on PetscDrawBar
304: Input Parameters:
305: + bar - The bar graph context
306: . sort - PETSC_TRUE to sort the values
307: . tolerance - discard values less than tolerance
309: Level: intermediate
311: Concepts: bar graph^setting axis
312: @*/
313: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
314: {
317: bar->sort = sort;
318: bar->sorttolerance = tolerance;
319: return(0);
320: }
324: /*@
325: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
326: points are added after this call, the limits will be adjusted to
327: include those additional points.
329: Logically Collective on PetscDrawBar
331: Input Parameters:
332: + bar - The bar graph context
333: - y_min,y_max - The limits
335: Level: intermediate
337: Concepts: bar graph^setting axis
338: @*/
339: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
340: {
343: bar->ymin = y_min;
344: bar->ymax = y_max;
345: return(0);
346: }
350: /*@C
351: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
352: This is useful if one wants to change some axis property, such as
353: labels, color, etc. The axis context should not be destroyed by the
354: application code.
356: Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel
358: Input Parameter:
359: . bar - The bar graph context
361: Output Parameter:
362: . axis - The axis context
364: Level: intermediate
366: @*/
367: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
368: {
372: *axis = bar->axis;
373: return(0);
374: }
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: @*/
392: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
393: {
397: *draw = bar->win;
398: return(0);
399: }
403: /*@
404: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
406: Collective over PetscDrawBar
408: Options Database:
409: . -bar_sort - sort the entries before drawing the bar graph
411: Level: intermediate
414: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate()
415: @*/
416: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
417: {
419: PetscBool set;
424: PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
425: if (set) {
426: PetscReal tol = bar->sorttolerance;
427: PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
428: PetscDrawBarSort(bar,PETSC_TRUE,tol);
429: }
430: return(0);
431: }