Actual source code: dscatter.c

  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: */

  7: #include <petscdraw.h>
  8: #include <petsc/private/drawimpl.h>

 10: PetscClassId PETSC_DRAWSP_CLASSID = 0;

 12: /*@C
 13:   PetscDrawSPCreate - Creates a scatter plot data structure.

 15:   Collective

 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

 21:   Output Parameters:
 22: . drawsp - the scatter plot context

 24:   Level: intermediate

 26:   Notes:
 27:   Add points to the plot with `PetscDrawSPAddPoint()` or `PetscDrawSPAddPoints()`; the new points are not displayed until `PetscDrawSPDraw()` is called.

 29:   `PetscDrawSPReset()` removes all the points that have been added

 31:   `PetscDrawSPSetDimension()` determines how many point curves are being plotted.

 33:   The MPI communicator that owns the `PetscDraw` owns this `PetscDrawSP`, and each process can add points. All MPI ranks in the communicator must call `PetscDrawSPDraw()` to display the updated graph.

 35: .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawSPDestroy()`, `PetscDraw`, `PetscDrawSP`, `PetscDrawSPSetDimension()`, `PetscDrawSPReset()`,
 36:           `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPDraw()`, `PetscDrawSPSave()`, `PetscDrawSPSetLimits()`, `PetscDrawSPGetAxis()`, `PetscDrawAxis`, `PetscDrawSPGetDraw()`
 37: @*/
 38: PetscErrorCode PetscDrawSPCreate(PetscDraw draw, int dim, PetscDrawSP *drawsp)
 39: {
 40:   PetscDrawSP sp;


 45:   PetscHeaderCreate(sp, PETSC_DRAWSP_CLASSID, "DrawSP", "Scatter Plot", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawSPDestroy, NULL);
 46:   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;

 61:   PetscDrawSPSetDimension(sp, dim);
 62:   PetscDrawAxisCreate(draw, &sp->axis);

 64:   *drawsp = sp;
 65:   return 0;
 66: }

 68: /*@
 69:   PetscDrawSPSetDimension - Change the number of points that are added at each  `PetscDrawSPAddPoint()`

 71:   Not collective

 73:   Input Parameters:
 74: + sp  - the scatter plot context.
 75: - dim - the number of point curves on this process

 77:   Level: intermediate

 79: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
 80: @*/
 81: PetscErrorCode PetscDrawSPSetDimension(PetscDrawSP sp, int dim)
 82: {
 84:   if (sp->dim == dim) return 0;
 85:   sp->dim = dim;
 86:   PetscFree3(sp->x, sp->y, sp->z);
 87:   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);
 88:   sp->len = dim * PETSC_DRAW_SP_CHUNK_SIZE;
 89:   return 0;
 90: }

 92: /*@
 93:   PetscDrawSPGetDimension - Get the number of sets of points that are to be drawn at each `PetscDrawSPAddPoint()`

 95:   Not collective

 97:   Input Parameters:
 98: . sp  - the scatter plot context.

100:   Output Parameter:
101: . dim - the number of point curves on this process

103:   Level: intermediate

105: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
106: @*/
107: PetscErrorCode PetscDrawSPGetDimension(PetscDrawSP sp, int *dim)
108: {
111:   *dim = sp->dim;
112:   return 0;
113: }

115: /*@
116:   PetscDrawSPReset - Clears scatter plot to allow for reuse with new data.

118:   Not collective

120:   Input Parameter:
121: . sp - the scatter plot context.

123:   Level: intermediate

125: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPDraw()`
126: @*/
127: PetscErrorCode PetscDrawSPReset(PetscDrawSP sp)
128: {
130:   sp->xmin  = 1.e20;
131:   sp->ymin  = 1.e20;
132:   sp->zmin  = 1.e20;
133:   sp->xmax  = -1.e20;
134:   sp->ymax  = -1.e20;
135:   sp->zmax  = -1.e20;
136:   sp->loc   = 0;
137:   sp->nopts = 0;
138:   return 0;
139: }

