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 40 PetscFunctionBegin; 41 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 42 PetscValidPointer(bar,2); 43 44 CHKERRQ(PetscHeaderCreate(h,PETSC_DRAWBAR_CLASSID,"DrawBar","Bar Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawBarDestroy,NULL)); 45 CHKERRQ(PetscLogObjectParent((PetscObject)draw,(PetscObject)h)); 46 47 CHKERRQ(PetscObjectReference((PetscObject)draw)); 48 h->win = draw; 49 50 h->view = NULL; 51 h->destroy = NULL; 52 h->color = PETSC_DRAW_GREEN; 53 h->ymin = 0.; /* if user has not set these then they are determined from the data */ 54 h->ymax = 0.; 55 h->numBins = 0; 56 57 CHKERRQ(PetscDrawAxisCreate(draw,&h->axis)); 58 h->axis->xticks = NULL; 59 60 *bar = h; 61 PetscFunctionReturn(0); 62 } 63 64 /*@C 65 PetscDrawBarSetData 66 67 Logically Collective on PetscDrawBar 68 69 Input Parameters: 70 + bar - The bar graph context. 71 . bins - number of items 72 . values - values of each item 73 - labels - optional label for each bar, NULL terminated array of strings 74 75 Level: intermediate 76 77 Notes: 78 Call PetscDrawBarDraw() after this call to display the new plot 79 80 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw() 81 82 @*/ 83 PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar,PetscInt bins,const PetscReal data[],const char *const *labels) 84 { 85 PetscFunctionBegin; 86 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 87 88 if (bar->numBins != bins) { 89 CHKERRQ(PetscFree(bar->values)); 90 CHKERRQ(PetscMalloc1(bins, &bar->values)); 91 bar->numBins = bins; 92 } 93 CHKERRQ(PetscArraycpy(bar->values,data,bins)); 94 bar->numBins = bins; 95 if (labels) { 96 CHKERRQ(PetscStrArrayallocpy(labels,&bar->labels)); 97 } 98 PetscFunctionReturn(0); 99 } 100 101 /*@C 102 PetscDrawBarDestroy - Frees all space taken up by bar graph data structure. 103 104 Collective over PetscDrawBar 105 106 Input Parameter: 107 . bar - The bar graph context 108 109 Level: intermediate 110 111 .seealso: PetscDrawBarCreate() 112 @*/ 113 PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar) 114 { 115 PetscFunctionBegin; 116 if (!*bar) PetscFunctionReturn(0); 117 PetscValidHeaderSpecific(*bar,PETSC_DRAWBAR_CLASSID,1); 118 if (--((PetscObject)(*bar))->refct > 0) PetscFunctionReturn(0); 119 120 CHKERRQ(PetscFree((*bar)->values)); 121 CHKERRQ(PetscStrArrayDestroy(&(*bar)->labels)); 122 CHKERRQ(PetscDrawAxisDestroy(&(*bar)->axis)); 123 CHKERRQ(PetscDrawDestroy(&(*bar)->win)); 124 CHKERRQ(PetscHeaderDestroy(bar)); 125 PetscFunctionReturn(0); 126 } 127 128 /*@ 129 PetscDrawBarDraw - Redraws a bar graph. 130 131 Collective on PetscDrawBar 132 133 Input Parameter: 134 . bar - The bar graph context 135 136 Level: intermediate 137 138 .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData() 139 140 @*/ 141 PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar) 142 { 143 PetscDraw draw; 144 PetscBool isnull; 145 PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight; 146 PetscInt numValues,i,bcolor,color,idx,*perm,nplot; 147 PetscMPIInt rank; 148 char **labels; 149 PetscErrorCode ierr; 150 151 PetscFunctionBegin; 152 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 153 CHKERRQ(PetscDrawIsNull(bar->win,&isnull)); 154 if (isnull) PetscFunctionReturn(0); 155 CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank)); 156 157 if (bar->numBins < 1) PetscFunctionReturn(0); 158 159 color = bar->color; 160 if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1; 161 else bcolor = color; 162 163 numValues = bar->numBins; 164 values = bar->values; 165 if (bar->ymin == bar->ymax) { 166 /* user has not set bounds on bars so set them based on the data */ 167 ymin = PETSC_MAX_REAL; 168 ymax = PETSC_MIN_REAL; 169 for (i=0; i<numValues; i++) { 170 ymin = PetscMin(ymin,values[i]); 171 ymax = PetscMax(ymax,values[i]); 172 } 173 } else { 174 ymin = bar->ymin; 175 ymax = bar->ymax; 176 } 177 nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */ 178 xmin = 0.0; 179 xmax = nplot; 180 labels = bar->labels; 181 182 if (bar->sort) { 183 CHKERRQ(PetscMalloc1(numValues,&perm)); 184 for (i=0; i<numValues;i++) perm[i] = i; 185 CHKERRQ(PetscSortRealWithPermutation(numValues,values,perm)); 186 if (bar->sorttolerance) { 187 for (i=0; i<numValues;i++) { 188 if (values[perm[numValues - i - 1]] < bar->sorttolerance) { 189 nplot = i; 190 break; 191 } 192 } 193 } 194 } 195 196 draw = bar->win; 197 CHKERRQ(PetscDrawCheckResizedWindow(draw)); 198 CHKERRQ(PetscDrawClear(draw)); 199 200 CHKERRQ(PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax)); 201 CHKERRQ(PetscDrawAxisDraw(bar->axis)); 202 203 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 204 if (rank == 0) { /* Draw bins */ 205 for (i=0; i<nplot; i++) { 206 idx = (bar->sort ? perm[numValues - i - 1] : i); 207 binLeft = xmin + i; 208 binRight = xmin + i + 1; 209 CHKERRQ(PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor)); 210 CHKERRQ(PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK)); 211 CHKERRQ(PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK)); 212 CHKERRQ(PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK)); 213 if (labels) { 214 PetscReal h; 215 CHKERRQ(PetscDrawStringGetSize(draw,NULL,&h)); 216 CHKERRQ(PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.5*h,bcolor,labels[idx])); 217 } 218 if (color == PETSC_DRAW_ROTATE) bcolor++; 219 if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1; 220 } 221 } 222 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 223 if (bar->sort) CHKERRQ(PetscFree(perm)); 224 225 CHKERRQ(PetscDrawFlush(draw)); 226 CHKERRQ(PetscDrawPause(draw)); 227 PetscFunctionReturn(0); 228 } 229 230 /*@ 231 PetscDrawBarSave - Saves a drawn image 232 233 Collective on PetscDrawBar 234 235 Input Parameters: 236 . bar - The bar graph context 237 238 Level: intermediate 239 240 .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave(), PetscDrawBarSetData() 241 @*/ 242 PetscErrorCode PetscDrawBarSave(PetscDrawBar bar) 243 { 244 PetscFunctionBegin; 245 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 246 CHKERRQ(PetscDrawSave(bar->win)); 247 PetscFunctionReturn(0); 248 } 249 250 /*@ 251 PetscDrawBarSetColor - Sets the color the bars will be drawn with. 252 253 Logically Collective on PetscDrawBar 254 255 Input Parameters: 256 + bar - The bar graph context 257 - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a 258 different color 259 260 Level: intermediate 261 262 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarDraw(), PetscDrawBarGetAxis() 263 264 @*/ 265 PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color) 266 { 267 PetscFunctionBegin; 268 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 269 bar->color = color; 270 PetscFunctionReturn(0); 271 } 272 273 /*@ 274 PetscDrawBarSort - Sorts the values before drawing the bar chart 275 276 Logically Collective on PetscDrawBar 277 278 Input Parameters: 279 + bar - The bar graph context 280 . sort - PETSC_TRUE to sort the values 281 - tolerance - discard values less than tolerance 282 283 Level: intermediate 284 285 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarSetData(), PetscDrawBarSetColor(), PetscDrawBarDraw(), PetscDrawBarGetAxis() 286 @*/ 287 PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance) 288 { 289 PetscFunctionBegin; 290 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 291 bar->sort = sort; 292 bar->sorttolerance = tolerance; 293 PetscFunctionReturn(0); 294 } 295 296 /*@ 297 PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more 298 points are added after this call, the limits will be adjusted to 299 include those additional points. 300 301 Logically Collective on PetscDrawBar 302 303 Input Parameters: 304 + bar - The bar graph context 305 - y_min,y_max - The limits 306 307 Level: intermediate 308 309 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarGetAxis(), PetscDrawBarSetData(), PetscDrawBarDraw() 310 @*/ 311 PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max) 312 { 313 PetscFunctionBegin; 314 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 315 bar->ymin = y_min; 316 bar->ymax = y_max; 317 PetscFunctionReturn(0); 318 } 319 320 /*@C 321 PetscDrawBarGetAxis - Gets the axis context associated with a bar graph. 322 This is useful if one wants to change some axis property, such as 323 labels, color, etc. The axis context should not be destroyed by the 324 application code. 325 326 Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel 327 328 Input Parameter: 329 . bar - The bar graph context 330 331 Output Parameter: 332 . axis - The axis context 333 334 Level: intermediate 335 336 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawAxis, PetscDrawAxisCreate() 337 @*/ 338 PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar,PetscDrawAxis *axis) 339 { 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 342 PetscValidPointer(axis,2); 343 *axis = bar->axis; 344 PetscFunctionReturn(0); 345 } 346 347 /*@C 348 PetscDrawBarGetDraw - Gets the draw context associated with a bar graph. 349 350 Not Collective, PetscDraw is parallel if PetscDrawBar is parallel 351 352 Input Parameter: 353 . bar - The bar graph context 354 355 Output Parameter: 356 . draw - The draw context 357 358 Level: intermediate 359 360 .seealso: PetscDrawBarCreate(), PetscDrawBar, PetscDrawBarDraw(), PetscDraw 361 @*/ 362 PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar,PetscDraw *draw) 363 { 364 PetscFunctionBegin; 365 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 366 PetscValidPointer(draw,2); 367 *draw = bar->win; 368 PetscFunctionReturn(0); 369 } 370 371 /*@ 372 PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar 373 374 Collective over PetscDrawBar 375 376 Options Database: 377 . -bar_sort - sort the entries before drawing the bar graph 378 379 Level: intermediate 380 381 .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate(), PetscDrawBarSort() 382 @*/ 383 PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar) 384 { 385 PetscBool set; 386 387 PetscFunctionBegin; 388 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 389 390 CHKERRQ(PetscOptionsHasName(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&set)); 391 if (set) { 392 PetscReal tol = bar->sorttolerance; 393 CHKERRQ(PetscOptionsGetReal(((PetscObject)bar)->options,((PetscObject)bar)->prefix,"-bar_sort",&tol,NULL)); 394 CHKERRQ(PetscDrawBarSort(bar,PETSC_TRUE,tol)); 395 } 396 PetscFunctionReturn(0); 397 } 398