Actual source code: bars.c


  2: /*
  3:   Contains the data structure for plotting a bargraph in a window with an axis.
  4: */
  5: #include <petscdraw.h>
  6: #include <petsc/private/petscimpl.h>
  7: #include <petscviewer.h>
  8: #include <../src/sys/classes/draw/utils/axisimpl.h>

 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

 29: /*@C
 30:    PetscDrawBarCreate - Creates a bar graph data structure.

 32:    Collective over PetscDraw

 34:    Input Parameters:
 35: .  draw  - The window where the graph will be made

 37:    Output Parameters:
 38: .  bar - The bar graph context

 40:    Notes:
 41:     Call PetscDrawBarSetData() to provide the bins to be plotted and then PetscDrawBarDraw() to display the new plot

 43:   The difference between a bar chart, PetscDrawBar, and a histogram, PetscDrawHG, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP

 45:    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
 46:    zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawBarDraw() to display the updated graph.

 48:    Level: intermediate

 50: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarDestroy(), PetscDrawBarSetData(),
 51:           PetscDrawBar, PetscDrawBarDraw(), PetscDrawBarSave(), PetscDrawBarSetColor(), PetscDrawBarSort(), PetscDrawBarSetLimits(), PetscDrawBarGetAxis(), PetscDrawAxis,
 52:           PetscDrawBarGetDraw(), PetscDrawBarSetFromOptions()
 53: @*/
 54: PetscErrorCode  PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
 55: {
 56:   PetscDrawBar   h;


 63:   PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);
 64:   PetscLogObjectParent((PetscObject)draw,(PetscObject)h);

 66:   PetscObjectReference((PetscObject)draw);
 67:   h->win = draw;

 69:   h->view        = NULL;
 70:   h->destroy     = NULL;
 71:   h->color       = PETSC_DRAW_GREEN;
 72:   h->ymin        = 0.;  /* if user has not set these then they are determined from the data */
 73:   h->ymax        = 0.;
 74:   h->numBins     = 0;

 76:   PetscDrawAxisCreate(draw,&h->axis);
 77:   h->axis->xticks = NULL;

 79:   *bar = h;
 80:   return(0);
 81: }

 83: /*@C
 84:    PetscDrawBarSetData

 86:    Logically Collective on PetscDrawBar

 88:    Input Parameter:
 89: +  bar - The bar graph context.
 90: .  bins  - number of items
 91: .  values - values of each item
 92: -  labels - optional label for each bar, NULL terminated array of strings

 94:    Level: intermediate

 96:    Notes:
 97:     Call PetscDrawBarDraw() after this call to display the new plot

 99: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw()

101: @*/
102: PetscErrorCode  PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
103: {


109:   if (bar->numBins != bins) {
110:     PetscFree(bar->values);
111:     PetscMalloc1(bins, &bar->values);
112:     bar->numBins = bins;
113:   }
114:   PetscArraycpy(bar->values,data,bins);
115:   bar->numBins = bins;
116:   if (labels) {
117:     PetscStrArrayallocpy(labels,&bar->labels);
118:   }
119:   return(0);
120: }

122: /*@C
123:   PetscDrawBarDestroy - Frees all space taken up by bar graph data structure.

125:   Collective over PetscDrawBar

127:   Input Parameter:
128: . bar - The bar graph context

130:   Level: intermediate

132: .seealso:  PetscDrawBarCreate()
133: @*/
134: PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
135: {

139:   if (!*bar) return(0);
141:   if (--((PetscObject)(*bar))->refct > 0) return(0);

143:   PetscFree((*bar)->values);
144:   PetscStrArrayDestroy(&(*bar)->labels);
145:   PetscDrawAxisDestroy(&(*bar)->axis);
146:   PetscDrawDestroy(&(*bar)->win);
147:   PetscHeaderDestroy(bar);
148:   return(0);
149: }

151: /*@
152:   PetscDrawBarDraw - Redraws a bar graph.

154:   Collective on PetscDrawBar

156:   Input Parameter:
157: . bar - The bar graph context

159:   Level: intermediate

161: .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData()

163: @*/
164: PetscErrorCode  PetscDrawBarDraw(PetscDrawBar bar)
165: {
166:   PetscDraw      draw;
167:   PetscBool      isnull;
168:   PetscReal      xmin,xmax,ymin,ymax,*values,binLeft,binRight;
169:   PetscInt       numValues,i,bcolor,color,idx,*perm,nplot;
170:   PetscMPIInt    rank;
172:   char           **labels;

176:   PetscDrawIsNull(bar->win,&isnull);
177:   if (isnull) return(0);
178:   MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);

180:   if (bar->numBins < 1) return(0);

182:   color = bar->color;
183:   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
184:   else bcolor = color;

