xref: /petsc/src/sys/classes/draw/utils/bars.c (revision 48cdcd6b53bc91835c082adca72c212f70eee222)
1 
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 */
9 
10 PetscClassId PETSC_DRAWBAR_CLASSID = 0;
11 
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 };
26 
27 #define CHUNKSIZE 100
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "PetscDrawBarCreate"
31 /*@C
32    PetscDrawBarCreate - Creates a bar graph data structure.
33 
34    Collective over PetscDraw
35 
36    Input Parameters:
37 .  draw  - The window where the graph will be made
38 
39    Output Parameters:
40 .  bar - The bar graph context
41 
42    Level: intermediate
43 
44    Concepts: bar graph^creating
45 
46 .seealso: PetscDrawBarDestroy()
47 
48 @*/
49 PetscErrorCode  PetscDrawBarCreate(PetscDraw draw, PetscDrawBar *bar)
50 {
51   PetscDrawBar    h;
52   PetscBool      isnull;
53   PetscErrorCode ierr;
54 
55   PetscFunctionBegin;
56   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
57   PetscValidPointer(bar,2);
58   ierr = PetscHeaderCreate(h, PETSC_DRAWBAR_CLASSID, "PetscDrawBar", "Bar Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawBarDestroy, NULL);CHKERRQ(ierr);
59 
60   h->view        = NULL;
61   h->destroy     = NULL;
62   h->win         = draw;
63 
64   ierr = PetscObjectReference((PetscObject) draw);CHKERRQ(ierr);
65 
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;
70 
71   ierr = PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);CHKERRQ(ierr);
72   if (!isnull) {
73     ierr = PetscDrawAxisCreate(draw, &h->axis);CHKERRQ(ierr);
74     h->axis->xticks = NULL;
75   } else h->axis = NULL;
76   *bar = h;
77   PetscFunctionReturn(0);
78 }
79 
80 #undef __FUNCT__
81 #define __FUNCT__ "PetscDrawBarSetData"
82 /*@C
83    PetscDrawBarSetData
84 
85    Not Collective (ignored except on processor 0 of PetscDrawBar)
86 
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
92 
93    Level: intermediate
94 
95 
96 @*/
97 PetscErrorCode  PetscDrawBarSetData(PetscDrawBar bar, PetscInt bins,const PetscReal data[],const char *const *labels)
98 {
99   PetscErrorCode ierr;
100 
101   PetscFunctionBegin;
102   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
103   if (bar->numBins != bins) {
104     ierr = PetscFree(bar->values);CHKERRQ(ierr);
105     ierr = PetscMalloc1(bins, &bar->values);CHKERRQ(ierr);
106     bar->numBins = bins;
107   }
108   ierr = PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));CHKERRQ(ierr);
109   bar->numBins = bins;
110   if (labels) {
111     ierr = PetscStrArrayallocpy(labels,&bar->labels);CHKERRQ(ierr);
112   }
113   PetscFunctionReturn(0);
114 }
115 
116 #undef __FUNCT__
117 #define __FUNCT__ "PetscDrawBarDestroy"
118 /*@C
119   PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
120 
121   Collective over PetscDrawBar
122 
123   Input Parameter:
124 . bar - The bar graph context
125 
126   Level: intermediate
127 
128 .seealso:  PetscDrawBarCreate()
129 @*/
130 PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
131 {
132   PetscErrorCode ierr;
133 
134   PetscFunctionBegin;
135   if (!*bar) PetscFunctionReturn(0);
136   PetscValidHeader(*bar,1);
137 
138   if (--((PetscObject)(*bar))->refct > 0) PetscFunctionReturn(0);
139   ierr = PetscDrawAxisDestroy(&(*bar)->axis);CHKERRQ(ierr);
140   ierr = PetscDrawDestroy(&(*bar)->win);CHKERRQ(ierr);
141   ierr = PetscFree((*bar)->values);CHKERRQ(ierr);
142   ierr = PetscStrArrayDestroy(&(*bar)->labels);CHKERRQ(ierr);
143   ierr = PetscHeaderDestroy(bar);CHKERRQ(ierr);
144   PetscFunctionReturn(0);
145 }
146 
147 #undef __FUNCT__
148 #define __FUNCT__ "PetscDrawBarDraw"
149 /*@
150   PetscDrawBarDraw - Redraws a bar graph.
151 
152   Not Collective (ignored except on processor 0 of PetscDrawBar)
153 
154   Input Parameter:
155 . bar - The bar graph context
156 
157   Level: intermediate
158 
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;
166   PetscErrorCode ierr;
167   char           **labels;
168 
169   PetscFunctionBegin;
170   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
171   ierr = PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);CHKERRQ(ierr);
172   if (isnull) PetscFunctionReturn(0);
173   if (bar->numBins < 1) PetscFunctionReturn(0);
174 
175   color = bar->color;
176   if (color == PETSC_DRAW_ROTATE) bcolor = 2;
177   else bcolor = color;
178 
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;
196 
197   if (bar->sort) {
198     ierr = PetscMalloc1(numValues,&perm);CHKERRQ(ierr);
199     for (i=0; i<numValues;i++) perm[i] = i;
200     ierr = PetscSortRealWithPermutation(numValues,values,perm);CHKERRQ(ierr);
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   }
210 
211   xmax   = nplot;
212   ierr = PetscDrawAxisSetLimits(bar->axis, xmin, xmax, ymin, ymax);CHKERRQ(ierr);
213   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
214   ierr = PetscDrawAxisDraw(bar->axis);CHKERRQ(ierr);
215 
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     ierr = PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);CHKERRQ(ierr);
222     ierr = PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr);
223     ierr = PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr);
224     ierr = PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr);
225     if (labels) {
226       PetscReal h;
227       ierr = PetscDrawStringGetSize(draw,NULL,&h);CHKERRQ(ierr);
228       ierr = PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.2*h,bcolor,labels[idx]);CHKERRQ(ierr);
229     }
230     if (color == PETSC_DRAW_ROTATE) bcolor++;
231     if (bcolor > 31) bcolor = 2;
232   }
233   if (bar->sort) {
234     ierr = PetscFree(perm);CHKERRQ(ierr);
235   }
236   ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
237   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "PetscDrawBarSetColor"
243 /*@
244   PetscDrawBarSetColor - Sets the color the bars will be drawn with.
245 
246   Not Collective (ignored except on processor 0 of PetscDrawBar)
247 
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
252 
253   Level: intermediate
254 
255 @*/
256 PetscErrorCode  PetscDrawBarSetColor(PetscDrawBar bar, int color)
257 {
258   PetscFunctionBegin;
259   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
260   bar->color = color;
261   PetscFunctionReturn(0);
262 }
263 
264 #undef __FUNCT__
265 #define __FUNCT__ "PetscDrawBarSort"
266 /*@
267   PetscDrawBarSort - Sorts the values before drawing the bar chart
268 
269   Not Collective (ignored except on processor 0 of PetscDrawBar)
270 
271   Input Parameters:
272 + bar - The bar graph context
273 . sort - PETSC_TRUE to sort the values
274 . tolerance - discard values less than tolerance
275 
276   Level: intermediate
277 
278   Concepts: bar graph^setting axis
279 @*/
280 PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
281 {
282   PetscFunctionBegin;
283   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
284   bar->sort          = sort;
285   bar->sorttolerance = tolerance;
286   PetscFunctionReturn(0);
287 }
288 
289 #undef __FUNCT__
290 #define __FUNCT__ "PetscDrawBarSetLimits"
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.
295 
296   Not Collective (ignored except on processor 0 of PetscDrawBar)
297 
298   Input Parameters:
299 + bar - The bar graph context
300 - y_min,y_max - The limits
301 
302   Level: intermediate
303 
304   Concepts: bar graph^setting axis
305 @*/
306 PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
307 {
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
310   bar->ymin = y_min;
311   bar->ymax = y_max;
312   PetscFunctionReturn(0);
313 }
314 
315 #undef __FUNCT__
316 #define __FUNCT__ "PetscDrawBarGetAxis"
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.
322 
323   Not Collective (ignored except on processor 0 of PetscDrawBar)
324 
325   Input Parameter:
326 . bar - The bar graph context
327 
328   Output Parameter:
329 . axis - The axis context
330 
331   Level: intermediate
332 
333 @*/
334 PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis)
335 {
336   PetscFunctionBegin;
337   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
338   PetscValidPointer(axis,2);
339   *axis = bar->axis;
340   PetscFunctionReturn(0);
341 }
342 
343 #undef __FUNCT__
344 #define __FUNCT__ "PetscDrawBarGetDraw"
345 /*@C
346   PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
347 
348   Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
349 
350   Input Parameter:
351 . bar - The bar graph context
352 
353   Output Parameter:
354 . win  - The draw context
355 
356   Level: intermediate
357 
358 @*/
359 PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *win)
360 {
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
363   PetscValidPointer(win,2);
364   *win = bar->win;
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "PetscDrawBarSetFromOptions"
370 /*@
371     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
372 
373     Collective over PetscDrawBar
374 
375     Options Database:
376 .  -bar_sort - sort the entries before drawing the bar graph
377 
378     Level: intermediate
379 
380 
381 .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate()
382 @*/
383 PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
384 {
385   PetscErrorCode ierr;
386   PetscBool      set;
387   PetscReal      tol = bar->sorttolerance;
388 
389   PetscFunctionBegin;
390   ierr = PetscOptionsHasName(NULL,"-bar_sort",&set);CHKERRQ(ierr);
391   if (set) {
392     ierr = PetscOptionsGetReal(NULL,"-bar_sort",&tol,NULL);CHKERRQ(ierr);
393     ierr = PetscDrawBarSort(bar,PETSC_TRUE,tol);CHKERRQ(ierr);
394   }
395   PetscFunctionReturn(0);
396 }
397 
398