Actual source code: bars.c
petsc-3.6.1 2015-08-06
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;
52: PetscBool isnull;
58: PetscHeaderCreate(h, PETSC_DRAWBAR_CLASSID, "PetscDrawBar", "Bar Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawBarDestroy, NULL);
60: h->view = NULL;
61: h->destroy = NULL;
62: h->win = draw;
64: PetscObjectReference((PetscObject) draw);
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: PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
72: if (!isnull) {
73: PetscDrawAxisCreate(draw, &h->axis);
74: h->axis->xticks = NULL;
75: } else h->axis = NULL;
76: *bar = h;
77: return(0);
78: }
82: /*@C
83: PetscDrawBarSetData
85: Not Collective (ignored except on processor 0 of PetscDrawBar)
87: Input Parameter:
88: + bar - The bar graph context.
89: . bins - number of items
90: . values - values of each item
91: - labels - optional label for each bar, NULL terminated array of strings
93: Level: intermediate
96: @*/
97: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar, PetscInt bins,const PetscReal data[],const char *const *labels)
98: {
103: if (bar->numBins != bins) {
104: PetscFree(bar->values);
105: PetscMalloc1(bins, &bar->values);
106: bar->numBins = bins;
107: }
108: PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));
109: bar->numBins = bins;
110: if (labels) {
111: PetscStrArrayallocpy(labels,&bar->labels);
112: }
113: return(0);
114: }
118: /*@C
119: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
121: Collective over PetscDrawBar
123: Input Parameter:
124: . bar - The bar graph context
126: Level: intermediate
128: .seealso: PetscDrawBarCreate()
129: @*/
130: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
131: {
135: if (!*bar) return(0);
138: if (--((PetscObject)(*bar))->refct > 0) return(0);
139: PetscDrawAxisDestroy(&(*bar)->axis);
140: PetscDrawDestroy(&(*bar)->win);
141: PetscFree((*bar)->values);
142: PetscStrArrayDestroy(&(*bar)->labels);
143: PetscHeaderDestroy(bar);
144: return(0);
145: }
149: /*@
150: PetscDrawBarDraw - Redraws a bar graph.
152: Not Collective (ignored except on processor 0 of PetscDrawBar)
154: Input Parameter:
155: . bar - The bar graph context
157: Level: intermediate
159: @*/
160: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
161: {
162: PetscDraw draw = bar->win;
163: PetscBool isnull;
164: PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight;
165: PetscInt numValues,i,bcolor,color,idx,*perm,nplot;
167: char **labels;
171: PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);
172: if (isnull) return(0);
173: if (bar->numBins < 1) return(0);
175: color = bar->color;
176: if (color == PETSC_DRAW_ROTATE) bcolor = 2;
177: else bcolor = color;
179: numValues = bar->numBins;
180: values = bar->values;
181: if (bar->ymin == bar->ymax) {
182: /* user has not set bounds on bars so set them based on the data */
183: ymin = PETSC_MAX_REAL;
184: ymax = PETSC_MIN_REAL;
185: for (i=0; i<numValues; i++) {
186: ymin = PetscMin(ymin,values[i]);
187: ymax = PetscMax(ymax,values[i]);
188: }
189: } else {
190: ymin = bar->ymin;
191: ymax = bar->ymax;
192: }
193: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
194: xmin = 0.0;
195: labels = bar->labels;
197: if (bar->sort) {
198: PetscMalloc1(numValues,&perm);
199: for (i=0; i<numValues;i++) perm[i] = i;
200: PetscSortRealWithPermutation(numValues,values,perm);
201: if (bar->sorttolerance) {
202: for (i=0; i<numValues;i++) {
203: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
204: nplot = i;
205: break;
206: }
207: }
208: }
209: }
211: xmax = nplot;
212: PetscDrawAxisSetLimits(bar->axis, xmin, xmax, ymin, ymax);
213: PetscDrawClear(draw);
214: PetscDrawAxisDraw(bar->axis);
216: /* Draw bins */
217: for (i = 0; i < nplot; i++) {
218: idx = (bar->sort ? perm[numValues - i - 1] : i);
219: binLeft = xmin + i;
220: binRight = xmin + i + 1;
221: PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
222: PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
223: PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
224: PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
225: if (labels) {
226: PetscReal h;
227: PetscDrawStringGetSize(draw,NULL,&h);
228: PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.2*h,bcolor,labels[idx]);
229: }
230: if (color == PETSC_DRAW_ROTATE) bcolor++;
231: if (bcolor > 31) bcolor = 2;
232: }
233: if (bar->sort) {
234: PetscFree(perm);
235: }
236: PetscDrawSynchronizedFlush(draw);
237: PetscDrawPause(draw);
238: return(0);
239: }
243: /*@
244: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
246: Not Collective (ignored except on processor 0 of PetscDrawBar)
248: Input Parameters:
249: + bar - The bar graph context
250: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
251: different color
253: Level: intermediate
255: @*/
256: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
257: {
260: bar->color = color;
261: return(0);
262: }
266: /*@
267: PetscDrawBarSort - Sorts the values before drawing the bar chart
269: Not Collective (ignored except on processor 0 of PetscDrawBar)
271: Input Parameters:
272: + bar - The bar graph context
273: . sort - PETSC_TRUE to sort the values
274: . tolerance - discard values less than tolerance
276: Level: intermediate
278: Concepts: bar graph^setting axis
279: @*/
280: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
281: {
284: bar->sort = sort;
285: bar->sorttolerance = tolerance;
286: return(0);
287: }
291: /*@
292: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
293: points are added after this call, the limits will be adjusted to
294: include those additional points.
296: Not Collective (ignored except on processor 0 of PetscDrawBar)
298: Input Parameters:
299: + bar - The bar graph context
300: - y_min,y_max - The limits
302: Level: intermediate
304: Concepts: bar graph^setting axis
305: @*/
306: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
307: {
310: bar->ymin = y_min;
311: bar->ymax = y_max;
312: return(0);
313: }
317: /*@C
318: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
319: This is useful if one wants to change some axis property, such as
320: labels, color, etc. The axis context should not be destroyed by the
321: application code.
323: Not Collective (ignored except on processor 0 of PetscDrawBar)
325: Input Parameter:
326: . bar - The bar graph context
328: Output Parameter:
329: . axis - The axis context
331: Level: intermediate
333: @*/
334: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis)
335: {
339: *axis = bar->axis;
340: return(0);
341: }
345: /*@C
346: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
348: Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
350: Input Parameter:
351: . bar - The bar graph context
353: Output Parameter:
354: . win - The draw context
356: Level: intermediate
358: @*/
359: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *win)
360: {
364: *win = bar->win;
365: return(0);
366: }
370: /*@
371: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
373: Collective over PetscDrawBar
375: Options Database:
376: . -bar_sort - sort the entries before drawing the bar graph
378: Level: intermediate
381: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate()
382: @*/
383: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
384: {
386: PetscBool set;
387: PetscReal tol = bar->sorttolerance;
390: PetscOptionsHasName(NULL,"-bar_sort",&set);
391: if (set) {
392: PetscOptionsGetReal(NULL,"-bar_sort",&tol,NULL);
393: PetscDrawBarSort(bar,PETSC_TRUE,tol);
394: }
395: return(0);
396: }