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