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 Level: intermediate 43 44 Concepts: bar graph^creating 45 46 .seealso: PetscDrawBarDestroy() 47 48 @*/ 49 PetscErrorCode PetscDrawBarCreate(PetscDraw draw, PetscDrawBar *bar) 50 { 51 PetscDrawBar h; 52 PetscBool isnull; 53 PetscErrorCode ierr; 54 55 PetscFunctionBegin; 56 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 57 PetscValidPointer(bar,2); 58 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 59 if (isnull) {*bar = NULL; PetscFunctionReturn(0);} 60 61 ierr = PetscHeaderCreate(h, PETSC_DRAWBAR_CLASSID, "PetscDrawBar", "Bar Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawBarDestroy, NULL);CHKERRQ(ierr); 62 ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)h);CHKERRQ(ierr); 63 64 ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr); 65 h->win = draw; 66 67 h->view = NULL; 68 h->destroy = NULL; 69 h->color = PETSC_DRAW_GREEN; 70 h->ymin = 0.; /* if user has not set these then they are determined from the data */ 71 h->ymax = 0.; 72 h->numBins = 0; 73 74 ierr = PetscDrawAxisCreate(draw,&h->axis);CHKERRQ(ierr); 75 if (h->axis) h->axis->xticks = NULL; 76 77 *bar = h; 78 PetscFunctionReturn(0); 79 } 80 81 #undef __FUNCT__ 82 #define __FUNCT__ "PetscDrawBarSetData" 83 /*@C 84 PetscDrawBarSetData 85 86 Logically Collective on PetscDrawBar 87 88 Input Parameter: 89 + bar - The bar graph context. 90 . bins - number of items 91 . values - values of each item 92 - labels - optional label for each bar, NULL terminated array of strings 93 94 Level: intermediate 95 96 97 @*/ 98 PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar, PetscInt bins,const PetscReal data[],const char *const *labels) 99 { 100 PetscErrorCode ierr; 101 102 PetscFunctionBegin; 103 if (!bar) PetscFunctionReturn(0); 104 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 105 106 if (bar->numBins != bins) { 107 ierr = PetscFree(bar->values);CHKERRQ(ierr); 108 ierr = PetscMalloc1(bins, &bar->values);CHKERRQ(ierr); 109 bar->numBins = bins; 110 } 111 ierr = PetscMemcpy(bar->values,data,bins*sizeof(PetscReal));CHKERRQ(ierr); 112 bar->numBins = bins; 113 if (labels) { 114 ierr = PetscStrArrayallocpy(labels,&bar->labels);CHKERRQ(ierr); 115 } 116 PetscFunctionReturn(0); 117 } 118 119 #undef __FUNCT__ 120 #define __FUNCT__ "PetscDrawBarDestroy" 121 /*@C 122 PetscDrawBarDestroy - Frees all space taken up by bar graph data structure. 123 124 Collective over PetscDrawBar 125 126 Input Parameter: 127 . bar - The bar graph context 128 129 Level: intermediate 130 131 .seealso: PetscDrawBarCreate() 132 @*/ 133 PetscErrorCode PetscDrawBarDestroy(PetscDrawBar *bar) 134 { 135 PetscErrorCode ierr; 136 137 PetscFunctionBegin; 138 if (!*bar) PetscFunctionReturn(0); 139 PetscValidHeaderSpecific(*bar,PETSC_DRAWBAR_CLASSID,1); 140 if (--((PetscObject)(*bar))->refct > 0) PetscFunctionReturn(0); 141 142 ierr = PetscFree((*bar)->values);CHKERRQ(ierr); 143 ierr = PetscStrArrayDestroy(&(*bar)->labels);CHKERRQ(ierr); 144 ierr = PetscDrawAxisDestroy(&(*bar)->axis);CHKERRQ(ierr); 145 ierr = PetscDrawDestroy(&(*bar)->win);CHKERRQ(ierr); 146 ierr = PetscHeaderDestroy(bar);CHKERRQ(ierr); 147 PetscFunctionReturn(0); 148 } 149 150 #undef __FUNCT__ 151 #define __FUNCT__ "PetscDrawBarDraw" 152 /*@ 153 PetscDrawBarDraw - Redraws a bar graph. 154 155 Collective on PetscDrawBar 156 157 Input Parameter: 158 . bar - The bar graph context 159 160 Level: intermediate 161 162 @*/ 163 PetscErrorCode PetscDrawBarDraw(PetscDrawBar bar) 164 { 165 PetscDraw draw; 166 PetscBool isnull; 167 PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight; 168 PetscInt numValues,i,bcolor,color,idx,*perm,nplot; 169 PetscMPIInt rank; 170 PetscErrorCode ierr; 171 char **labels; 172 173 PetscFunctionBegin; 174 if (!bar) PetscFunctionReturn(0); 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 = 2; 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.2*h,bcolor,labels[idx]);CHKERRQ(ierr); 240 } 241 if (color == PETSC_DRAW_ROTATE) bcolor++; 242 if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = 2; 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 #undef __FUNCT__ 254 #define __FUNCT__ "PetscDrawBarSave" 255 /*@ 256 PetscDrawBarSave - Saves a drawn image 257 258 Collective on PetscDrawBar 259 260 Input Parameters: 261 . bar - The bar graph context 262 263 Level: intermediate 264 265 Concepts: bar graph^saving 266 267 .seealso: PetscDrawBarCreate(), PetscDrawBarGetDraw(), PetscDrawSetSave(), PetscDrawSave() 268 @*/ 269 PetscErrorCode PetscDrawBarSave(PetscDrawBar bar) 270 { 271 PetscErrorCode ierr; 272 273 PetscFunctionBegin; 274 if (!bar) PetscFunctionReturn(0); 275 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 276 ierr = PetscDrawSave(bar->win);CHKERRQ(ierr); 277 PetscFunctionReturn(0); 278 } 279 280 #undef __FUNCT__ 281 #define __FUNCT__ "PetscDrawBarSetColor" 282 /*@ 283 PetscDrawBarSetColor - Sets the color the bars will be drawn with. 284 285 Logically Collective on PetscDrawBar 286 287 Input Parameters: 288 + bar - The bar graph context 289 - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a 290 different color 291 292 Level: intermediate 293 294 @*/ 295 PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color) 296 { 297 PetscFunctionBegin; 298 if (!bar) PetscFunctionReturn(0); 299 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 300 bar->color = color; 301 PetscFunctionReturn(0); 302 } 303 304 #undef __FUNCT__ 305 #define __FUNCT__ "PetscDrawBarSort" 306 /*@ 307 PetscDrawBarSort - Sorts the values before drawing the bar chart 308 309 Logically Collective on PetscDrawBar 310 311 Input Parameters: 312 + bar - The bar graph context 313 . sort - PETSC_TRUE to sort the values 314 . tolerance - discard values less than tolerance 315 316 Level: intermediate 317 318 Concepts: bar graph^setting axis 319 @*/ 320 PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance) 321 { 322 PetscFunctionBegin; 323 if (!bar) PetscFunctionReturn(0); 324 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 325 bar->sort = sort; 326 bar->sorttolerance = tolerance; 327 PetscFunctionReturn(0); 328 } 329 330 #undef __FUNCT__ 331 #define __FUNCT__ "PetscDrawBarSetLimits" 332 /*@ 333 PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more 334 points are added after this call, the limits will be adjusted to 335 include those additional points. 336 337 Logically Collective on PetscDrawBar 338 339 Input Parameters: 340 + bar - The bar graph context 341 - y_min,y_max - The limits 342 343 Level: intermediate 344 345 Concepts: bar graph^setting axis 346 @*/ 347 PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max) 348 { 349 PetscFunctionBegin; 350 if (!bar) PetscFunctionReturn(0); 351 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 352 bar->ymin = y_min; 353 bar->ymax = y_max; 354 PetscFunctionReturn(0); 355 } 356 357 #undef __FUNCT__ 358 #define __FUNCT__ "PetscDrawBarGetAxis" 359 /*@C 360 PetscDrawBarGetAxis - Gets the axis context associated with a bar graph. 361 This is useful if one wants to change some axis property, such as 362 labels, color, etc. The axis context should not be destroyed by the 363 application code. 364 365 Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel 366 367 Input Parameter: 368 . bar - The bar graph context 369 370 Output Parameter: 371 . axis - The axis context 372 373 Level: intermediate 374 375 @*/ 376 PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis) 377 { 378 PetscFunctionBegin; 379 PetscValidPointer(axis,2); 380 if (!bar) {*axis = NULL; PetscFunctionReturn(0);} 381 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 382 *axis = bar->axis; 383 PetscFunctionReturn(0); 384 } 385 386 #undef __FUNCT__ 387 #define __FUNCT__ "PetscDrawBarGetDraw" 388 /*@C 389 PetscDrawBarGetDraw - Gets the draw context associated with a bar graph. 390 391 Not Collective, PetscDraw is parallel if PetscDrawBar is parallel 392 393 Input Parameter: 394 . bar - The bar graph context 395 396 Output Parameter: 397 . draw - The draw context 398 399 Level: intermediate 400 401 @*/ 402 PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *draw) 403 { 404 PetscFunctionBegin; 405 PetscValidPointer(draw,2); 406 if (!bar) {*draw = NULL; PetscFunctionReturn(0);} 407 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 408 *draw = bar->win; 409 PetscFunctionReturn(0); 410 } 411 412 #undef __FUNCT__ 413 #define __FUNCT__ "PetscDrawBarSetFromOptions" 414 /*@ 415 PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar 416 417 Collective over PetscDrawBar 418 419 Options Database: 420 . -bar_sort - sort the entries before drawing the bar graph 421 422 Level: intermediate 423 424 425 .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate() 426 @*/ 427 PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar) 428 { 429 PetscErrorCode ierr; 430 PetscBool set; 431 432 PetscFunctionBegin; 433 if (!bar) PetscFunctionReturn(0); 434 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 435 436 ierr = PetscOptionsHasName(((PetscObject)bar)->options,NULL,"-bar_sort",&set);CHKERRQ(ierr); 437 if (set) { 438 PetscReal tol = bar->sorttolerance; 439 ierr = PetscOptionsGetReal(((PetscObject)bar)->options,NULL,"-bar_sort",&tol,NULL);CHKERRQ(ierr); 440 ierr = PetscDrawBarSort(bar,PETSC_TRUE,tol);CHKERRQ(ierr); 441 } 442 PetscFunctionReturn(0); 443 } 444 445