141: /*@
142:   PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.

144:   Collective

146:   Input Parameter:
147: . sp - the scatter plot context

149:   Level: intermediate

151: .seealso: `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawSPReset()`
152: @*/
153: PetscErrorCode PetscDrawSPDestroy(PetscDrawSP *sp)
154: {
155:   if (!*sp) return 0;
157:   if (--((PetscObject)(*sp))->refct > 0) {
158:     *sp = NULL;
159:     return 0;
160:   }

162:   PetscFree3((*sp)->x, (*sp)->y, (*sp)->z);
163:   PetscDrawAxisDestroy(&(*sp)->axis);
164:   PetscDrawDestroy(&(*sp)->win);
165:   PetscHeaderDestroy(sp);
166:   return 0;
167: }

169: /*@
170:   PetscDrawSPAddPoint - Adds another point to each of the scatter plot point curves.

172:   Not collective

174:   Input Parameters:
175: + sp - the scatter plot data structure
176: - x, y - two arrays of length dim containing the new x and y coordinate values for each of the point curves. Here  dim is the number of point curves passed to PetscDrawSPCreate()

178:   Level: intermediate

180:   Note:
181:   The new points will not be displayed until a call to `PetscDrawSPDraw()` is made

183: .seealso: `PetscDrawSPAddPoints()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPointColorized()`
184: @*/
185: PetscErrorCode PetscDrawSPAddPoint(PetscDrawSP sp, PetscReal *x, PetscReal *y)
186: {
187:   PetscInt i;


191:   if (sp->loc + sp->dim >= sp->len) { /* allocate more space */
192:     PetscReal *tmpx, *tmpy, *tmpz;
193:     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);
194:     PetscArraycpy(tmpx, sp->x, sp->len);
195:     PetscArraycpy(tmpy, sp->y, sp->len);
196:     PetscArraycpy(tmpz, sp->z, sp->len);
197:     PetscFree3(sp->x, sp->y, sp->z);
198:     sp->x = tmpx;
199:     sp->y = tmpy;
200:     sp->z = tmpz;
201:     sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
202:   }
203:   for (i = 0; i < sp->dim; ++i) {
204:     if (x[i] > sp->xmax) sp->xmax = x[i];
205:     if (x[i] < sp->xmin) sp->xmin = x[i];
206:     if (y[i] > sp->ymax) sp->ymax = y[i];
207:     if (y[i] < sp->ymin) sp->ymin = y[i];

209:     sp->x[sp->loc]   = x[i];
210:     sp->y[sp->loc++] = y[i];
211:   }
212:   ++sp->nopts;
213:   return 0;
214: }

