Actual source code: bars.c

petsc-3.7.5 2017-01-01
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;


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

 61:   PetscObjectReference((PetscObject)draw);
 62:   h->win = draw;

 64:   h->view        = NULL;
 65:   h->destroy     = NULL;
 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:   PetscDrawAxisCreate(draw,&h->axis);
 72:   h->axis->xticks = NULL;

 74:   *bar = h;
 75:   return(0);
 76: }

 80: /*@C
 81:    PetscDrawBarSetData

 83:    Logically Collective on PetscDrawBar

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

 91:    Level: intermediate


 94: @*/
 95: PetscErrorCode  PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
 96: {


102:   if (bar->numBins != bins) {
103:     PetscFree(bar->values);
104:     PetscMalloc1(bins, &bar->values);
105:     bar->numBins = bins;
106:   }
107:   PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));
108:   bar->numBins = bins;
109:   if (labels) {
110:     PetscStrArrayallocpy(labels,&bar->labels);
111:   }
112:   return(0);
113: }

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

120:   Collective over PetscDrawBar

122:   Input Parameter:
123: . bar - The bar graph context

125:   Level: intermediate

127: .seealso:  PetscDrawBarCreate()
128: @*/
129: PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
130: {

134:   if (!*bar) return(0);
136:   if (--((PetscObject)(*bar))->refct > 0) return(0);

138:   PetscFree((*bar)->values);
139:   PetscStrArrayDestroy(&(*bar)->labels);
140:   PetscDrawAxisDestroy(&(*bar)->axis);
141:   PetscDrawDestroy(&(*bar)->win);
142:   PetscHeaderDestroy(bar);
143:   return(0);
144: }

148: /*@
149:   PetscDrawBarDraw - Redraws a bar graph.

151:   Collective on PetscDrawBar

153:   Input Parameter:
154: . bar - The bar graph context

156:   Level: intermediate

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

171:   PetscDrawIsNull(bar->win,&isnull);
172:   if (isnull) return(0);
173:   MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);

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

177:   color = bar->color;
178:   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
179:   else bcolor = color;

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

200:   if (bar->sort) {
201:     PetscMalloc1(numValues,&perm);
202:     for (i=0; i<numValues;i++) perm[i] = i;
203:     PetscSortRealWithPermutation(numValues,values,perm);
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:   }

214:   draw = bar->win;
215:   PetscDrawCheckResizedWindow(draw);
216:   PetscDrawClear(draw);

218:   PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
219:   PetscDrawAxisDraw(bar->axis);

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

243:   PetscDrawFlush(draw);
244:   PetscDrawPause(draw);
245:   return(0);
246: }

250: /*@
251:   PetscDrawBarSave - Saves a drawn image

253:   Collective on PetscDrawBar

255:   Input Parameters:
256: . bar - The bar graph context

258:   Level: intermediate

260:   Concepts: bar graph^saving

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

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

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

279:   Logically Collective on PetscDrawBar

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

286:   Level: intermediate

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

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

302:   Logically Collective on PetscDrawBar

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

309:   Level: intermediate

311:   Concepts: bar graph^setting axis
312: @*/
313: PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
314: {
317:   bar->sort          = sort;
318:   bar->sorttolerance = tolerance;
319:   return(0);
320: }

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

329:   Logically Collective on PetscDrawBar

331:   Input Parameters:
332: + bar - The bar graph context
333: - y_min,y_max - The limits

335:   Level: intermediate

337:   Concepts: bar graph^setting axis
338: @*/
339: PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
340: {
343:   bar->ymin = y_min;
344:   bar->ymax = y_max;
345:   return(0);
346: }

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

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

358:   Input Parameter:
359: . bar - The bar graph context

361:   Output Parameter:
362: . axis - The axis context

364:   Level: intermediate

366: @*/
367: PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
368: {
372:   *axis = bar->axis;
373:   return(0);
374: }

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

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

383:   Input Parameter:
384: . bar - The bar graph context

386:   Output Parameter:
387: . draw  - The draw context

389:   Level: intermediate

391: @*/
392: PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
393: {
397:   *draw = bar->win;
398:   return(0);
399: }

403: /*@
404:     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar

406:     Collective over PetscDrawBar

408:     Options Database:
409: .  -bar_sort - sort the entries before drawing the bar graph

411:     Level: intermediate


414: .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate()
415: @*/
416: PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
417: {
419:   PetscBool      set;


424:   PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
425:   if (set) {
426:     PetscReal tol = bar->sorttolerance;
427:     PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
428:     PetscDrawBarSort(bar,PETSC_TRUE,tol);
429:   }
430:   return(0);
431: }