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