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