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: }