216: /*@C
217:   PetscDrawSPAddPoints - Adds several points to each of the scatter plot point curves.

219:   Not collective

221:   Input Parameters:
222: + sp - the scatter plot context
223: . xx,yy - points to two arrays of pointers that point to arrays containing the new x and y points for each curve.
224: - n - number of points being added, each represents a subarray of length dim where dim is the value from `PetscDrawSPGetDimension()`

226:   Level: intermediate

228:   Note:
229:   The new points will not be displayed until a call to `PetscDrawSPDraw()` is made

231: .seealso: `PetscDrawSPAddPoint()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPointColorized()`
232: @*/
233: PetscErrorCode PetscDrawSPAddPoints(PetscDrawSP sp, int n, PetscReal **xx, PetscReal **yy)
234: {
235:   PetscInt   i, j, k;
236:   PetscReal *x, *y;


240:   if (sp->loc + n * sp->dim >= sp->len) { /* allocate more space */
241:     PetscReal *tmpx, *tmpy, *tmpz;
242:     PetscInt   chunk = PETSC_DRAW_SP_CHUNK_SIZE;
243:     if (n > chunk) chunk = n;
244:     PetscMalloc3(sp->len + sp->dim * chunk, &tmpx, sp->len + sp->dim * chunk, &tmpy, sp->len + sp->dim * chunk, &tmpz);
245:     PetscArraycpy(tmpx, sp->x, sp->len);
246:     PetscArraycpy(tmpy, sp->y, sp->len);
247:     PetscArraycpy(tmpz, sp->z, sp->len);
248:     PetscFree3(sp->x, sp->y, sp->z);

250:     sp->x = tmpx;
251:     sp->y = tmpy;
252:     sp->z = tmpz;
253:     sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
254:   }
255:   for (j = 0; j < sp->dim; ++j) {
256:     x = xx[j];
257:     y = yy[j];
258:     k = sp->loc + j;
259:     for (i = 0; i < n; ++i) {
260:       if (x[i] > sp->xmax) sp->xmax = x[i];
261:       if (x[i] < sp->xmin) sp->xmin = x[i];
262:       if (y[i] > sp->ymax) sp->ymax = y[i];
263:       if (y[i] < sp->ymin) sp->ymin = y[i];

265:       sp->x[k] = x[i];
266:       sp->y[k] = y[i];
267:       k += sp->dim;
268:     }
269:   }
270:   sp->loc += n * sp->dim;
271:   sp->nopts += n;
272:   return 0;
273: }

275: /*@
276:   PetscDrawSPAddPointColorized - Adds another point to each of the scatter plots as well as a numeric value to be used to colorize the scatter point.

278:   Not collective

280:   Input Parameters:
281: + sp - the scatter plot data structure
282: . x, y - two arrays of length dim containing the new x and y coordinate values for each of the point curves. Here  dim is the number of point curves passed to `PetscDrawSPCreate()`
283: - z - array of length dim containing the numeric values that will be mapped to [0,255] and used for scatter point colors.

285:   Level: intermediate

287:   Note:
288:   The new points will not be displayed until a call to `PetscDrawSPDraw()` is made

290: .seealso: `PetscDrawSPAddPoints()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`
291: @*/
292: PetscErrorCode PetscDrawSPAddPointColorized(PetscDrawSP sp, PetscReal *x, PetscReal *y, PetscReal *z)
293: {
294:   PetscInt i;

297:   sp->colorized = PETSC_TRUE;
298:   if (sp->loc + sp->dim >= sp->len) { /* allocate more space */
299:     PetscReal *tmpx, *tmpy, *tmpz;
300:     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);
301:     PetscArraycpy(tmpx, sp->x, sp->len);
302:     PetscArraycpy(tmpy, sp->y, sp->len);
303:     PetscArraycpy(tmpz, sp->z, sp->len);
304:     PetscFree3(sp->x, sp->y, sp->z);
305:     sp->x = tmpx;
306:     sp->y = tmpy;
307:     sp->z = tmpz;
308:     sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
309:   }
310:   for (i = 0; i < sp->dim; ++i) {
311:     if (x[i] > sp->xmax) sp->xmax = x[i];
312:     if (x[i] < sp->xmin) sp->xmin = x[i];
313:     if (y[i] > sp->ymax) sp->ymax = y[i];
314:     if (y[i] < sp->ymin) sp->ymin = y[i];
315:     if (z[i] < sp->zmin) sp->zmin = z[i];
316:     if (z[i] > sp->zmax) sp->zmax = z[i];
317:     // if (z[i] > sp->zmax && z[i] < 5.) sp->zmax = z[i];

319:     sp->x[sp->loc]   = x[i];
320:     sp->y[sp->loc]   = y[i];
321:     sp->z[sp->loc++] = z[i];
322:   }
323:   ++sp->nopts;
324:   return 0;
325: }

