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