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;
43: PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
44: PetscLogObjectParent((PetscObject)draw,(PetscObject)h);
46: PetscObjectReference((PetscObject)draw);
47: h->win = draw;
49: h->view = NULL;
50: h->destroy = NULL;
51: h->color = PETSC_DRAW_GREEN;
52: h->ymin = 0.; /* if user has not set these then they are determined from the data */
53: h->ymax = 0.;
54: h->numBins = 0;
56: PetscDrawAxisCreate(draw,&h->axis);
57: h->axis->xticks = NULL;
59: *bar = h;
60: return 0;
61: }
63: /*@C
64: PetscDrawBarSetData
66: Logically Collective on PetscDrawBar
68: Input Parameters:
69: + bar - The bar graph context.
70: . bins - number of items
71: . values - values of each item
72: - labels - optional label for each bar, NULL terminated array of strings
74: Level: intermediate
76: Notes:
77: Call PetscDrawBarDraw() after this call to display the new plot
79: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw()
81: @*/
82: PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
83: {
86: if (bar->numBins != bins) {
87: PetscFree(bar->values);
88: PetscMalloc1(bins, &bar->values);
89: bar->numBins = bins;
90: }
91: PetscArraycpy(bar->values,data,bins);
92: bar->numBins = bins;
93: if (labels) {
94: PetscStrArrayallocpy(labels,&bar->labels);
95: }
96: return 0;
97: }
99: /*@C
100: PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
102: Collective over PetscDrawBar
104: Input Parameter:
105: . bar - The bar graph context
107: Level: intermediate
109: .seealso: PetscDrawBarCreate()
110: @*/
111: PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar)
112: {
113: if (!*bar) return 0;
115: if (--((PetscObject)(*bar))->refct > 0) return 0;
117: PetscFree((*bar)->values);
118: PetscStrArrayDestroy(&(*bar)->labels);
119: PetscDrawAxisDestroy(&(*bar)->axis);
120: PetscDrawDestroy(&(*bar)->win);
121: PetscHeaderDestroy(bar);
122: return 0;
123: }
125: /*@
126: PetscDrawBarDraw - Redraws a bar graph.
128: Collective on PetscDrawBar
130: Input Parameter:
131: . bar - The bar graph context
133: Level: intermediate
135: .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData()
137: @*/
138: PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar)
139: {
140: PetscDraw draw;
141: PetscBool isnull;
142: PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight;
143: PetscInt numValues,i,bcolor,color,idx,*perm,nplot;
144: PetscMPIInt rank;
145: char **labels;
149: PetscDrawIsNull(bar->win,&isnull);
150: if (isnull) return 0;
151: MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);
153: if (bar->numBins < 1) return 0;
155: color = bar->color;
156: if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
157: else bcolor = color;
159: numValues = bar->numBins;
160: values = bar->values;
161: if (bar->ymin == bar->ymax) {
162: /* user has not set bounds on bars so set them based on the data */
163: ymin = PETSC_MAX_REAL;
164: ymax = PETSC_MIN_REAL;
165: for (i=0; i<numValues; i++) {
166: ymin = PetscMin(ymin,values[i]);
167: ymax = PetscMax(ymax,values[i]);
168: }
169: } else {
170: ymin = bar->ymin;
171: ymax = bar->ymax;
172: }
173: nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */
174: xmin = 0.0;
175: xmax = nplot;
176: labels = bar->labels;
178: if (bar->sort) {
179: PetscMalloc1(numValues,&perm);
180: for (i=0; i<numValues;i++) perm[i] = i;
181: PetscSortRealWithPermutation(numValues,values,perm);
182: if (bar->sorttolerance) {
183: for (i=0; i<numValues;i++) {
184: if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
185: nplot = i;
186: break;
187: }
188: }
189: }
190: }
192: draw = bar->win;
193: PetscDrawCheckResizedWindow(draw);
194: PetscDrawClear(draw);
196: PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
197: PetscDrawAxisDraw(bar->axis);
199: PetscDrawCollectiveBegin(draw);
200: if (rank == 0) { /* Draw bins */
201: for (i=0; i<nplot; i++) {
202: idx = (bar->sort ? perm[numValues - i - 1] : i);
203: binLeft = xmin + i;
204: binRight = xmin + i + 1;
205: PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
206: PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
207: PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
208: PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
209: if (labels) {
210: PetscReal h;
211: PetscDrawStringGetSize(draw,NULL,&h);
212: PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
213: }
214: if (color == PETSC_DRAW_ROTATE) bcolor++;
215: if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
216: }
217: }
218: PetscDrawCollectiveEnd(draw);
219: if (bar->sort) PetscFree(perm);
221: PetscDrawFlush(draw);
222: PetscDrawPause(draw);
223: return 0;
224: }
226: /*@
227: PetscDrawBarSave - Saves a drawn image
229: Collective on PetscDrawBar
231: Input Parameters:
232: . bar - The bar graph context
234: Level: intermediate
236: .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
237: @*/
238: PetscErrorCode PetscDrawBarSave(PetscDrawBar bar)
239: {
241: PetscDrawSave(bar->win);
242: return 0;
243: }
245: /*@
246: PetscDrawBarSetColor - Sets the color the bars will be drawn with.
248: Logically Collective on PetscDrawBar
250: Input Parameters:
251: + bar - The bar graph context
252: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
253: different color
255: Level: intermediate
257: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
259: @*/
260: PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color)
261: {
263: bar->color = color;
264: return 0;
265: }
267: /*@
268: PetscDrawBarSort - Sorts the values before drawing the bar chart
270: Logically Collective on PetscDrawBar
272: Input Parameters:
273: + bar - The bar graph context
274: . sort - PETSC_TRUE to sort the values
275: - tolerance - discard values less than tolerance
277: Level: intermediate
279: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
280: @*/
281: PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
282: {
284: bar->sort = sort;
285: bar->sorttolerance = tolerance;
286: return 0;
287: }
289: /*@
290: PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
291: points are added after this call, the limits will be adjusted to
292: include those additional points.
294: Logically Collective on PetscDrawBar
296: Input Parameters:
297: + bar - The bar graph context
298: - y_min,y_max - The limits
300: Level: intermediate
302: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
303: @*/
304: PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
305: {
307: bar->ymin = y_min;
308: bar->ymax = y_max;
309: return 0;
310: }
312: /*@C
313: PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
314: This is useful if one wants to change some axis property, such as
315: labels, color, etc. The axis context should not be destroyed by the
316: application code.
318: Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel
320: Input Parameter:
321: . bar - The bar graph context
323: Output Parameter:
324: . axis - The axis context
326: Level: intermediate
328: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
329: @*/
330: PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
331: {
334: *axis = bar->axis;
335: return 0;
336: }
338: /*@C
339: PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
341: Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
343: Input Parameter:
344: . bar - The bar graph context
346: Output Parameter:
347: . draw - The draw context
349: Level: intermediate
351: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
352: @*/
353: PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
354: {
357: *draw = bar->win;
358: return 0;
359: }
361: /*@
362: PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
364: Collective over PetscDrawBar
366: Options Database:
367: . -bar_sort - sort the entries before drawing the bar graph
369: Level: intermediate
371: .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
372: @*/
373: PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar)
374: {
375: PetscBool set;
379: PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
380: if (set) {
381: PetscReal tol = bar->sorttolerance;
382: PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
383: PetscDrawBarSort(bar,PETSC_TRUE,tol);
384: }
385: return 0;
386: }