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;


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

 46:   PetscObjectReference((PetscObject)draw);
 47:   h->win = draw;

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

 56:   PetscDrawAxisCreate(draw,&h->axis);
 57:   h->axis->xticks = NULL;

 59:   *bar = h;
 60:   return 0;
 61: }

 63: /*@C
 64:    PetscDrawBarSetData

 66:    Logically Collective on PetscDrawBar

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

 74:    Level: intermediate

 76:    Notes:
 77:     Call PetscDrawBarDraw() after this call to display the new plot

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

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

 86:   if (bar->numBins != bins) {
 87:     PetscFree(bar->values);
 88:     PetscMalloc1(bins, &bar->values);
 89:     bar->numBins = bins;
 90:   }
 91:   PetscArraycpy(bar->values,data,bins);
 92:   bar->numBins = bins;
 93:   if (labels) {
 94:     PetscStrArrayallocpy(labels,&bar->labels);
 95:   }
 96:   return 0;
 97: }

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

102:   Collective over PetscDrawBar

104:   Input Parameter:
105: . bar - The bar graph context

107:   Level: intermediate

109: .seealso:  PetscDrawBarCreate()
110: @*/
111: PetscErrorCode  PetscDrawBarDestroy(PetscDrawBar *bar)
112: {
113:   if (!*bar) return 0;
115:   if (--((PetscObject)(*bar))->refct > 0) return 0;

117:   PetscFree((*bar)->values);
118:   PetscStrArrayDestroy(&(*bar)->labels);
119:   PetscDrawAxisDestroy(&(*bar)->axis);
120:   PetscDrawDestroy(&(*bar)->win);
121:   PetscHeaderDestroy(bar);
122:   return 0;
123: }

125: /*@
126:   PetscDrawBarDraw - Redraws a bar graph.

128:   Collective on PetscDrawBar

130:   Input Parameter:
131: . bar - The bar graph context

133:   Level: intermediate

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

137: @*/
138: PetscErrorCode  PetscDrawBarDraw(PetscDrawBar bar)
139: {
140:   PetscDraw      draw;
141:   PetscBool      isnull;
142:   PetscReal      xmin,xmax,ymin,ymax,*values,binLeft,binRight;
143:   PetscInt       numValues,i,bcolor,color,idx,*perm,nplot;
144:   PetscMPIInt    rank;
145:   char           **labels;

149:   PetscDrawIsNull(bar->win,&isnull);
150:   if (isnull) return 0;
151:   MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);

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

155:   color = bar->color;
156:   if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1;
157:   else bcolor = color;

159:   numValues = bar->numBins;
160:   values    = bar->values;
161:   if (bar->ymin == bar->ymax) {
162:     /* user has not set bounds on bars so set them based on the data */
163:     ymin = PETSC_MAX_REAL;
164:     ymax = PETSC_MIN_REAL;
165:     for (i=0; i<numValues; i++) {
166:       ymin = PetscMin(ymin,values[i]);
167:       ymax = PetscMax(ymax,values[i]);
168:     }
169:   } else {
170:     ymin = bar->ymin;
171:     ymax = bar->ymax;
172:   }
173:   nplot  = numValues;  /* number of points to actually plot; if some are lower than requested tolerance */
174:   xmin   = 0.0;
175:   xmax   = nplot;
176:   labels = bar->labels;

178:   if (bar->sort) {
179:     PetscMalloc1(numValues,&perm);
180:     for (i=0; i<numValues;i++) perm[i] = i;
181:     PetscSortRealWithPermutation(numValues,values,perm);
182:     if (bar->sorttolerance) {
183:       for (i=0; i<numValues;i++) {
184:         if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
185:           nplot = i;
186:           break;
187:         }
188:       }
189:     }
190:   }

192:   draw = bar->win;
193:   PetscDrawCheckResizedWindow(draw);
194:   PetscDrawClear(draw);

196:   PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
197:   PetscDrawAxisDraw(bar->axis);

