1 2 /* 3 Contains the data structure for plotting a bargraph in a window with an axis. 4 */ 5 6 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/ 7 #include <petscviewer.h> /*I "petscviewer.h" I*/ 8 9 PetscClassId PETSC_DRAWBAR_CLASSID = 0; 10 11 /*@C 12 PetscDrawBarCreate - Creates a bar graph data structure. 13 14 Collective over PetscDraw 15 16 Input Parameters: 17 . draw - The window where the graph will be made 18 19 Output Parameters: 20 . bar - The bar graph context 21 22 Notes: 23 Call PetscDrawBarSetData() to provide the bins to be plotted and then PetscDrawBarDraw() to display the new plot 24 25 The difference between a bar chart, PetscDrawBar, and a histogram, PetscDrawHG, is explained here https://stattrek.com/statistics/charts/histogram.aspx?Tutorial=AP 26 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. 29 30 Level: intermediate 31 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; 39 PetscErrorCode ierr; 40 41 PetscFunctionBegin; 42 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 43 PetscValidPointer(bar,2); 44 45 ierr = PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL);CHKERRQ(ierr); 46 ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)h);CHKERRQ(ierr); 47 48 ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr); 49 h->win = draw; 50 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; 57 58 ierr = PetscDrawAxisCreate(draw,&h->axis);CHKERRQ(ierr); 59 h->axis->xticks = NULL; 60 61 *bar = h; 62 PetscFunctionReturn(0); 63 } 64 65 /*@C 66 PetscDrawBarSetData 67 68 Logically Collective on PetscDrawBar 69 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 75 76 Level: intermediate 77 78 Notes: 79 Call PetscDrawBarDraw() after this call to display the new plot 80 81 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw() 82 83 @*/ 84 PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels) 85 { 86 PetscErrorCode ierr; 87 88 PetscFunctionBegin; 89 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 90 91 if (bar->numBins != bins) { 92 ierr = PetscFree(bar->values);CHKERRQ(ierr); 93 ierr = PetscMalloc1(bins, &bar->values);CHKERRQ(ierr); 94 bar->numBins = bins; 95 } 96 ierr = PetscArraycpy(bar->values,data,bins);CHKERRQ(ierr); 97 bar->numBins = bins; 98 if (labels) { 99 ierr = PetscStrArrayallocpy(labels,&bar->labels);CHKERRQ(ierr); 100 } 101 PetscFunctionReturn(0); 102 } 103 104 /*@C 105 PetscDrawBarDestroy - Frees all space taken up by bar graph data structure. 106 107 Collective over PetscDrawBar 108 109 Input Parameter: 110 . bar - The bar graph context 111 112 Level: intermediate 113 114 .seealso: PetscDrawBarCreate() 115 @*/ 116 PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar) 117 { 118 PetscErrorCode ierr; 119 120 PetscFunctionBegin; 121 if (!*bar) PetscFunctionReturn(0); 122 PetscValidHeaderSpecific(*bar,PETSC_DRAWBAR_CLASSID,1); 123 if (--((PetscObject)(*bar))->refct > 0) PetscFunctionReturn(0); 124 125 ierr = PetscFree((*bar)->values);CHKERRQ(ierr); 126 ierr = PetscStrArrayDestroy(&(*bar)->labels);CHKERRQ(ierr); 127 ierr = PetscDrawAxisDestroy(&(*bar)->axis);CHKERRQ(ierr); 128 ierr = PetscDrawDestroy(&(*bar)->win);CHKERRQ(ierr); 129 ierr = PetscHeaderDestroy(bar);CHKERRQ(ierr); 130 PetscFunctionReturn(0); 131 } 132 133 /*@ 134 PetscDrawBarDraw - Redraws a bar graph. 135 136 Collective on PetscDrawBar 137 138 Input Parameter: 139 . bar - The bar graph context 140 141 Level: intermediate 142 143 .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData() 144 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; 153 PetscErrorCode ierr; 154 char **labels; 155 156 PetscFunctionBegin; 157 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 158 ierr = PetscDrawIsNull(bar->win,&isnull);CHKERRQ(ierr); 159 if (isnull) PetscFunctionReturn(0); 160 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);CHKERRMPI(ierr); 161 162 if (bar->numBins < 1) PetscFunctionReturn(0); 163 164 color = bar->color; 165 if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1; 166 else bcolor = color; 167 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; 186 187 if (bar->sort) { 188 ierr = PetscMalloc1(numValues,&perm);CHKERRQ(ierr); 189 for (i=0; i<numValues;i++) perm[i] = i; 190 ierr = PetscSortRealWithPermutation(numValues,values,perm);CHKERRQ(ierr); 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 } 200 201 draw = bar->win; 202 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 203 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 204 205 ierr = PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 206 ierr = PetscDrawAxisDraw(bar->axis);CHKERRQ(ierr); 207 208 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 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 ierr = PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);CHKERRQ(ierr); 215 ierr = PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr); 216 ierr = PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr); 217 ierr = PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr); 218 if (labels) { 219 PetscReal h; 220 ierr = PetscDrawStringGetSize(draw,NULL,&h);CHKERRQ(ierr); 221 ierr = PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx]);CHKERRQ(ierr); 222 } 223 if (color == PETSC_DRAW_ROTATE) bcolor++; 224 if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1; 225 } 226 } 227 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 228 if (bar->sort) {ierr = PetscFree(perm);CHKERRQ(ierr);} 229 230 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 231 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 232 PetscFunctionReturn(0); 233 } 234 235 /*@ 236 PetscDrawBarSave - Saves a drawn image 237 238 Collective on PetscDrawBar 239 240 Input Parameters: 241 . bar - The bar graph context 242 243 Level: intermediate 244 245 .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData() 246 @*/ 247 PetscErrorCode PetscDrawBarSave(PetscDrawBar bar) 248 { 249 PetscErrorCode ierr; 250 251 PetscFunctionBegin; 252 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 253 ierr = PetscDrawSave(bar->win);CHKERRQ(ierr); 254 PetscFunctionReturn(0); 255 } 256 257 /*@ 258 PetscDrawBarSetColor - Sets the color the bars will be drawn with. 259 260 Logically Collective on PetscDrawBar 261 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 266 267 Level: intermediate 268 269 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis() 270 271 @*/ 272 PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color) 273 { 274 PetscFunctionBegin; 275 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 276 bar->color = color; 277 PetscFunctionReturn(0); 278 } 279 280 /*@ 281 PetscDrawBarSort - Sorts the values before drawing the bar chart 282 283 Logically Collective on PetscDrawBar 284 285 Input Parameters: 286 + bar - The bar graph context 287 . sort - PETSC_TRUE to sort the values 288 - tolerance - discard values less than tolerance 289 290 Level: intermediate 291 292 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis() 293 @*/ 294 PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance) 295 { 296 PetscFunctionBegin; 297 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 298 bar->sort = sort; 299 bar->sorttolerance = tolerance; 300 PetscFunctionReturn(0); 301 } 302 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. 307 308 Logically Collective on PetscDrawBar 309 310 Input Parameters: 311 + bar - The bar graph context 312 - y_min,y_max - The limits 313 314 Level: intermediate 315 316 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw() 317 @*/ 318 PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max) 319 { 320 PetscFunctionBegin; 321 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 322 bar->ymin = y_min; 323 bar->ymax = y_max; 324 PetscFunctionReturn(0); 325 } 326 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. 332 333 Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel 334 335 Input Parameter: 336 . bar - The bar graph context 337 338 Output Parameter: 339 . axis - The axis context 340 341 Level: intermediate 342 343 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate() 344 @*/ 345 PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis) 346 { 347 PetscFunctionBegin; 348 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 349 PetscValidPointer(axis,2); 350 *axis = bar->axis; 351 PetscFunctionReturn(0); 352 } 353 354 /*@C 355 PetscDrawBarGetDraw - Gets the draw context associated with a bar graph. 356 357 Not Collective, PetscDraw is parallel if PetscDrawBar is parallel 358 359 Input Parameter: 360 . bar - The bar graph context 361 362 Output Parameter: 363 . draw - The draw context 364 365 Level: intermediate 366 367 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw 368 @*/ 369 PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw) 370 { 371 PetscFunctionBegin; 372 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 373 PetscValidPointer(draw,2); 374 *draw = bar->win; 375 PetscFunctionReturn(0); 376 } 377 378 /*@ 379 PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar 380 381 Collective over PetscDrawBar 382 383 Options Database: 384 . -bar_sort - sort the entries before drawing the bar graph 385 386 Level: intermediate 387 388 .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort() 389 @*/ 390 PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar) 391 { 392 PetscErrorCode ierr; 393 PetscBool set; 394 395 PetscFunctionBegin; 396 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 397 398 ierr = PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set);CHKERRQ(ierr); 399 if (set) { 400 PetscReal tol = bar->sorttolerance; 401 ierr = PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL);CHKERRQ(ierr); 402 ierr = PetscDrawBarSort(bar,PETSC_TRUE,tol);CHKERRQ(ierr); 403 } 404 PetscFunctionReturn(0); 405 } 406