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 */
6
7 #include <petscdraw.h> /*I "petscdraw.h" I*/
8 #include <petsc/private/drawimpl.h> /*I "petscsys.h" I*/
9
10 PetscClassId PETSC_DRAWSP_CLASSID = 0;
11
12 /*@
13 PetscDrawSPCreate - Creates a scatter plot data structure.
14
15 Collective
16
17 Input Parameters:
18 + draw - the window where the graph will be made.
19 - dim - the number of sets of points which will be drawn
20
21 Output Parameter:
22 . drawsp - the scatter plot context
23
24 Level: intermediate
25
26 Notes:
27 Add points to the plot with `PetscDrawSPAddPoint()` or `PetscDrawSPAddPoints()`; the new points are not displayed until `PetscDrawSPDraw()` is called.
28
29 `PetscDrawSPReset()` removes all the points that have been added
30
31 `PetscDrawSPSetDimension()` determines how many point curves are being plotted.
32
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.
34
35 .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawSPDestroy()`, `PetscDraw`, `PetscDrawSP`, `PetscDrawSPSetDimension()`, `PetscDrawSPReset()`,
36 `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPDraw()`, `PetscDrawSPSave()`, `PetscDrawSPSetLimits()`, `PetscDrawSPGetAxis()`, `PetscDrawAxis`, `PetscDrawSPGetDraw()`
37 @*/
PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP * drawsp)38 PetscErrorCode PetscDrawSPCreate(PetscDraw draw, int dim, PetscDrawSP *drawsp)
39 {
40 PetscDrawSP sp;
41
42 PetscFunctionBegin;
43 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
44 PetscAssertPointer(drawsp, 3);
45
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 = (PetscReal)1.e20;
54 sp->ymin = (PetscReal)1.e20;
55 sp->zmin = (PetscReal)1.e20;
56 sp->xmax = (PetscReal)-1.e20;
57 sp->ymax = (PetscReal)-1.e20;
58 sp->zmax = (PetscReal)-1.e20;
59 sp->colorized = PETSC_FALSE;
60 sp->loc = 0;
61
62 PetscCall(PetscDrawSPSetDimension(sp, dim));
63 PetscCall(PetscDrawAxisCreate(draw, &sp->axis));
64
65 *drawsp = sp;
66 PetscFunctionReturn(PETSC_SUCCESS);
67 }
68
69 /*@
70 PetscDrawSPSetDimension - Change the number of points that are added at each `PetscDrawSPAddPoint()`
71
72 Not Collective
73
74 Input Parameters:
75 + sp - the scatter plot context.
76 - dim - the number of point curves on this process
77
78 Level: intermediate
79
80 .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
81 @*/
PetscDrawSPSetDimension(PetscDrawSP sp,int dim)82 PetscErrorCode PetscDrawSPSetDimension(PetscDrawSP sp, int dim)
83 {
84 PetscFunctionBegin;
85 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
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 }
93
94 /*@
95 PetscDrawSPGetDimension - Get the number of sets of points that are to be drawn at each `PetscDrawSPAddPoint()`
96
97 Not Collective
98
99 Input Parameter:
100 . sp - the scatter plot context.
101
102 Output Parameter:
103 . dim - the number of point curves on this process
104
105 Level: intermediate
106
107 .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
108 @*/
PetscDrawSPGetDimension(PetscDrawSP sp,int * dim)109 PetscErrorCode PetscDrawSPGetDimension(PetscDrawSP sp, int *dim)
110 {
111 PetscFunctionBegin;
112 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
113 PetscAssertPointer(dim, 2);
114 *dim = sp->dim;
115 PetscFunctionReturn(PETSC_SUCCESS);
116 }
117
118 /*@
119 PetscDrawSPReset - Clears scatter plot to allow for reuse with new data.
120
121 Not Collective
122
123 Input Parameter:
124 . sp - the scatter plot context.
125
126 Level: intermediate
127
128 .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPDraw()`
129 @*/
PetscDrawSPReset(PetscDrawSP sp)130 PetscErrorCode PetscDrawSPReset(PetscDrawSP sp)
131 {
132 PetscFunctionBegin;
133 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
134 sp->xmin = (PetscReal)1.e20;
135 sp->ymin = (PetscReal)1.e20;
136 sp->zmin = (PetscReal)1.e20;
137 sp->xmax = (PetscReal)-1.e20;
138 sp->ymax = (PetscReal)-1.e20;
139 sp->zmax = (PetscReal)-1.e20;
140 sp->loc = 0;
141 sp->nopts = 0;
142 PetscFunctionReturn(PETSC_SUCCESS);
143 }
144
145 /*@
146 PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
147
148 Collective
149
150 Input Parameter:
151 . sp - the scatter plot context
152
153 Level: intermediate
154
155 .seealso: `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawSPReset()`
156 @*/
PetscDrawSPDestroy(PetscDrawSP * sp)157 PetscErrorCode PetscDrawSPDestroy(PetscDrawSP *sp)
158 {
159 PetscFunctionBegin;
160 if (!*sp) PetscFunctionReturn(PETSC_SUCCESS);
161 PetscValidHeaderSpecific(*sp, PETSC_DRAWSP_CLASSID, 1);
162 if (--((PetscObject)*sp)->refct > 0) {
163 *sp = NULL;
164 PetscFunctionReturn(PETSC_SUCCESS);
165 }
166
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 }
173
174 /*@
175 PetscDrawSPAddPoint - Adds another point to each of the scatter plot point curves.
176
177 Not Collective
178
179 Input Parameters:
180 + sp - the scatter plot data structure
181 . x - the x coordinate values (of length dim) for the points of the curve
182 - y - the y coordinate values (of length dim) for the points of the curve
183
184 Level: intermediate
185
186 Note:
187 Here dim is the number of point curves passed to `PetscDrawSPCreate()`. The new points will
188 not be displayed until a call to `PetscDrawSPDraw()` is made.
189
190 .seealso: `PetscDrawSPAddPoints()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPointColorized()`
191 @*/
PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal * x,PetscReal * y)192 PetscErrorCode PetscDrawSPAddPoint(PetscDrawSP sp, PetscReal *x, PetscReal *y)
193 {
194 PetscInt i;
195
196 PetscFunctionBegin;
197 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
198
199 if (sp->loc + sp->dim >= sp->len) { /* allocate more space */
200 PetscReal *tmpx, *tmpy, *tmpz;
201 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));
202 PetscCall(PetscArraycpy(tmpx, sp->x, sp->len));
203 PetscCall(PetscArraycpy(tmpy, sp->y, sp->len));
204 PetscCall(PetscArraycpy(tmpz, sp->z, sp->len));
205 PetscCall(PetscFree3(sp->x, sp->y, sp->z));
206 sp->x = tmpx;
207 sp->y = tmpy;
208 sp->z = tmpz;
209 sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
210 }
211 for (i = 0; i < sp->dim; ++i) {
212 if (x[i] > sp->xmax) sp->xmax = x[i];
213 if (x[i] < sp->xmin) sp->xmin = x[i];
214 if (y[i] > sp->ymax) sp->ymax = y[i];
215 if (y[i] < sp->ymin) sp->ymin = y[i];
216
217 sp->x[sp->loc] = x[i];
218 sp->y[sp->loc++] = y[i];
219 }
220 ++sp->nopts;
221 PetscFunctionReturn(PETSC_SUCCESS);
222 }
223
224 /*@C
225 PetscDrawSPAddPoints - Adds several points to each of the scatter plot point curves.
226
227 Not Collective
228
229 Input Parameters:
230 + sp - the scatter plot context
231 . xx - array of pointers that point to arrays containing the new x coordinates for each curve.
232 . yy - array of pointers that point to arrays containing the new y points for each curve.
233 - n - number of points being added, each represents a subarray of length dim where dim is the value from `PetscDrawSPGetDimension()`
234
235 Level: intermediate
236
237 Note:
238 The new points will not be displayed until a call to `PetscDrawSPDraw()` is made
239
240 .seealso: `PetscDrawSPAddPoint()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPointColorized()`
241 @*/
PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal * xx[],PetscReal * yy[])242 PetscErrorCode PetscDrawSPAddPoints(PetscDrawSP sp, int n, PetscReal *xx[], PetscReal *yy[])
243 {
244 PetscInt i, j, k;
245 PetscReal *x, *y;
246
247 PetscFunctionBegin;
248 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
249
250 if (sp->loc + n * sp->dim >= sp->len) { /* allocate more space */
251 PetscReal *tmpx, *tmpy, *tmpz;
252 PetscInt chunk = PETSC_DRAW_SP_CHUNK_SIZE;
253 if (n > chunk) chunk = n;
254 PetscCall(PetscMalloc3(sp->len + sp->dim * chunk, &tmpx, sp->len + sp->dim * chunk, &tmpy, sp->len + sp->dim * chunk, &tmpz));
255 PetscCall(PetscArraycpy(tmpx, sp->x, sp->len));
256 PetscCall(PetscArraycpy(tmpy, sp->y, sp->len));
257 PetscCall(PetscArraycpy(tmpz, sp->z, sp->len));
258 PetscCall(PetscFree3(sp->x, sp->y, sp->z));
259
260 sp->x = tmpx;
261 sp->y = tmpy;
262 sp->z = tmpz;
263 sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
264 }
265 for (j = 0; j < sp->dim; ++j) {
266 x = xx[j];
267 y = yy[j];
268 k = sp->loc + j;
269 for (i = 0; i < n; ++i) {
270 if (x[i] > sp->xmax) sp->xmax = x[i];
271 if (x[i] < sp->xmin) sp->xmin = x[i];
272 if (y[i] > sp->ymax) sp->ymax = y[i];
273 if (y[i] < sp->ymin) sp->ymin = y[i];
274
275 sp->x[k] = x[i];
276 sp->y[k] = y[i];
277 k += sp->dim;
278 }
279 }
280 sp->loc += n * sp->dim;
281 sp->nopts += n;
282 PetscFunctionReturn(PETSC_SUCCESS);
283 }
284
285 /*@
286 PetscDrawSPAddPointColorized - Adds another point to each of the scatter plots as well as a numeric value to be used to colorize the scatter point.
287
288 Not Collective
289
290 Input Parameters:
291 + sp - the scatter plot data structure
292 . x - array of length dim containing the new x coordinate values for each of the point curves.
293 . y - array of length dim containing the new y coordinate values for each of the point curves.
294 - z - array of length dim containing the numeric values that will be mapped to [0,255] and used for scatter point colors.
295
296 Level: intermediate
297
298 Note:
299 The dimensions of the arrays is the number of point curves passed to `PetscDrawSPCreate()`.
300 The new points will not be displayed until a call to `PetscDrawSPDraw()` is made
301
302 .seealso: `PetscDrawSPAddPoints()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`
303 @*/
PetscDrawSPAddPointColorized(PetscDrawSP sp,PetscReal * x,PetscReal * y,PetscReal * z)304 PetscErrorCode PetscDrawSPAddPointColorized(PetscDrawSP sp, PetscReal *x, PetscReal *y, PetscReal *z)
305 {
306 PetscInt i;
307
308 PetscFunctionBegin;
309 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
310 sp->colorized = PETSC_TRUE;
311 if (sp->loc + sp->dim >= sp->len) { /* allocate more space */
312 PetscReal *tmpx, *tmpy, *tmpz;
313 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));
314 PetscCall(PetscArraycpy(tmpx, sp->x, sp->len));
315 PetscCall(PetscArraycpy(tmpy, sp->y, sp->len));
316 PetscCall(PetscArraycpy(tmpz, sp->z, sp->len));
317 PetscCall(PetscFree3(sp->x, sp->y, sp->z));
318 sp->x = tmpx;
319 sp->y = tmpy;
320 sp->z = tmpz;
321 sp->len += sp->dim * PETSC_DRAW_SP_CHUNK_SIZE;
322 }
323 for (i = 0; i < sp->dim; ++i) {
324 if (x[i] > sp->xmax) sp->xmax = x[i];
325 if (x[i] < sp->xmin) sp->xmin = x[i];
326 if (y[i] > sp->ymax) sp->ymax = y[i];
327 if (y[i] < sp->ymin) sp->ymin = y[i];
328 if (z[i] < sp->zmin) sp->zmin = z[i];
329 if (z[i] > sp->zmax) sp->zmax = z[i];
330 // if (z[i] > sp->zmax && z[i] < 5.) sp->zmax = z[i];
331
332 sp->x[sp->loc] = x[i];
333 sp->y[sp->loc] = y[i];
334 sp->z[sp->loc++] = z[i];
335 }
336 ++sp->nopts;
337 PetscFunctionReturn(PETSC_SUCCESS);
338 }
339
340 /*@
341 PetscDrawSPDraw - Redraws a scatter plot.
342
343 Collective
344
345 Input Parameters:
346 + sp - the scatter plot context
347 - clear - clear the window before drawing the new plot
348
349 Level: intermediate
350
351 .seealso: `PetscDrawLGDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPReset()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`
352 @*/
PetscDrawSPDraw(PetscDrawSP sp,PetscBool clear)353 PetscErrorCode PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
354 {
355 PetscDraw draw;
356 PetscBool isnull;
357 PetscMPIInt rank, size;
358
359 PetscFunctionBegin;
360 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
361 draw = sp->win;
362 PetscCall(PetscDrawIsNull(draw, &isnull));
363 if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
364 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sp), &rank));
365 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sp), &size));
366
367 if (clear) {
368 PetscCall(PetscDrawCheckResizedWindow(draw));
369 PetscCall(PetscDrawClear(draw));
370 }
371 {
372 PetscReal lower[2] = {sp->xmin, sp->ymin}, glower[2];
373 PetscReal upper[2] = {sp->xmax, sp->ymax}, gupper[2];
374 PetscCallMPI(MPIU_Allreduce(lower, glower, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)sp)));
375 PetscCallMPI(MPIU_Allreduce(upper, gupper, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)sp)));
376 PetscCall(PetscDrawAxisSetLimits(sp->axis, glower[0], gupper[0], glower[1], gupper[1]));
377 PetscCall(PetscDrawAxisDraw(sp->axis));
378 }
379
380 PetscDrawCollectiveBegin(draw);
381 {
382 const int dim = sp->dim, nopts = sp->nopts;
383
384 for (int i = 0; i < dim; ++i) {
385 for (int p = 0; p < nopts; ++p) {
386 int color = sp->colorized ? PetscDrawRealToColor(sp->z[p * dim], sp->zmin, sp->zmax) : (size > 1 ? PetscDrawRealToColor(rank, 0, size - 1) : PETSC_DRAW_RED);
387
388 PetscCall(PetscDrawPoint(draw, sp->x[p * dim + i], sp->y[p * dim + i], color));
389 }
390 }
391 }
392 PetscDrawCollectiveEnd(draw);
393
394 PetscCall(PetscDrawFlush(draw));
395 PetscCall(PetscDrawPause(draw));
396 PetscFunctionReturn(PETSC_SUCCESS);
397 }
398
399 /*@
400 PetscDrawSPSave - Saves a drawn image
401
402 Collective
403
404 Input Parameter:
405 . sp - the scatter plot context
406
407 Level: intermediate
408
409 .seealso: `PetscDrawSPCreate()`, `PetscDrawSPGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()`
410 @*/
PetscDrawSPSave(PetscDrawSP sp)411 PetscErrorCode PetscDrawSPSave(PetscDrawSP sp)
412 {
413 PetscFunctionBegin;
414 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
415 PetscCall(PetscDrawSave(sp->win));
416 PetscFunctionReturn(PETSC_SUCCESS);
417 }
418
419 /*@
420 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.
421
422 Not Collective
423
424 Input Parameters:
425 + sp - the line graph context
426 . x_min - the horizontal lower limit
427 . x_max - the horizontal upper limit
428 . y_min - the vertical lower limit
429 - y_max - the vertical upper limit
430
431 Level: intermediate
432
433 .seealso: `PetscDrawSP`, `PetscDrawAxis`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawSPGetAxis()`
434 @*/
PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)435 PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max)
436 {
437 PetscFunctionBegin;
438 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
439 sp->xmin = x_min;
440 sp->xmax = x_max;
441 sp->ymin = y_min;
442 sp->ymax = y_max;
443 PetscFunctionReturn(PETSC_SUCCESS);
444 }
445
446 /*@
447 PetscDrawSPGetAxis - Gets the axis context associated with a scatter plot
448
449 Not Collective
450
451 Input Parameter:
452 . sp - the scatter plot context
453
454 Output Parameter:
455 . axis - the axis context
456
457 Level: intermediate
458
459 Note:
460 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.
461
462 .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDrawSPAddPoint()`, `PetscDrawSPAddPoints()`, `PetscDrawAxis`, `PetscDrawAxisCreate()`
463 @*/
PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis * axis)464 PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp, PetscDrawAxis *axis)
465 {
466 PetscFunctionBegin;
467 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
468 PetscAssertPointer(axis, 2);
469 *axis = sp->axis;
470 PetscFunctionReturn(PETSC_SUCCESS);
471 }
472
473 /*@
474 PetscDrawSPGetDraw - Gets the draw context associated with a scatter plot
475
476 Not Collective
477
478 Input Parameter:
479 . sp - the scatter plot context
480
481 Output Parameter:
482 . draw - the draw context
483
484 Level: intermediate
485
486 .seealso: `PetscDrawSP`, `PetscDrawSPCreate()`, `PetscDrawSPDraw()`, `PetscDraw`
487 @*/
PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw * draw)488 PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp, PetscDraw *draw)
489 {
490 PetscFunctionBegin;
491 PetscValidHeaderSpecific(sp, PETSC_DRAWSP_CLASSID, 1);
492 PetscAssertPointer(draw, 2);
493 *draw = sp->win;
494 PetscFunctionReturn(PETSC_SUCCESS);
495 }
496