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;
42: PetscFunctionBegin;
46: PetscCall(PetscHeaderCreate(sp, PETSC_DRAWSP_CLASSID, "DrawSP", "Scatter Plot", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawSPDestroy, NULL));
47: PetscCall(PetscObjectReference((PetscObject)draw));
48: sp->win = draw;
49: sp->view = NULL;
50: sp->destroy = NULL;
51: sp->nopts = 0;
52: sp->dim = -1;
53: sp->xmin = 1.e20;
54: sp->ymin = 1.e20;
55: sp->zmin = 1.e20;
56: sp->xmax = -1.e20;
57: sp->ymax = -1.e20;
58: sp->zmax = -1.e20;
59: sp->colorized = PETSC_FALSE;
60: sp->loc = 0;
62: PetscCall(PetscDrawSPSetDimension(sp, dim));
63: PetscCall(PetscDrawAxisCreate(draw, &sp->axis));
65: *drawsp = sp;
66: PetscFunctionReturn(PETSC_SUCCESS);
67: }
69: /*@
70: PetscDrawSPSetDimension - Change the number of points that are added at each `PetscDrawSPAddPoint()`
72: Not collective
74: Input Parameters:
75: + sp - the scatter plot context.
76: - dim - the number of point curves on this process
78: Level: intermediate
80: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
81: @*/
82: PetscErrorCode PetscDrawSPSetDimension(PetscDrawSP sp, int dim)
83: {
84: PetscFunctionBegin;
86: if (sp->dim == dim) PetscFunctionReturn(PETSC_SUCCESS);
87: sp->dim = dim;
88: PetscCall(PetscFree3(sp->x, sp->y, sp->z));
89: PetscCall(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));
90: sp->len = dim * PETSC_DRAW_SP_CHUNK_SIZE;
91: PetscFunctionReturn(PETSC_SUCCESS);
92: }
94: /*@
95: PetscDrawSPGetDimension - Get the number of sets of points that are to be drawn at each `PetscDrawSPAddPoint()`
97: Not collective
99: Input Parameters:
100: . sp - the scatter plot context.
102: Output Parameter:
103: . dim - the number of point curves on this process
105: Level: intermediate
107: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
108: @*/
109: PetscErrorCode PetscDrawSPGetDimension(PetscDrawSP sp, int *dim)
110: {
111: PetscFunctionBegin;
114: *dim = sp->dim;
115: PetscFunctionReturn(PETSC_SUCCESS);
116: }
118: /*@
119: PetscDrawSPReset - Clears scatter plot to allow for reuse with new data.
121: Not collective
123: Input Parameter:
124: . sp - the scatter plot context.
126: Level: intermediate
128: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPDraw()`
129: @*/
130: PetscErrorCode PetscDrawSPReset(PetscDrawSP sp)
131: {
132: PetscFunctionBegin;
134: sp->xmin = 1.e20;
135: sp->ymin = 1.e20;
136: sp->zmin = 1.e20;
137: sp->xmax = -1.e20;
138: sp->ymax = -1.e20;
139: sp->zmax = -1.e20;
140: sp->loc = 0;
141: sp->nopts = 0;
142: PetscFunctionReturn(PETSC_SUCCESS);
143: }
145: /*@
146: PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
148: Collective
150: Input Parameter:
151: . sp - the scatter plot context
153: Level: intermediate
155: .seealso: `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawSPReset()`
156: @*/
157: PetscErrorCode PetscDrawSPDestroy(PetscDrawSP *sp)
158: {
159: PetscFunctionBegin;
160: if (!*sp) PetscFunctionReturn(PETSC_SUCCESS);
162: if (--((PetscObject)(*sp))->refct > 0) {
163: *sp = NULL;
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: PetscCall(PetscFree3((*sp)->x, (*sp)->y, (*sp)->z));
168: PetscCall(PetscDrawAxisDestroy(&(*sp)->axis));
169: PetscCall(PetscDrawDestroy(&(*sp)->win));
170: PetscCall(PetscHeaderDestroy(sp));
171: PetscFunctionReturn(PETSC_SUCCESS);
172: }
174: /*@
175: PetscDrawSPAddPoint - Adds another point to each of the scatter plot point curves.
177: Not collective
179: Input Parameters:
180: + sp - the scatter plot data structure
181: - 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()
183: Level: intermediate
185: Note:
186: The new points will not be displayed until a call to `PetscDrawSPDraw()` is made
188: .seealso: `PetscDrawSPAddPoints()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPointColorized()`
189: @*/
190: PetscErrorCode PetscDrawSPAddPoint(PetscDrawSP sp, PetscReal *x, PetscReal *y)
191: {
192: PetscInt i;
194: PetscFunctionBegin;
197: if (sp->loc + sp->dim >= sp->len) { /* allocate more space */
198: PetscReal *tmpx, *tmpy, *tmpz;
199: PetscCall(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));
200: PetscCall(PetscArraycpy(tmpx, sp->x, sp->len));
201: PetscCall(PetscArraycpy(tmpy, sp->y, sp->len));
202: PetscCall(PetscArraycpy(tmpz, sp->z, sp->len));
203: PetscCall(PetscFree3(sp->x, sp->y, sp->z));
204: sp->x = tmpx;
205: sp->y = tmpy;
206: sp->z = tmpz;
207: sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
208: }
209: for (i = 0; i < sp->dim; ++i) {
210: if (x[i] > sp->xmax) sp->xmax = x[i];
211: if (x[i] < sp->xmin) sp->xmin = x[i];
212: if (y[i] > sp->ymax) sp->ymax = y[i];
213: if (y[i] < sp->ymin) sp->ymin = y[i];
215: sp->x[sp->loc] = x[i];
216: sp->y[sp->loc++] = y[i];
217: }
218: ++sp->nopts;
219: PetscFunctionReturn(PETSC_SUCCESS);
220: }
222: /*@C
223: PetscDrawSPAddPoints - Adds several points to each of the scatter plot point curves.
225: Not collective
227: Input Parameters:
228: + sp - the scatter plot context
229: . xx,yy - points to two arrays of pointers that point to arrays containing the new x and y points for each curve.
230: - n - number of points being added, each represents a subarray of length dim where dim is the value from `PetscDrawSPGetDimension()`
232: Level: intermediate
234: Note:
235: The new points will not be displayed until a call to `PetscDrawSPDraw()` is made
237: .seealso: `PetscDrawSPAddPoint()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPointColorized()`
238: @*/
239: PetscErrorCode PetscDrawSPAddPoints(PetscDrawSP sp, int n, PetscReal **xx, PetscReal **yy)
240: {
241: PetscInt i, j, k;
242: PetscReal *x, *y;
244: PetscFunctionBegin;
247: if (sp->loc + n * sp->dim >= sp->len) { /* allocate more space */
248: PetscReal *tmpx, *tmpy, *tmpz;
249: PetscInt chunk = PETSC_DRAW_SP_CHUNK_SIZE;
250: if (n > chunk) chunk = n;
251: PetscCall(PetscMalloc3(sp->len + sp->dim * chunk, &tmpx, sp->len + sp->dim * chunk, &tmpy, sp->len + sp->dim * chunk, &tmpz));
252: PetscCall(PetscArraycpy(tmpx, sp->x, sp->len));
253: PetscCall(PetscArraycpy(tmpy, sp->y, sp->len));
254: PetscCall(PetscArraycpy(tmpz, sp->z, sp->len));
255: PetscCall(PetscFree3(sp->x, sp->y, sp->z));
257: sp->x = tmpx;
258: sp->y = tmpy;
259: sp->z = tmpz;
260: sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
261: }
262: for (j = 0; j < sp->dim; ++j) {
263: x = xx[j];
264: y = yy[j];
265: k = sp->loc + j;
266: for (i = 0; i < n; ++i) {
267: if (x[i] > sp->xmax) sp->xmax = x[i];
268: if (x[i] < sp->xmin) sp->xmin = x[i];
269: if (y[i] > sp->ymax) sp->ymax = y[i];
270: if (y[i] < sp->ymin) sp->ymin = y[i];
272: sp->x[k] = x[i];
273: sp->y[k] = y[i];
274: k += sp->dim;
275: }
276: }
277: sp->loc += n * sp->dim;
278: sp->nopts += n;
279: PetscFunctionReturn(PETSC_SUCCESS);
280: }
282: /*@
283: PetscDrawSPAddPointColorized - Adds another point to each of the scatter plots as well as a numeric value to be used to colorize the scatter point.
285: Not collective
287: Input Parameters:
288: + sp - the scatter plot data structure
289: . 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()`
290: - z - array of length dim containing the numeric values that will be mapped to [0,255] and used for scatter point colors.
292: Level: intermediate
294: Note:
295: The new points will not be displayed until a call to `PetscDrawSPDraw()` is made
297: .seealso: `PetscDrawSPAddPoints()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`
298: @*/
299: PetscErrorCode PetscDrawSPAddPointColorized(PetscDrawSP sp, PetscReal *x, PetscReal *y, PetscReal *z)
300: {
301: PetscInt i;
303: PetscFunctionBegin;
305: sp->colorized = PETSC_TRUE;
306: if (sp->loc + sp->dim >= sp->len) { /* allocate more space */
307: PetscReal *tmpx, *tmpy, *tmpz;
308: PetscCall(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));
309: PetscCall(PetscArraycpy(tmpx, sp->x, sp->len));
310: PetscCall(PetscArraycpy(tmpy, sp->y, sp->len));
311: PetscCall(PetscArraycpy(tmpz, sp->z, sp->len));
312: PetscCall(PetscFree3(sp->x, sp->y, sp->z));
313: sp->x = tmpx;
314: sp->y = tmpy;
315: sp->z = tmpz;
316: sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
317: }
318: for (i = 0; i < sp->dim; ++i) {
319: if (x[i] > sp->xmax) sp->xmax = x[i];
320: if (x[i] < sp->xmin) sp->xmin = x[i];
321: if (y[i] > sp->ymax) sp->ymax = y[i];
322: if (y[i] < sp->ymin) sp->ymin = y[i];
323: if (z[i] < sp->zmin) sp->zmin = z[i];
324: if (z[i] > sp->zmax) sp->zmax = z[i];
325: // if (z[i] > sp->zmax && z[i] < 5.) sp->zmax = z[i];
327: sp->x[sp->loc] = x[i];
328: sp->y[sp->loc] = y[i];
329: sp->z[sp->loc++] = z[i];
330: }
331: ++sp->nopts;
332: PetscFunctionReturn(PETSC_SUCCESS);
333: }
335: /*@
336: PetscDrawSPDraw - Redraws a scatter plot.
338: Collective
340: Input Parameters:
341: + sp - the scatter plot context
342: - clear - clear the window before drawing the new plot
344: Level: intermediate
346: .seealso: `PetscDrawLGDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
347: @*/
348: PetscErrorCode PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
349: {
350: PetscDraw draw;
351: PetscBool isnull;
352: PetscMPIInt rank, size;
354: PetscFunctionBegin;
356: draw = sp->win;
357: PetscCall(PetscDrawIsNull(draw, &isnull));
358: if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
359: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sp), &rank));
360: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sp), &size));
362: if (clear) {
363: PetscCall(PetscDrawCheckResizedWindow(draw));
364: PetscCall(PetscDrawClear(draw));
365: }
366: {
367: PetscReal lower[2] = {sp->xmin, sp->ymin}, glower[2];
368: PetscReal upper[2] = {sp->xmax, sp->ymax}, gupper[2];
369: PetscCall(MPIU_Allreduce(lower, glower, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)sp)));
370: PetscCall(MPIU_Allreduce(upper, gupper, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)sp)));
371: PetscCall(PetscDrawAxisSetLimits(sp->axis, glower[0], gupper[0], glower[1], gupper[1]));
372: PetscCall(PetscDrawAxisDraw(sp->axis));
373: }
375: PetscDrawCollectiveBegin(draw);
376: {
377: const int dim = sp->dim, nopts = sp->nopts;
379: for (int i = 0; i < dim; ++i) {
380: for (int p = 0; p < nopts; ++p) {
381: PetscInt color = sp->colorized ? PetscDrawRealToColor(sp->z[p * dim], sp->zmin, sp->zmax) : (size > 1 ? PetscDrawRealToColor(rank, 0, size - 1) : PETSC_DRAW_RED);
383: PetscCall(PetscDrawPoint(draw, sp->x[p * dim + i], sp->y[p * dim + i], color));
384: }
385: }
386: }
387: PetscDrawCollectiveEnd(draw);
389: PetscCall(PetscDrawFlush(draw));
390: PetscCall(PetscDrawPause(draw));
391: PetscFunctionReturn(PETSC_SUCCESS);
392: }
394: /*@
395: PetscDrawSPSave - Saves a drawn image
397: Collective
399: Input Parameter:
400: . sp - the scatter plot context
402: Level: intermediate
404: .seealso: `PetscDrawSPSave()`, `PetscDrawSPCreate()`, `PetscDrawSPGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`
405: @*/
406: PetscErrorCode PetscDrawSPSave(PetscDrawSP sp)
407: {
408: PetscFunctionBegin;
410: PetscCall(PetscDrawSave(sp->win));
411: PetscFunctionReturn(PETSC_SUCCESS);
412: }
414: /*@
415: 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.
417: Not collective
419: Input Parameters:
420: + xsp - the line graph context
421: - x_min,x_max,y_min,y_max - the limits
423: Level: intermediate
425: .seealso: `PetscDrawSP`, `PetscDrawAxis`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPGetAxis()`
426: @*/
427: PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max)
428: {
429: PetscFunctionBegin;
431: sp->xmin = x_min;
432: sp->xmax = x_max;
433: sp->ymin = y_min;
434: sp->ymax = y_max;
435: PetscFunctionReturn(PETSC_SUCCESS);
436: }
438: /*@
439: PetscDrawSPGetAxis - Gets the axis context associated with a scatter plot
441: Not Collective
443: Input Parameter:
444: . sp - the scatter plot context
446: Output Parameter:
447: . axis - the axis context
449: Note:
450: 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.
452: Level: intermediate
454: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawAxis`, `PetscDrawAxisCreate()`
455: @*/
456: PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp, PetscDrawAxis *axis)
457: {
458: PetscFunctionBegin;
461: *axis = sp->axis;
462: PetscFunctionReturn(PETSC_SUCCESS);
463: }
465: /*@
466: PetscDrawSPGetDraw - Gets the draw context associated with a scatter plot
468: Not Collective
470: Input Parameter:
471: . sp - the scatter plot context
473: Output Parameter:
474: . draw - the draw context
476: Level: intermediate
478: .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDraw`
479: @*/
480: PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp, PetscDraw *draw)
481: {
482: PetscFunctionBegin;
485: *draw = sp->win;
486: PetscFunctionReturn(PETSC_SUCCESS);
487: }