1 2 /* 3 Contains the data structure for drawing scatter plots 4 graphs in a window with an axis. This is intended for scatter 5 plots that change dynamically. 6 */ 7 8 #include <petscdraw.h> /*I "petscdraw.h" I*/ 9 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 10 11 PetscClassId PETSC_DRAWSP_CLASSID = 0; 12 13 struct _p_PetscDrawSP { 14 PETSCHEADER(int); 15 PetscErrorCode (*destroy)(PetscDrawSP); 16 PetscErrorCode (*view)(PetscDrawSP,PetscViewer); 17 int len,loc; 18 PetscDraw win; 19 PetscDrawAxis axis; 20 PetscReal xmin,xmax,ymin,ymax,*x,*y; 21 int nopts,dim; 22 }; 23 24 #define CHUNCKSIZE 100 25 26 #undef __FUNCT__ 27 #define __FUNCT__ "PetscDrawSPCreate" 28 /*@C 29 PetscDrawSPCreate - Creates a scatter plot data structure. 30 31 Collective on PetscDraw 32 33 Input Parameters: 34 + win - the window where the graph will be made. 35 - dim - the number of sets of points which will be drawn 36 37 Output Parameters: 38 . drawsp - the scatter plot context 39 40 Level: intermediate 41 42 Notes: Add points to the plot with PetscDrawSPAddPoint() or PetscDrawSPAddPoints(); the new points are not displayed until PetscDrawSPDraw() is called. 43 44 PetscDrawSPReset() removes all the points that have been added 45 46 Concepts: scatter plot^creating 47 48 .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawHGCreate(), PetscDrawHG, PetscDrawSPDestroy(), PetscDraw, PetscDrawSP, PetscDrawSPSetDimension(), PetscDrawSPReset(), 49 PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw(), PetscDrawSPSave(), PetscDrawSPSetLimits(), PetscDrawSPGetAxis(),PetscDrawAxis, PetscDrawSPGetDraw() 50 @*/ 51 PetscErrorCode PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp) 52 { 53 PetscDrawSP sp; 54 PetscErrorCode ierr; 55 56 PetscFunctionBegin; 57 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 58 PetscValidLogicalCollectiveInt(draw,dim,2); 59 PetscValidPointer(drawsp,3); 60 61 ierr = PetscHeaderCreate(sp,PETSC_DRAWSP_CLASSID,"DrawSP","Scatter Plot","Draw",PetscObjectComm((PetscObject)draw),PetscDrawSPDestroy,NULL);CHKERRQ(ierr); 62 ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)sp);CHKERRQ(ierr); 63 64 ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr); 65 sp->win = draw; 66 67 sp->view = NULL; 68 sp->destroy = NULL; 69 sp->nopts = 0; 70 sp->dim = dim; 71 sp->xmin = 1.e20; 72 sp->ymin = 1.e20; 73 sp->xmax = -1.e20; 74 sp->ymax = -1.e20; 75 76 ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr); 77 ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 78 79 sp->len = dim*CHUNCKSIZE; 80 sp->loc = 0; 81 82 ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr); 83 ierr = PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis);CHKERRQ(ierr); 84 85 *drawsp = sp; 86 PetscFunctionReturn(0); 87 } 88 89 #undef __FUNCT__ 90 #define __FUNCT__ "PetscDrawSPSetDimension" 91 /*@ 92 PetscDrawSPSetDimension - Change the number of sets of points that are to be drawn. 93 94 Logically Collective on PetscDrawSP 95 96 Input Parameter: 97 + sp - the line graph context. 98 - dim - the number of curves. 99 100 Level: intermediate 101 102 Concepts: scatter plot^setting number of data types 103 104 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints() 105 106 @*/ 107 PetscErrorCode PetscDrawSPSetDimension(PetscDrawSP sp,int dim) 108 { 109 PetscErrorCode ierr; 110 111 PetscFunctionBegin; 112 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 113 PetscValidLogicalCollectiveInt(sp,dim,2); 114 if (sp->dim == dim) PetscFunctionReturn(0); 115 116 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 117 sp->dim = dim; 118 ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr); 119 ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 120 sp->len = dim*CHUNCKSIZE; 121 PetscFunctionReturn(0); 122 } 123 124 #undef __FUNCT__ 125 #define __FUNCT__ "PetscDrawSPReset" 126 /*@ 127 PetscDrawSPReset - Clears line graph to allow for reuse with new data. 128 129 Logically Collective on PetscDrawSP 130 131 Input Parameter: 132 . sp - the line graph context. 133 134 Level: intermediate 135 136 Concepts: scatter plot^resetting 137 138 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw() 139 @*/ 140 PetscErrorCode PetscDrawSPReset(PetscDrawSP sp) 141 { 142 PetscFunctionBegin; 143 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 144 sp->xmin = 1.e20; 145 sp->ymin = 1.e20; 146 sp->xmax = -1.e20; 147 sp->ymax = -1.e20; 148 sp->loc = 0; 149 sp->nopts = 0; 150 PetscFunctionReturn(0); 151 } 152 153 #undef __FUNCT__ 154 #define __FUNCT__ "PetscDrawSPDestroy" 155 /*@C 156 PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure. 157 158 Collective on PetscDrawSP 159 160 Input Parameter: 161 . sp - the line graph context 162 163 Level: intermediate 164 165 .seealso: PetscDrawSPCreate(), PetscDrawSP, PetscDrawSPReset() 166 167 @*/ 168 PetscErrorCode PetscDrawSPDestroy(PetscDrawSP *sp) 169 { 170 PetscErrorCode ierr; 171 172 PetscFunctionBegin; 173 if (!*sp) PetscFunctionReturn(0); 174 PetscValidHeaderSpecific(*sp,PETSC_DRAWSP_CLASSID,1); 175 if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);} 176 177 ierr = PetscFree2((*sp)->x,(*sp)->y);CHKERRQ(ierr); 178 ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr); 179 ierr = PetscDrawDestroy(&(*sp)->win);CHKERRQ(ierr); 180 ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 181 PetscFunctionReturn(0); 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "PetscDrawSPAddPoint" 186 /*@ 187 PetscDrawSPAddPoint - Adds another point to each of the scatter plots. 188 189 Logically Collective on PetscDrawSP 190 191 Input Parameters: 192 + sp - the scatter plot data structure 193 - x, y - the points to two vectors containing the new x and y 194 point for each curve. 195 196 Level: intermediate 197 198 Notes: the new points will not be displayed until a call to PetscDrawSPDraw() is made 199 200 Concepts: scatter plot^adding points 201 202 .seealso: PetscDrawSPAddPoints(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw() 203 204 @*/ 205 PetscErrorCode PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal *x,PetscReal *y) 206 { 207 PetscErrorCode ierr; 208 PetscInt i; 209 210 PetscFunctionBegin; 211 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 212 213 if (sp->loc+sp->dim >= sp->len) { /* allocate more space */ 214 PetscReal *tmpx,*tmpy; 215 ierr = PetscMalloc2(sp->len+sp->dim*CHUNCKSIZE,&tmpx,sp->len+sp->dim*CHUNCKSIZE,&tmpy);CHKERRQ(ierr); 216 ierr = PetscLogObjectMemory((PetscObject)sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 217 ierr = PetscMemcpy(tmpx,sp->x,sp->len*sizeof(PetscReal));CHKERRQ(ierr); 218 ierr = PetscMemcpy(tmpy,sp->y,sp->len*sizeof(PetscReal));CHKERRQ(ierr); 219 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 220 sp->x = tmpx; 221 sp->y = tmpy; 222 sp->len += sp->dim*CHUNCKSIZE; 223 } 224 for (i=0; i<sp->dim; i++) { 225 if (x[i] > sp->xmax) sp->xmax = x[i]; 226 if (x[i] < sp->xmin) sp->xmin = x[i]; 227 if (y[i] > sp->ymax) sp->ymax = y[i]; 228 if (y[i] < sp->ymin) sp->ymin = y[i]; 229 230 sp->x[sp->loc] = x[i]; 231 sp->y[sp->loc++] = y[i]; 232 } 233 sp->nopts++; 234 PetscFunctionReturn(0); 235 } 236 237 238 #undef __FUNCT__ 239 #define __FUNCT__ "PetscDrawSPAddPoints" 240 /*@C 241 PetscDrawSPAddPoints - Adds several points to each of the scatter plots. 242 243 Logically Collective on PetscDrawSP 244 245 Input Parameters: 246 + sp - the LineGraph data structure 247 . xx,yy - points to two arrays of pointers that point to arrays 248 containing the new x and y points for each curve. 249 - n - number of points being added 250 251 Level: intermediate 252 253 Notes: the new points will not be displayed until a call to PetscDrawSPDraw() is made 254 255 Concepts: scatter plot^adding points 256 257 .seealso: PetscDrawSPAddPoint(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw() 258 @*/ 259 PetscErrorCode PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy) 260 { 261 PetscErrorCode ierr; 262 PetscInt i,j,k; 263 PetscReal *x,*y; 264 265 PetscFunctionBegin; 266 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 267 268 if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */ 269 PetscReal *tmpx,*tmpy; 270 PetscInt chunk = CHUNCKSIZE; 271 if (n > chunk) chunk = n; 272 ierr = PetscMalloc2(sp->len+sp->dim*chunk,&tmpx,sp->len+sp->dim*chunk,&tmpy);CHKERRQ(ierr); 273 ierr = PetscLogObjectMemory((PetscObject)sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 274 ierr = PetscMemcpy(tmpx,sp->x,sp->len*sizeof(PetscReal));CHKERRQ(ierr); 275 ierr = PetscMemcpy(tmpy,sp->y,sp->len*sizeof(PetscReal));CHKERRQ(ierr); 276 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 277 278 sp->x = tmpx; 279 sp->y = tmpy; 280 sp->len += sp->dim*CHUNCKSIZE; 281 } 282 for (j=0; j<sp->dim; j++) { 283 x = xx[j]; y = yy[j]; 284 k = sp->loc + j; 285 for (i=0; i<n; i++) { 286 if (x[i] > sp->xmax) sp->xmax = x[i]; 287 if (x[i] < sp->xmin) sp->xmin = x[i]; 288 if (y[i] > sp->ymax) sp->ymax = y[i]; 289 if (y[i] < sp->ymin) sp->ymin = y[i]; 290 291 sp->x[k] = x[i]; 292 sp->y[k] = y[i]; 293 k += sp->dim; 294 } 295 } 296 sp->loc += n*sp->dim; 297 sp->nopts += n; 298 PetscFunctionReturn(0); 299 } 300 301 #undef __FUNCT__ 302 #define __FUNCT__ "PetscDrawSPDraw" 303 /*@ 304 PetscDrawSPDraw - Redraws a scatter plot. 305 306 Collective on PetscDrawSP 307 308 Input Parameter: 309 + sp - the line graph context 310 - clear - clear the window before drawing the new plot 311 312 Level: intermediate 313 314 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints() 315 316 @*/ 317 PetscErrorCode PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear) 318 { 319 PetscReal xmin,xmax,ymin,ymax; 320 PetscErrorCode ierr; 321 PetscMPIInt rank; 322 PetscBool isnull; 323 PetscDraw draw; 324 325 PetscFunctionBegin; 326 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 327 ierr = PetscDrawIsNull(sp->win,&isnull);CHKERRQ(ierr); 328 if (isnull) PetscFunctionReturn(0); 329 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRQ(ierr); 330 331 if (sp->xmin > sp->xmax || sp->ymin > sp->ymax) PetscFunctionReturn(0); 332 if (sp->nopts < 1) PetscFunctionReturn(0); 333 334 draw = sp->win; 335 if (clear) { 336 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 337 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 338 } 339 340 xmin = sp->xmin; xmax = sp->xmax; ymin = sp->ymin; ymax = sp->ymax; 341 ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 342 ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr); 343 344 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 345 if (!rank) { 346 int i,j,dim=sp->dim,nopts=sp->nopts; 347 for (i=0; i<dim; i++) { 348 for (j=0; j<nopts; j++) { 349 ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr); 350 } 351 } 352 } 353 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 354 355 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 356 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 357 PetscFunctionReturn(0); 358 } 359 360 #undef __FUNCT__ 361 #define __FUNCT__ "PetscDrawSPSave" 362 /*@ 363 PetscDrawSPSave - Saves a drawn image 364 365 Collective on PetscDrawSP 366 367 Input Parameter: 368 . sp - the scatter plot context 369 370 Level: intermediate 371 372 Concepts: scatter plot^saving 373 374 .seealso: PetscDrawSPCreate(), PetscDrawSPGetDraw(), PetscDrawSetSave(), PetscDrawSave() 375 @*/ 376 PetscErrorCode PetscDrawSPSave(PetscDrawSP sp) 377 { 378 PetscErrorCode ierr; 379 380 PetscFunctionBegin; 381 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 382 ierr = PetscDrawSave(sp->win);CHKERRQ(ierr); 383 PetscFunctionReturn(0); 384 } 385 386 #undef __FUNCT__ 387 #define __FUNCT__ "PetscDrawSPSetLimits" 388 /*@ 389 PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more 390 points are added after this call, the limits will be adjusted to 391 include those additional points. 392 393 Logically Collective on PetscDrawSP 394 395 Input Parameters: 396 + xsp - the line graph context 397 - x_min,x_max,y_min,y_max - the limits 398 399 Level: intermediate 400 401 Concepts: scatter plot^setting axis 402 403 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPGetAxis() 404 @*/ 405 PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max) 406 { 407 PetscFunctionBegin; 408 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 409 sp->xmin = x_min; 410 sp->xmax = x_max; 411 sp->ymin = y_min; 412 sp->ymax = y_max; 413 PetscFunctionReturn(0); 414 } 415 416 #undef __FUNCT__ 417 #define __FUNCT__ "PetscDrawSPGetAxis" 418 /*@C 419 PetscDrawSPGetAxis - Gets the axis context associated with a line graph. 420 This is useful if one wants to change some axis property, such as 421 labels, color, etc. The axis context should not be destroyed by the 422 application code. 423 424 Not Collective, if PetscDrawSP is parallel then PetscDrawAxis is parallel 425 426 Input Parameter: 427 . sp - the line graph context 428 429 Output Parameter: 430 . axis - the axis context 431 432 Level: intermediate 433 434 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawAxis, PetscDrawAxisCreate() 435 436 @*/ 437 PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis) 438 { 439 PetscFunctionBegin; 440 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 441 PetscValidPointer(axis,2); 442 *axis = sp->axis; 443 PetscFunctionReturn(0); 444 } 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "PetscDrawSPGetDraw" 448 /*@C 449 PetscDrawSPGetDraw - Gets the draw context associated with a line graph. 450 451 Not Collective, PetscDraw is parallel if PetscDrawSP is parallel 452 453 Input Parameter: 454 . sp - the line graph context 455 456 Output Parameter: 457 . draw - the draw context 458 459 Level: intermediate 460 461 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDraw 462 @*/ 463 PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw) 464 { 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 467 PetscValidPointer(draw,2); 468 *draw = sp->win; 469 PetscFunctionReturn(0); 470 } 471