327: /*@
328:   PetscDrawSPDraw - Redraws a scatter plot.

330:   Collective

332:   Input Parameters:
333: + sp - the scatter plot context
334: - clear - clear the window before drawing the new plot

336:   Level: intermediate

338: .seealso: `PetscDrawLGDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
339: @*/
340: PetscErrorCode PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
341: {
342:   PetscDraw   draw;
343:   PetscBool   isnull;
344:   PetscMPIInt rank, size;

347:   draw = sp->win;
348:   PetscDrawIsNull(draw, &isnull);
349:   if (isnull) return 0;
350:   MPI_Comm_rank(PetscObjectComm((PetscObject)sp), &rank);
351:   MPI_Comm_size(PetscObjectComm((PetscObject)sp), &size);

353:   if (clear) {
354:     PetscDrawCheckResizedWindow(draw);
355:     PetscDrawClear(draw);
356:   }
357:   {
358:     PetscReal lower[2] = {sp->xmin, sp->ymin}, glower[2];
359:     PetscReal upper[2] = {sp->xmax, sp->ymax}, gupper[2];
360:     MPIU_Allreduce(lower, glower, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)sp));
361:     MPIU_Allreduce(upper, gupper, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)sp));
362:     PetscDrawAxisSetLimits(sp->axis, glower[0], gupper[0], glower[1], gupper[1]);
363:     PetscDrawAxisDraw(sp->axis);
364:   }

366:   PetscDrawCollectiveBegin(draw);
367:   {
368:     const int dim = sp->dim, nopts = sp->nopts;

370:     for (int i = 0; i < dim; ++i) {
371:       for (int p = 0; p < nopts; ++p) {
372:         PetscInt color = sp->colorized ? PetscDrawRealToColor(sp->z[p * dim], sp->zmin, sp->zmax) : (size > 1 ? PetscDrawRealToColor(rank, 0, size - 1) : PETSC_DRAW_RED);

374:         PetscDrawPoint(draw, sp->x[p * dim + i], sp->y[p * dim + i], color);
375:       }
376:     }
377:   }
378:   PetscDrawCollectiveEnd(draw);

380:   PetscDrawFlush(draw);
381:   PetscDrawPause(draw);
382:   return 0;
383: }

385: /*@
386:   PetscDrawSPSave - Saves a drawn image

388:   Collective

390:   Input Parameter:
391: . sp - the scatter plot context

393:   Level: intermediate

395: .seealso: `PetscDrawSPSave()`, `PetscDrawSPCreate()`, `PetscDrawSPGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`
396: @*/
397: PetscErrorCode PetscDrawSPSave(PetscDrawSP sp)
398: {
400:   PetscDrawSave(sp->win);
401:   return 0;
402: }

404: /*@
405:   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.

407:   Not collective

409:   Input Parameters:
410: + xsp - the line graph context
411: - x_min,x_max,y_min,y_max - the limits

413:   Level: intermediate

415: .seealso: `PetscDrawSP`, `PetscDrawAxis`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPGetAxis()`
416: @*/
417: PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max)
418: {
420:   sp->xmin = x_min;
421:   sp->xmax = x_max;
422:   sp->ymin = y_min;
423:   sp->ymax = y_max;
424:   return 0;
425: }

427: /*@
428:   PetscDrawSPGetAxis - Gets the axis context associated with a scatter plot

430:   Not Collective

432:   Input Parameter:
433: . sp - the scatter plot context

435:   Output Parameter:
436: . axis - the axis context

438:   Note:
439:   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.

441:   Level: intermediate

443: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawAxis`, `PetscDrawAxisCreate()`
444: @*/
445: PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp, PetscDrawAxis *axis)
446: {
449:   *axis = sp->axis;
450:   return 0;
451: }

453: /*@
454:   PetscDrawSPGetDraw - Gets the draw context associated with a scatter plot

456:   Not Collective

458:   Input Parameter:
459: . sp - the scatter plot context

461:   Output Parameter:
462: . draw - the draw context

464:   Level: intermediate

466: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDraw`
467: @*/
468: PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp, PetscDraw *draw)
469: {
472:   *draw = sp->win;
473:   return 0;
474: }