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