Actual source code: bars.c

petsc-3.6.4 2016-04-12
Report Typos and Errors
  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: }