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