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