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 MPI_Comm comm; 53 PetscBool isnull; 54 PetscErrorCode ierr; 55 56 PetscFunctionBegin; 57 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID,1); 58 PetscValidPointer(bar,3); 59 ierr = PetscObjectGetComm((PetscObject) draw, &comm);CHKERRQ(ierr); 60 ierr = PetscHeaderCreate(h, _p_PetscDrawBar, int, PETSC_DRAWBAR_CLASSID, "PetscDrawBar", "Bar Graph", "Draw", comm, PetscDrawBarDestroy, NULL);CHKERRQ(ierr); 61 62 h->view = NULL; 63 h->destroy = NULL; 64 h->win = draw; 65 66 ierr = PetscObjectReference((PetscObject) draw);CHKERRQ(ierr); 67 68 h->color = PETSC_DRAW_GREEN; 69 h->ymin = 0.; /* if user has not set these then they are determined from the data */ 70 h->ymax = 0.; 71 h->numBins = 0; 72 73 ierr = PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);CHKERRQ(ierr); 74 if (!isnull) { 75 ierr = PetscDrawAxisCreate(draw, &h->axis);CHKERRQ(ierr); 76 ierr = PetscLogObjectParent((PetscObject)h, (PetscObject)h->axis);CHKERRQ(ierr); 77 h->axis->xticks = NULL; 78 } else h->axis = NULL; 79 *bar = h; 80 PetscFunctionReturn(0); 81 } 82 83 #undef __FUNCT__ 84 #define __FUNCT__ "PetscDrawBarSetData" 85 /*@C 86 PetscDrawBarSetData 87 88 Not Collective (ignored except on processor 0 of 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 99 @*/ 100 PetscErrorCode PetscDrawBarSetData(PetscDrawBar bar, PetscInt bins,const PetscReal data[],const char *const *labels) 101 { 102 PetscErrorCode ierr; 103 104 PetscFunctionBegin; 105 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 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 PetscValidHeader(*bar,1); 140 141 if (--((PetscObject)(*bar))->refct > 0) PetscFunctionReturn(0); 142 ierr = PetscDrawAxisDestroy(&(*bar)->axis);CHKERRQ(ierr); 143 ierr = PetscDrawDestroy(&(*bar)->win);CHKERRQ(ierr); 144 ierr = PetscFree((*bar)->values);CHKERRQ(ierr); 145 ierr = PetscStrArrayDestroy(&(*bar)->labels);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 Not Collective (ignored except on processor 0 of 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 = bar->win; 166 PetscBool isnull; 167 PetscReal xmin,xmax,ymin,ymax,*values,binLeft,binRight; 168 PetscInt numValues,i,bcolor,color,idx,*perm,nplot; 169 PetscErrorCode ierr; 170 char **labels; 171 172 PetscFunctionBegin; 173 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 174 ierr = PetscObjectTypeCompare((PetscObject) draw, PETSC_DRAW_NULL, &isnull);CHKERRQ(ierr); 175 if (isnull) PetscFunctionReturn(0); 176 if (bar->numBins < 1) PetscFunctionReturn(0); 177 178 color = bar->color; 179 if (color == PETSC_DRAW_ROTATE) bcolor = 2; 180 else bcolor = color; 181 182 numValues = bar->numBins; 183 values = bar->values; 184 if (bar->ymin == bar->ymax) { 185 /* user has not set bounds on bars so set them based on the data */ 186 ymin = PETSC_MAX_REAL; 187 ymax = PETSC_MIN_REAL; 188 for (i=0; i<numValues; i++) { 189 ymin = PetscMin(ymin,values[i]); 190 ymax = PetscMax(ymax,values[i]); 191 } 192 } else { 193 ymin = bar->ymin; 194 ymax = bar->ymax; 195 } 196 nplot = numValues; /* number of points to actually plot; if some are lower than requested tolerance */ 197 xmin = 0.0; 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 xmax = nplot; 215 ierr = PetscDrawAxisSetLimits(bar->axis, xmin, xmax, ymin, ymax);CHKERRQ(ierr); 216 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 217 ierr = PetscDrawAxisDraw(bar->axis);CHKERRQ(ierr); 218 219 /* Draw bins */ 220 for (i = 0; i < nplot; i++) { 221 idx = (bar->sort ? perm[numValues - i - 1] : i); 222 binLeft = xmin + i; 223 binRight = xmin + i + 1; 224 ierr = PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);CHKERRQ(ierr); 225 ierr = PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr); 226 ierr = PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr); 227 ierr = PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);CHKERRQ(ierr); 228 if (labels) { 229 PetscReal h; 230 ierr = PetscDrawStringGetSize(draw,NULL,&h);CHKERRQ(ierr); 231 ierr = PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.2*h,bcolor,labels[idx]);CHKERRQ(ierr); 232 } 233 if (color == PETSC_DRAW_ROTATE) bcolor++; 234 if (bcolor > 31) bcolor = 2; 235 } 236 if (bar->sort) { 237 ierr = PetscFree(perm);CHKERRQ(ierr); 238 } 239 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 240 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 241 PetscFunctionReturn(0); 242 } 243 244 #undef __FUNCT__ 245 #define __FUNCT__ "PetscDrawBarSetColor" 246 /*@ 247 PetscDrawBarSetColor - Sets the color the bars will be drawn with. 248 249 Not Collective (ignored except on processor 0 of PetscDrawBar) 250 251 Input Parameters: 252 + bar - The bar graph context 253 - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a 254 different color 255 256 Level: intermediate 257 258 @*/ 259 PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color) 260 { 261 PetscFunctionBegin; 262 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 263 bar->color = color; 264 PetscFunctionReturn(0); 265 } 266 267 #undef __FUNCT__ 268 #define __FUNCT__ "PetscDrawBarSort" 269 /*@ 270 PetscDrawBarSort - Sorts the values before drawing the bar chart 271 272 Not Collective (ignored except on processor 0 of PetscDrawBar) 273 274 Input Parameters: 275 + bar - The bar graph context 276 . sort - PETSC_TRUE to sort the values 277 . tolerance - discard values less than tolerance 278 279 Level: intermediate 280 281 Concepts: bar graph^setting axis 282 @*/ 283 PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance) 284 { 285 PetscFunctionBegin; 286 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 287 bar->sort = sort; 288 bar->sorttolerance = tolerance; 289 PetscFunctionReturn(0); 290 } 291 292 #undef __FUNCT__ 293 #define __FUNCT__ "PetscDrawBarSetLimits" 294 /*@ 295 PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more 296 points are added after this call, the limits will be adjusted to 297 include those additional points. 298 299 Not Collective (ignored except on processor 0 of PetscDrawBar) 300 301 Input Parameters: 302 + bar - The bar graph context 303 - y_min,y_max - The limits 304 305 Level: intermediate 306 307 Concepts: bar graph^setting axis 308 @*/ 309 PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max) 310 { 311 PetscFunctionBegin; 312 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 313 bar->ymin = y_min; 314 bar->ymax = y_max; 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "PetscDrawBarGetAxis" 320 /*@C 321 PetscDrawBarGetAxis - Gets the axis context associated with a bar graph. 322 This is useful if one wants to change some axis property, such as 323 labels, color, etc. The axis context should not be destroyed by the 324 application code. 325 326 Not Collective (ignored except on processor 0 of PetscDrawBar) 327 328 Input Parameter: 329 . bar - The bar graph context 330 331 Output Parameter: 332 . axis - The axis context 333 334 Level: intermediate 335 336 @*/ 337 PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis) 338 { 339 PetscFunctionBegin; 340 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 341 PetscValidPointer(axis,2); 342 *axis = bar->axis; 343 PetscFunctionReturn(0); 344 } 345 346 #undef __FUNCT__ 347 #define __FUNCT__ "PetscDrawBarGetDraw" 348 /*@C 349 PetscDrawBarGetDraw - Gets the draw context associated with a bar graph. 350 351 Not Collective, PetscDraw is parallel if PetscDrawBar is parallel 352 353 Input Parameter: 354 . bar - The bar graph context 355 356 Output Parameter: 357 . win - The draw context 358 359 Level: intermediate 360 361 @*/ 362 PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *win) 363 { 364 PetscFunctionBegin; 365 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 366 PetscValidPointer(win,2); 367 *win = bar->win; 368 PetscFunctionReturn(0); 369 } 370 371 #undef __FUNCT__ 372 #define __FUNCT__ "PetscDrawBarSetFromOptions" 373 /*@ 374 PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar 375 376 Collective over PetscDrawBar 377 378 Options Database: 379 . -bar_sort - sort the entries before drawing the bar graph 380 381 Level: intermediate 382 383 384 .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate() 385 @*/ 386 PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar) 387 { 388 PetscErrorCode ierr; 389 PetscBool set; 390 PetscReal tol = bar->sorttolerance; 391 392 PetscFunctionBegin; 393 ierr = PetscOptionsHasName(NULL,"-bar_sort",&set);CHKERRQ(ierr); 394 if (set) { 395 ierr = PetscOptionsGetReal(NULL,"-bar_sort",&tol,NULL);CHKERRQ(ierr); 396 ierr = PetscDrawBarSort(bar,PETSC_TRUE,tol);CHKERRQ(ierr); 397 } 398 PetscFunctionReturn(0); 399 } 400 401