199:   PetscDrawCollectiveBegin(draw);
200:   if (rank == 0) { /* Draw bins */
201:     for (i=0; i<nplot; i++) {
202:       idx = (bar->sort ? perm[numValues - i - 1] : i);
203:       binLeft  = xmin + i;
204:       binRight = xmin + i + 1;
205:       PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
206:       PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
207:       PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
208:       PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
209:       if (labels) {
210:         PetscReal h;
211:         PetscDrawStringGetSize(draw,NULL,&h);
212:         PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);
213:       }
214:       if (color == PETSC_DRAW_ROTATE) bcolor++;
215:       if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1;
216:     }
217:   }
218:   PetscDrawCollectiveEnd(draw);
219:   if (bar->sort) PetscFree(perm);

221:   PetscDrawFlush(draw);
222:   PetscDrawPause(draw);
223:   return 0;
224: }

226: /*@
227:   PetscDrawBarSave - Saves a drawn image

229:   Collective on PetscDrawBar

231:   Input Parameters:
232: . bar - The bar graph context

234:   Level: intermediate

236: .seealso:  PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData()
237: @*/
238: PetscErrorCode  PetscDrawBarSave(PetscDrawBar bar)
239: {
241:   PetscDrawSave(bar->win);
242:   return 0;
243: }

245: /*@
246:   PetscDrawBarSetColor - Sets the color the bars will be drawn with.

248:   Logically Collective on PetscDrawBar

250:   Input Parameters:
251: + bar - The bar graph context
252: - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a
253:           different color

255:   Level: intermediate

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

259: @*/
260: PetscErrorCode  PetscDrawBarSetColor(PetscDrawBar bar, int color)
261: {
263:   bar->color = color;
264:   return 0;
265: }

267: /*@
268:   PetscDrawBarSort - Sorts the values before drawing the bar chart

270:   Logically Collective on PetscDrawBar

272:   Input Parameters:
273: + bar - The bar graph context
274: . sort - PETSC_TRUE to sort the values
275: - tolerance - discard values less than tolerance

277:   Level: intermediate

279: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis()
280: @*/
281: PetscErrorCode  PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance)
282: {
284:   bar->sort          = sort;
285:   bar->sorttolerance = tolerance;
286:   return 0;
287: }

289: /*@
290:   PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more
291:   points are added after this call, the limits will be adjusted to
292:   include those additional points.

294:   Logically Collective on PetscDrawBar

296:   Input Parameters:
297: + bar - The bar graph context
298: - y_min,y_max - The limits

300:   Level: intermediate

302: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw()
303: @*/
304: PetscErrorCode  PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max)
305: {
307:   bar->ymin = y_min;
308:   bar->ymax = y_max;
309:   return 0;
310: }

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

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

320:   Input Parameter:
321: . bar - The bar graph context

323:   Output Parameter:
324: . axis - The axis context

326:   Level: intermediate

328: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate()
329: @*/
330: PetscErrorCode  PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis)
331: {
334:   *axis = bar->axis;
335:   return 0;
336: }

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

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

343:   Input Parameter:
344: . bar - The bar graph context

346:   Output Parameter:
347: . draw  - The draw context

349:   Level: intermediate

351: .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw
352: @*/
353: PetscErrorCode  PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw)
354: {
357:   *draw = bar->win;
358:   return 0;
359: }

361: /*@
362:     PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar

364:     Collective over PetscDrawBar

366:     Options Database:
367: .  -bar_sort - sort the entries before drawing the bar graph

369:     Level: intermediate

371: .seealso:  PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort()
372: @*/
373: PetscErrorCode  PetscDrawBarSetFromOptions(PetscDrawBar bar)
374: {
375:   PetscBool      set;


379:   PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);
380:   if (set) {
381:     PetscReal tol = bar->sorttolerance;
382:     PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);
383:     PetscDrawBarSort(bar,PETSC_TRUE,tol);
384:   }
385:   return 0;
386: }