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