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