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