Actual source code: bars.c


  2: /*
  3:   Contains the data structure for plotting a bargraph in a window with an axis.
  4: */

  6: #include <petsc/private/drawimpl.h>
  7: #include <petscviewer.h>

  9: PetscClassId PETSC_DRAWBAR_CLASSID = 0;

 11: /*@C
 12:    PetscDrawBarCreate - Creates a bar graph data structure.

 14:    Collective over PetscDraw

 16:    Input Parameters:
 17: .  draw  - The window where the graph will be made

 19:    Output Parameters:
 20: .  bar - The bar graph context

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

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

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

 30:    Level: intermediate

 32: .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarDestroy(), PetscDrawBarSetData(),
 33:           PetscDrawBar, PetscDrawBarDraw(), PetscDrawBarSave(), PetscDrawBarSetColor(), PetscDrawBarSort(), PetscDrawBarSetLimits(), PetscDrawBarGetAxis(), PetscDrawAxis,
 34:           PetscDrawBarGetDraw(), PetscDrawBarSetFromOptions()
 35: @*/
 36: PetscErrorCode  PetscDrawBarCreate(PetscDraw draw,PetscDrawBar *bar)
 37: {
 38:   PetscDrawBar   h;


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

 48:   PetscObjectReference((PetscObject)draw);
 49:   h->win = draw;

 51:   h->view        = NULL;
 52:   h->destroy     = NULL;
 53:   h->color       = PETSC_DRAW_GREEN;
 54:   h->ymin        = 0.;  /* if user has not set these then they are determined from the data */
 55:   h->ymax        = 0.;
 56:   h->numBins     = 0;

 58:   PetscDrawAxisCreate(draw,&h->axis);
 59:   h->axis->xticks = NULL;

 61:   *bar = h;
 62:   return(0);
 63: }

 65: /*@C
 66:    PetscDrawBarSetData

 68:    Logically Collective on PetscDrawBar

 70:    Input Parameters:
 71: +  bar - The bar graph context.
 72: .  bins  - number of items
 73: .  values - values of each item
 74: -  labels - optional label for each bar, NULL terminated array of strings

 76:    Level: intermediate

 78:    Notes:
 79:     Call PetscDrawBarDraw() after this call to display the new plot

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

 83: @*/
 84: PetscErrorCode  PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels)
 85: {


 91:   if (bar->numBins != bins) {
 92:     PetscFree(bar->values);
 93:     PetscMalloc1(bins, &bar->values);
 94:     bar->numBins = bins;
 95:   }
 96:   PetscArraycpy(bar->values,data,bins);
 97:   bar->numBins = bins;
 98:   if (labels) {
 99:     PetscStrArrayallocpy(labels,&bar->labels);
100:   }
101:   return(0);
102: }

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

107:   Collective over PetscDrawBar

109:   Input Parameter:
110: . bar - The bar graph context

112:   Level: intermediate

114: .seealso:  PetscDrawBarCreate()
115: @*/
116: PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
117: {

121:   if (!*bar) return(0);
123:   if (--((PetscObject)(*bar))->refct > 0) return(0);

125:   PetscFree((*bar)->values);
126:   PetscStrArrayDestroy(&(*bar)->labels);
127:   PetscDrawAxisDestroy(&(*bar)->axis);
128:   PetscDrawDestroy(&(*bar)->win);
129:   PetscHeaderDestroy(bar);
130:   return(0);
131: }

133: /*@
134:   PetscDrawBarDraw - Redraws a bar graph.

136:   Collective on PetscDrawBar

138:   Input Parameter:
139: . bar - The bar graph context

141:   Level: intermediate

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

145: @*/
146: PetscErrorCode  PetscDrawBarDraw(PetscDrawBar bar)
147: {
148:   PetscDraw      draw;
149:   PetscBool      isnull;
150:   PetscReal      xmin,xmax,ymin,ymax,*values,binLeft,binRight;
151:   PetscInt       numValues,i,bcolor,color,idx,*perm,nplot;
152:   PetscMPIInt    rank;
154:   char           **labels;

158:   PetscDrawIsNull(bar->win,&isnull);
159:   if (isnull) return(0);
160:   MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);

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

164:   color = bar->color;
165:   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
166:   else bcolor = color;

168:   numValues = bar->numBins;
169:   values    = bar->values;
170:   if (bar->ymin == bar->ymax) {
171:     /* user has not set bounds on bars so set them based on the data */
172:     ymin = PETSC_MAX_REAL;
173:     ymax = PETSC_MIN_REAL;
174:     for (i=0; i<numValues; i++) {
175:       ymin = PetscMin(ymin,values[i]);
176:       ymax = PetscMax(ymax,values[i]);
177:     }
178:   } else {
179:     ymin = bar->ymin;
180:     ymax = bar->ymax;
181:   }
182:   nplot  = numValues;  /* number of points to actually plot; if some are lower than requested tolerance */
183:   xmin   = 0.0;
184:   xmax   = nplot;
185:   labels = bar->labels;