186:   numValues = bar->numBins;
187:   values    = bar->values;
188:   if (bar->ymin == bar->ymax) {
189:     /* user has not set bounds on bars so set them based on the data */
190:     ymin = PETSC_MAX_REAL;
191:     ymax = PETSC_MIN_REAL;
192:     for (i=0; i<numValues; i++) {
193:       ymin = PetscMin(ymin,values[i]);
194:       ymax = PetscMax(ymax,values[i]);
195:     }
196:   } else {
197:     ymin = bar->ymin;
198:     ymax = bar->ymax;
199:   }
200:   nplot  = numValues;  /* number of points to actually plot; if some are lower than requested tolerance */
201:   xmin   = 0.0;
202:   xmax   = nplot;
203:   labels = bar->labels;

205:   if (bar->sort) {
206:     PetscMalloc1(numValues,&perm);
207:     for (i=0; i<numValues;i++) perm[i] = i;
208:     PetscSortRealWithPermutation(numValues,values,perm);
209:     if (bar->sorttolerance) {
210:       for (i=0; i<numValues;i++) {
211:         if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
212:           nplot = i;
213:           break;
214:         }
215:       }
216:     }
217:   }

219:   draw = bar->win;
220:   PetscDrawCheckResizedWindow(draw);
221:   PetscDrawClear(draw);

223:   PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
224:   PetscDrawAxisDraw(bar->axis);

226:   PetscDrawCollectiveBegin(draw);
227:   if (!rank) { /* Draw bins */
228:     for (i=0; i<nplot; i++) {
229:       idx = (bar->sort ? perm[numValues - i - 1] : i);
230:       binLeft  = xmin + i;
231:       binRight = xmin + i + 1;
232:       PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
233:       PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
234:       PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
235:       PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
236:       if (labels) {
237:         PetscReal h;
238:         PetscDrawStringGetSize(draw,NULL,&h);
239:         PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
240:       }
241:       if (color == PETSC_DRAW_ROTATE) bcolor++;
242:       if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
243:     }
244:   }
245:   PetscDrawCollectiveEnd(draw);
246:   if (bar->sort) {PetscFree(perm);}

248:   PetscDrawFlush(draw);
249:   PetscDrawPause(draw);
250:   return(0);
251: }

253: /*@
254:   PetscDrawBarSave - Saves a drawn image

256:   Collective on PetscDrawBar

258:   Input Parameters:
259: . bar - The bar graph context

261:   Level: intermediate

263: .seealso:  PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
264: @*/
265: PetscErrorCode  PetscDrawBarSave(PetscDrawBar bar)
266: {

271:   PetscDrawSave(bar->win);
272:   return(0);
273: }

275: /*@
276:   PetscDrawBarSetColor - Sets the color the bars will be drawn with.

278:   Logically Collective on PetscDrawBar

280:   Input Parameters:
281: + bar - The bar graph context
282: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
283:           different color

285:   Level: intermediate

287: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis()

289: @*/
290: PetscErrorCode  PetscDrawBarSetColor(PetscDrawBar bar, int color)
291: {
294:   bar->color = color;
295:   return(0);
296: }

298: /*@
299:   PetscDrawBarSort - Sorts the values before drawing the bar chart

301:   Logically Collective on PetscDrawBar

303:   Input Parameters:
304: + bar - The bar graph context
305: . sort - PETSC_TRUE to sort the values
306: - tolerance - discard values less than tolerance

308:   Level: intermediate

310: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
311: @*/
312: PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
313: {
316:   bar->sort          = sort;
317:   bar->sorttolerance = tolerance;
318:   return(0);
319: }

321: /*@
322:   PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
323:   points are added after this call, the limits will be adjusted to
324:   include those additional points.

326:   Logically Collective on PetscDrawBar

328:   Input Parameters:
329: + bar - The bar graph context
330: - y_min,y_max - The limits

332:   Level: intermediate

334: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
335: @*/
336: PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
337: {
340:   bar->ymin = y_min;
341:   bar->ymax = y_max;
342:   return(0);
343: }

345: /*@C
346:   PetscDrawBarGetAxis - Gets the axis context associated with a bar graph.
347:   This is useful if one wants to change some axis property, such as
348:   labels, color, etc. The axis context should not be destroyed by the
349:   application code.

351:   Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel

353:   Input Parameter:
354: . bar - The bar graph context

356:   Output Parameter:
357: . axis - The axis context

359:   Level: intermediate

361: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
362: @*/
363: PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
364: {
368:   *axis = bar->axis;
369:   return(0);
370: }

372: /*@C
373:   PetscDrawBarGetDraw - Gets the draw context associated with a bar graph.

375:   Not Collective, PetscDraw is parallel if PetscDrawBar is parallel

377:   Input Parameter:
378: . bar - The bar graph context

380:   Output Parameter:
381: . draw  - The draw context

383:   Level: intermediate

385: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
386: @*/
387: PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
388: {
392:   *draw = bar->win;
393:   return(0);
394: }

396: /*@
397:     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar

399:     Collective over PetscDrawBar

401:     Options Database:
402: .  -bar_sort - sort the entries before drawing the bar graph

404:     Level: intermediate


407: .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
408: @*/
409: PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
410: {
412:   PetscBool      set;


417:   PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
418:   if (set) {
419:     PetscReal tol = bar->sorttolerance;
420:     PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
421:     PetscDrawBarSort(bar,PETSC_TRUE,tol);
422:   }
423:   return(0);
424: }