xref: /petsc/src/sys/classes/draw/utils/bars.c (revision af0996ce37bc06907c37d8d91773840993d61e62)
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   MPI_Comm       comm;
53   PetscBool      isnull;
54   PetscErrorCode ierr;
55 
56   PetscFunctionBegin;
57   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID,1);
58   PetscValidPointer(bar,3);
59   ierr = PetscObjectGetComm((PetscObject) draw, &comm);CHKERRQ(ierr);
60   ierr = PetscHeaderCreate(h, _p_PetscDrawBar, int, PETSC_DRAWBAR_CLASSID,  "PetscDrawBar", "Bar Graph", "Draw", comm, PetscDrawBarDestroy, NULL);CHKERRQ(ierr);
61 
62   h->view        = NULL;
63   h->destroy     = NULL;
64   h->win         = draw;
65 
66   ierr = PetscObjectReference((PetscObject) draw);CHKERRQ(ierr);
67 
68   h->color       = PETSC_DRAW_GREEN;
69   h->ymin        = 0.;  /* if user has not set these then they are determined from the data */
70   h->ymax        = 0.;
71   h->numBins     = 0;
72 
73   ierr = PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);CHKERRQ(ierr);
74   if (!isnull) {
75     ierr = PetscDrawAxisCreate(draw, &h->axis);CHKERRQ(ierr);
76     ierr = PetscLogObjectParent((PetscObject)h, (PetscObject)h->axis);CHKERRQ(ierr);
77     h->axis->xticks = NULL;
78   } else h->axis = NULL;
79   *bar = h;
80   PetscFunctionReturn(0);
81 }
82 
83 #undef __FUNCT__
84 #define __FUNCT__ "PetscDrawBarSetData"
85 /*@C
86    PetscDrawBarSetData
87 
88    Not Collective (ignored except on processor 0 of PetscDrawBar)
89 
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
95 
96    Level: intermediate
97 
98 
99 @*/
100 PetscErrorCode  PetscDrawBarSetData(PetscDrawBar bar, PetscInt bins,const PetscReal data[],const char *const *labels)
101 {
102   PetscErrorCode ierr;
103 
104   PetscFunctionBegin;
105   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
106   if (bar->numBins != bins) {
107     ierr = PetscFree(bar->values);CHKERRQ(ierr);
108     ierr = PetscMalloc1(bins, &bar->values);CHKERRQ(ierr);
109     bar->numBins = bins;
110   }
111   ierr = PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));CHKERRQ(ierr);
112   bar->numBins = bins;
113   if (labels) {
114     ierr = PetscStrArrayallocpy(labels,&bar->labels);CHKERRQ(ierr);
115   }
116   PetscFunctionReturn(0);
117 }
118 
119 #undef __FUNCT__
120 #define __FUNCT__ "PetscDrawBarDestroy"
121 /*@C
122   PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.
123 
124   Collective over PetscDrawBar
125 
126   Input Parameter:
127 . bar - The bar graph context
128 
129   Level: intermediate
130 
131 .seealso:  PetscDrawBarCreate()
132 @*/
133 PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
134 {
135   PetscErrorCode ierr;
136 
137   PetscFunctionBegin;
138   if (!*bar) PetscFunctionReturn(0);
139   PetscValidHeader(*bar,1);
140 
141   if (--((PetscObject)(*bar))->refct > 0) PetscFunctionReturn(0);
142   ierr = PetscDrawAxisDestroy(&(*bar)->axis);CHKERRQ(ierr);
143   ierr = PetscDrawDestroy(&(*bar)->win);CHKERRQ(ierr);
144   ierr = PetscFree((*bar)->values);CHKERRQ(ierr);
145   ierr = PetscStrArrayDestroy(&(*bar)->labels);CHKERRQ(ierr);
146   ierr = PetscHeaderDestroy(bar);CHKERRQ(ierr);
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "PetscDrawBarDraw"
152 /*@
153   PetscDrawBarDraw - Redraws a bar graph.
154 
155   Not Collective (ignored except on processor 0 of PetscDrawBar)
156 
157   Input Parameter:
158 . bar - The bar graph context
159 
160   Level: intermediate
161 
162 @*/
163 PetscErrorCode  PetscDrawBarDraw(PetscDrawBar bar)
164 {
165   PetscDraw      draw = bar->win;
166   PetscBool      isnull;
167   PetscReal      xmin,xmax,ymin,ymax,*values,binLeft,binRight;
168   PetscInt       numValues,i,bcolor,color,idx,*perm,nplot;
169   PetscErrorCode ierr;
170   char           **labels;
171 
172   PetscFunctionBegin;
173   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
174   ierr = PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);CHKERRQ(ierr);
175   if (isnull) PetscFunctionReturn(0);
176   if (bar->numBins < 1) PetscFunctionReturn(0);
177 
178   color = bar->color;
179   if (color == PETSC_DRAW_ROTATE) bcolor = 2;
180   else bcolor = color;
181 
182   numValues = bar->numBins;
183   values    = bar->values;
184   if (bar->ymin == bar->ymax) {
185     /* user has not set bounds on bars so set them based on the data */
186     ymin = PETSC_MAX_REAL;
187     ymax = PETSC_MIN_REAL;
188     for (i=0; i<numValues; i++) {
189       ymin = PetscMin(ymin,values[i]);
190       ymax = PetscMax(ymax,values[i]);
191     }
192   } else {
193     ymin      = bar->ymin;
194     ymax      = bar->ymax;
195   }
196   nplot  = numValues;  /* number of points to actually plot; if some are lower than requested tolerance */
197   xmin   = 0.0;
198   labels = bar->labels;
199 
200   if (bar->sort) {
201     ierr = PetscMalloc1(numValues,&perm);CHKERRQ(ierr);
202     for (i=0; i<numValues;i++) perm[i] = i;
203     ierr = PetscSortRealWithPermutation(numValues,values,perm);CHKERRQ(ierr);
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   }
213 
214   xmax   = nplot;
215   ierr = PetscDrawAxisSetLimits(bar->axis, xmin, xmax, ymin, ymax);CHKERRQ(ierr);
216   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
217   ierr = PetscDrawAxisDraw(bar->axis);CHKERRQ(ierr);
218 
219   /* Draw bins */
220   for (i = 0; i < nplot; i++) {
221     idx = (bar->sort ? perm[numValues - i - 1] : i);
222     binLeft  = xmin + i;
223     binRight = xmin + i + 1;
224     ierr = PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);CHKERRQ(ierr);
225     ierr = PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr);
226     ierr = PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr);
227     ierr = PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr);
228     if (labels) {
229       PetscReal h;
230       ierr = PetscDrawStringGetSize(draw,NULL,&h);CHKERRQ(ierr);
231       ierr = PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.2*h,bcolor,labels[idx]);CHKERRQ(ierr);
232     }
233     if (color == PETSC_DRAW_ROTATE) bcolor++;
234     if (bcolor > 31) bcolor = 2;
235   }
236   if (bar->sort) {
237     ierr = PetscFree(perm);CHKERRQ(ierr);
238   }
239   ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
240   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "PetscDrawBarSetColor"
246 /*@
247   PetscDrawBarSetColor - Sets the color the bars will be drawn with.
248 
249   Not Collective (ignored except on processor 0 of PetscDrawBar)
250 
251   Input Parameters:
252 + bar - The bar graph context
253 - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
254           different color
255 
256   Level: intermediate
257 
258 @*/
259 PetscErrorCode  PetscDrawBarSetColor(PetscDrawBar bar, int color)
260 {
261   PetscFunctionBegin;
262   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
263   bar->color = color;
264   PetscFunctionReturn(0);
265 }
266 
267 #undef __FUNCT__
268 #define __FUNCT__ "PetscDrawBarSort"
269 /*@
270   PetscDrawBarSort - Sorts the values before drawing the bar chart
271 
272   Not Collective (ignored except on processor 0 of PetscDrawBar)
273 
274   Input Parameters:
275 + bar - The bar graph context
276 . sort - PETSC_TRUE to sort the values
277 . tolerance - discard values less than tolerance
278 
279   Level: intermediate
280 
281   Concepts: bar graph^setting axis
282 @*/
283 PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
284 {
285   PetscFunctionBegin;
286   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
287   bar->sort          = sort;
288   bar->sorttolerance = tolerance;
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNCT__
293 #define __FUNCT__ "PetscDrawBarSetLimits"
294 /*@
295   PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
296   points are added after this call, the limits will be adjusted to
297   include those additional points.
298 
299   Not Collective (ignored except on processor 0 of PetscDrawBar)
300 
301   Input Parameters:
302 + bar - The bar graph context
303 - y_min,y_max - The limits
304 
305   Level: intermediate
306 
307   Concepts: bar graph^setting axis
308 @*/
309 PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
310 {
311   PetscFunctionBegin;
312   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
313   bar->ymin = y_min;
314   bar->ymax = y_max;
315   PetscFunctionReturn(0);
316 }
317 
318 #undef __FUNCT__
319 #define __FUNCT__ "PetscDrawBarGetAxis"
320 /*@C
321   PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
322   This is useful if one wants to change some axis property, such as
323   labels, color, etc. The axis context should not be destroyed by the
324   application code.
325 
326   Not Collective (ignored except on processor 0 of PetscDrawBar)
327 
328   Input Parameter:
329 . bar - The bar graph context
330 
331   Output Parameter:
332 . axis - The axis context
333 
334   Level: intermediate
335 
336 @*/
337 PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis)
338 {
339   PetscFunctionBegin;
340   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
341   PetscValidPointer(axis,2);
342   *axis = bar->axis;
343   PetscFunctionReturn(0);
344 }
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "PetscDrawBarGetDraw"
348 /*@C
349   PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.
350 
351   Not Collective, PetscDraw is parallel if PetscDrawBar is parallel
352 
353   Input Parameter:
354 . bar - The bar graph context
355 
356   Output Parameter:
357 . win  - The draw context
358 
359   Level: intermediate
360 
361 @*/
362 PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *win)
363 {
364   PetscFunctionBegin;
365   PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1);
366   PetscValidPointer(win,2);
367   *win = bar->win;
368   PetscFunctionReturn(0);
369 }
370 
371 #undef __FUNCT__
372 #define __FUNCT__ "PetscDrawBarSetFromOptions"
373 /*@
374     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar
375 
376     Collective over PetscDrawBar
377 
378     Options Database:
379 .  -bar_sort - sort the entries before drawing the bar graph
380 
381     Level: intermediate
382 
383 
384 .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate()
385 @*/
386 PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
387 {
388   PetscErrorCode ierr;
389   PetscBool      set;
390   PetscReal      tol = bar->sorttolerance;
391 
392   PetscFunctionBegin;
393   ierr = PetscOptionsHasName(NULL,"-bar_sort",&set);CHKERRQ(ierr);
394   if (set) {
395     ierr = PetscOptionsGetReal(NULL,"-bar_sort",&tol,NULL);CHKERRQ(ierr);
396     ierr = PetscDrawBarSort(bar,PETSC_TRUE,tol);CHKERRQ(ierr);
397   }
398   PetscFunctionReturn(0);
399 }
400 
401