187:   if (bar->sort) {
188:     PetscMalloc1(numValues,&perm);
189:     for (i=0; i<numValues;i++) perm[i] = i;
190:     PetscSortRealWithPermutation(numValues,values,perm);
191:     if (bar->sorttolerance) {
192:       for (i=0; i<numValues;i++) {
193:         if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
194:           nplot = i;
195:           break;
196:         }
197:       }
198:     }
199:   }

201:   draw = bar->win;
202:   PetscDrawCheckResizedWindow(draw);
203:   PetscDrawClear(draw);

205:   PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
206:   PetscDrawAxisDraw(bar->axis);

208:   PetscDrawCollectiveBegin(draw);
209:   if (rank == 0) { /* Draw bins */
210:     for (i=0; i<nplot; i++) {
211:       idx = (bar->sort ? perm[numValues - i - 1] : i);
212:       binLeft  = xmin + i;
213:       binRight = xmin + i + 1;
214:       PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
215:       PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
216:       PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
217:       PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
218:       if (labels) {
219:         PetscReal h;
220:         PetscDrawStringGetSize(draw,NULL,&h);
221:         PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
222:       }
223:       if (color == PETSC_DRAW_ROTATE) bcolor++;
224:       if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
225:     }
226:   }
227:   PetscDrawCollectiveEnd(draw);
228:   if (bar->sort) {PetscFree(perm);}

230:   PetscDrawFlush(draw);
231:   PetscDrawPause(draw);
232:   return(0);
233: }

235: /*@
236:   PetscDrawBarSave - Saves a drawn image

238:   Collective on PetscDrawBar

240:   Input Parameters:
241: . bar - The bar graph context

243:   Level: intermediate

245: .seealso:  PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
246: @*/
247: PetscErrorCode  PetscDrawBarSave(PetscDrawBar bar)
248: {

253:   PetscDrawSave(bar->win);
254:   return(0);
255: }

257: /*@
258:   PetscDrawBarSetColor - Sets the color the bars will be drawn with.

260:   Logically Collective on PetscDrawBar

262:   Input Parameters:
263: + bar - The bar graph context
264: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
265:           different color

267:   Level: intermediate

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

271: @*/
272: PetscErrorCode  PetscDrawBarSetColor(PetscDrawBar bar, int color)
273: {
276:   bar->color = color;
277:   return(0);
278: }

280: /*@
281:   PetscDrawBarSort - Sorts the values before drawing the bar chart

283:   Logically Collective on PetscDrawBar

285:   Input Parameters:
286: + bar - The bar graph context
287: . sort - PETSC_TRUE to sort the values
288: - tolerance - discard values less than tolerance

290:   Level: intermediate

292: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
293: @*/
294: PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
295: {
298:   bar->sort          = sort;
299:   bar->sorttolerance = tolerance;
300:   return(0);
301: }

303: /*@
304:   PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
305:   points are added after this call, the limits will be adjusted to
306:   include those additional points.

308:   Logically Collective on PetscDrawBar

310:   Input Parameters:
311: + bar - The bar graph context
312: - y_min,y_max - The limits

314:   Level: intermediate

316: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
317: @*/
318: PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
319: {
322:   bar->ymin = y_min;
323:   bar->ymax = y_max;
324:   return(0);
325: }

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

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

335:   Input Parameter:
336: . bar - The bar graph context

338:   Output Parameter:
339: . axis - The axis context

341:   Level: intermediate

343: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
344: @*/
345: PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
346: {
350:   *axis = bar->axis;
351:   return(0);
352: }

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

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

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

362:   Output Parameter:
363: . draw  - The draw context

365:   Level: intermediate

367: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
368: @*/
369: PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
370: {
374:   *draw = bar->win;
375:   return(0);
376: }

378: /*@
379:     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar

381:     Collective over PetscDrawBar

383:     Options Database:
384: .  -bar_sort - sort the entries before drawing the bar graph

386:     Level: intermediate

388: .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
389: @*/
390: PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
391: {
393:   PetscBool      set;


398:   PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
399:   if (set) {
400:     PetscReal tol = bar->sorttolerance;
401:     PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
402:     PetscDrawBarSort(bar,PETSC_TRUE,tol);
403:   }
404:   return(0);
405: }