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