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