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__ "PetscDrawBarSetColor" 255 /*@ 256 PetscDrawBarSetColor - Sets the color the bars will be drawn with. 257 258 Logically Collective on PetscDrawBar 259 260 Input Parameters: 261 + bar - The bar graph context 262 - color - one of the colors defined in petscdraw.h or PETSC_DRAW_ROTATE to make each bar a 263 different color 264 265 Level: intermediate 266 267 @*/ 268 PetscErrorCode PetscDrawBarSetColor(PetscDrawBar bar, int color) 269 { 270 PetscFunctionBegin; 271 if (!bar) PetscFunctionReturn(0); 272 PetscValidHeaderSpecific(bar, PETSC_DRAWBAR_CLASSID,1); 273 bar->color = color; 274 PetscFunctionReturn(0); 275 } 276 277 #undef __FUNCT__ 278 #define __FUNCT__ "PetscDrawBarSort" 279 /*@ 280 PetscDrawBarSort - Sorts the values before drawing the bar chart 281 282 Logically Collective on PetscDrawBar 283 284 Input Parameters: 285 + bar - The bar graph context 286 . sort - PETSC_TRUE to sort the values 287 . tolerance - discard values less than tolerance 288 289 Level: intermediate 290 291 Concepts: bar graph^setting axis 292 @*/ 293 PetscErrorCode PetscDrawBarSort(PetscDrawBar bar, PetscBool sort, PetscReal tolerance) 294 { 295 PetscFunctionBegin; 296 if (!bar) PetscFunctionReturn(0); 297 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 298 bar->sort = sort; 299 bar->sorttolerance = tolerance; 300 PetscFunctionReturn(0); 301 } 302 303 #undef __FUNCT__ 304 #define __FUNCT__ "PetscDrawBarSetLimits" 305 /*@ 306 PetscDrawBarSetLimits - Sets the axis limits for a bar graph. If more 307 points are added after this call, the limits will be adjusted to 308 include those additional points. 309 310 Logically Collective on PetscDrawBar 311 312 Input Parameters: 313 + bar - The bar graph context 314 - y_min,y_max - The limits 315 316 Level: intermediate 317 318 Concepts: bar graph^setting axis 319 @*/ 320 PetscErrorCode PetscDrawBarSetLimits(PetscDrawBar bar, PetscReal y_min, PetscReal y_max) 321 { 322 PetscFunctionBegin; 323 if (!bar) PetscFunctionReturn(0); 324 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 325 bar->ymin = y_min; 326 bar->ymax = y_max; 327 PetscFunctionReturn(0); 328 } 329 330 #undef __FUNCT__ 331 #define __FUNCT__ "PetscDrawBarGetAxis" 332 /*@C 333 PetscDrawBarGetAxis - Gets the axis context associated with a bar graph. 334 This is useful if one wants to change some axis property, such as 335 labels, color, etc. The axis context should not be destroyed by the 336 application code. 337 338 Not Collective, PetscDrawAxis is parallel if PetscDrawBar is parallel 339 340 Input Parameter: 341 . bar - The bar graph context 342 343 Output Parameter: 344 . axis - The axis context 345 346 Level: intermediate 347 348 @*/ 349 PetscErrorCode PetscDrawBarGetAxis(PetscDrawBar bar, PetscDrawAxis *axis) 350 { 351 PetscFunctionBegin; 352 PetscValidPointer(axis,2); 353 if (!bar) {*axis = NULL; PetscFunctionReturn(0);} 354 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 355 *axis = bar->axis; 356 PetscFunctionReturn(0); 357 } 358 359 #undef __FUNCT__ 360 #define __FUNCT__ "PetscDrawBarGetDraw" 361 /*@C 362 PetscDrawBarGetDraw - Gets the draw context associated with a bar graph. 363 364 Not Collective, PetscDraw is parallel if PetscDrawBar is parallel 365 366 Input Parameter: 367 . bar - The bar graph context 368 369 Output Parameter: 370 . draw - The draw context 371 372 Level: intermediate 373 374 @*/ 375 PetscErrorCode PetscDrawBarGetDraw(PetscDrawBar bar, PetscDraw *draw) 376 { 377 PetscFunctionBegin; 378 PetscValidPointer(draw,2); 379 if (!bar) {*draw = NULL; PetscFunctionReturn(0);} 380 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 381 *draw = bar->win; 382 PetscFunctionReturn(0); 383 } 384 385 #undef __FUNCT__ 386 #define __FUNCT__ "PetscDrawBarSetFromOptions" 387 /*@ 388 PetscDrawBarSetFromOptions - Sets options related to the PetscDrawBar 389 390 Collective over PetscDrawBar 391 392 Options Database: 393 . -bar_sort - sort the entries before drawing the bar graph 394 395 Level: intermediate 396 397 398 .seealso: PetscDrawBarDestroy(), PetscDrawBarCreate() 399 @*/ 400 PetscErrorCode PetscDrawBarSetFromOptions(PetscDrawBar bar) 401 { 402 PetscErrorCode ierr; 403 PetscBool set; 404 405 PetscFunctionBegin; 406 if (!bar) PetscFunctionReturn(0); 407 PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); 408 409 ierr = PetscOptionsHasName(((PetscObject)bar)->options,NULL,"-bar_sort",&set);CHKERRQ(ierr); 410 if (set) { 411 PetscReal tol = bar->sorttolerance; 412 ierr = PetscOptionsGetReal(((PetscObject)bar)->options,NULL,"-bar_sort",&tol,NULL);CHKERRQ(ierr); 413 ierr = PetscDrawBarSort(bar,PETSC_TRUE,tol);CHKERRQ(ierr); 414 } 415 PetscFunctionReturn(0); 416 } 417 418