xref: /petsc/src/sys/classes/draw/utils/dscatter.c (revision ffa8c5705e8ab2cf85ee1d14dbe507a6e2eb5283)
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 /*@C
13     PetscDrawSPCreate - Creates a scatter plot data structure.
14 
15     Collective on PetscDraw
16 
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
20 
21     Output Parameters:
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    The MPI communicator that owns the PetscDraw owns this PetscDrawSP, but the calls to set options and add points are ignored on all processes except the
32    zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawSPDraw() to display the updated graph.
33 
34 .seealso:  PetscDrawLGCreate(), PetscDrawLG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawHGCreate(), PetscDrawHG, PetscDrawSPDestroy(), PetscDraw, PetscDrawSP, PetscDrawSPSetDimension(), PetscDrawSPReset(),
35            PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw(), PetscDrawSPSave(), PetscDrawSPSetLimits(), PetscDrawSPGetAxis(),PetscDrawAxis, PetscDrawSPGetDraw()
36 @*/
37 PetscErrorCode  PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp)
38 {
39   PetscDrawSP    sp;
40 
41   PetscFunctionBegin;
42   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
43   PetscValidLogicalCollectiveInt(draw,dim,2);
44   PetscValidPointer(drawsp,3);
45 
46   PetscCall(PetscHeaderCreate(sp,PETSC_DRAWSP_CLASSID,"DrawSP","Scatter Plot","Draw",PetscObjectComm((PetscObject)draw),PetscDrawSPDestroy,NULL));
47   PetscCall(PetscLogObjectParent((PetscObject)draw,(PetscObject)sp));
48 
49   PetscCall(PetscObjectReference((PetscObject)draw));
50   sp->win = draw;
51 
52   sp->view      = NULL;
53   sp->destroy   = NULL;
54   sp->nopts     = 0;
55   sp->dim       = dim;
56   sp->xmin      = 1.e20;
57   sp->ymin      = 1.e20;
58   sp->xmax      = -1.e20;
59   sp->ymax      = -1.e20;
60   sp->zmax      = 1.;
61   sp->zmin      = 1.e20;
62   sp->colorized = PETSC_FALSE;
63 
64   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));
65   PetscCall(PetscLogObjectMemory((PetscObject)sp,2*dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal)));
66 
67   sp->len     = dim*PETSC_DRAW_SP_CHUNK_SIZE;
68   sp->loc     = 0;
69 
70   PetscCall(PetscDrawAxisCreate(draw,&sp->axis));
71   PetscCall(PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis));
72 
73   *drawsp = sp;
74   PetscFunctionReturn(0);
75 }
76 
77 /*@
78    PetscDrawSPSetDimension - Change the number of sets of points  that are to be drawn.
79 
80    Logically Collective on PetscDrawSP
81 
82    Input Parameters:
83 +  sp - the line graph context.
84 -  dim - the number of curves.
85 
86    Level: intermediate
87 
88 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints()
89 
90 @*/
91 PetscErrorCode  PetscDrawSPSetDimension(PetscDrawSP sp,int dim)
92 {
93   PetscFunctionBegin;
94   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
95   PetscValidLogicalCollectiveInt(sp,dim,2);
96   if (sp->dim == dim) PetscFunctionReturn(0);
97 
98   PetscCall(PetscFree2(sp->x,sp->y));
99   sp->dim = dim;
100   PetscCall(PetscMalloc2(dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->x,dim*PETSC_DRAW_SP_CHUNK_SIZE,&sp->y));
101   PetscCall(PetscLogObjectMemory((PetscObject)sp,2*dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal)));
102   sp->len = dim*PETSC_DRAW_SP_CHUNK_SIZE;
103   PetscFunctionReturn(0);
104 }
105 
106 /*@
107    PetscDrawSPReset - Clears line graph to allow for reuse with new data.
108 
109    Logically Collective on PetscDrawSP
110 
111    Input Parameter:
112 .  sp - the line graph context.
113 
114    Level: intermediate
115 
116 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw()
117 @*/
118 PetscErrorCode  PetscDrawSPReset(PetscDrawSP sp)
119 {
120   PetscFunctionBegin;
121   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
122   sp->xmin  = 1.e20;
123   sp->ymin  = 1.e20;
124   sp->zmin  = 1.e20;
125   sp->xmax  = -1.e20;
126   sp->ymax  = -1.e20;
127   sp->zmax  = -1.e20;
128   sp->loc   = 0;
129   sp->nopts = 0;
130   PetscFunctionReturn(0);
131 }
132 
133 /*@C
134    PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
135 
136    Collective on PetscDrawSP
137 
138    Input Parameter:
139 .  sp - the line graph context
140 
141    Level: intermediate
142 
143 .seealso:  PetscDrawSPCreate(), PetscDrawSP, PetscDrawSPReset()
144 
145 @*/
146 PetscErrorCode  PetscDrawSPDestroy(PetscDrawSP *sp)
147 {
148   PetscFunctionBegin;
149   if (!*sp) PetscFunctionReturn(0);
150   PetscValidHeaderSpecific(*sp,PETSC_DRAWSP_CLASSID,1);
151   if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);}
152 
153   PetscCall(PetscFree3((*sp)->x,(*sp)->y,(*sp)->z));
154   PetscCall(PetscDrawAxisDestroy(&(*sp)->axis));
155   PetscCall(PetscDrawDestroy(&(*sp)->win));
156   PetscCall(PetscHeaderDestroy(sp));
157   PetscFunctionReturn(0);
158 }
159 
160 /*@
161    PetscDrawSPAddPoint - Adds another point to each of the scatter plots.
162 
163    Logically Collective on PetscDrawSP
164 
165    Input Parameters:
166 +  sp - the scatter plot data structure
167 -  x, y - two arrays of length dim containing the new x and y coordinate values for each of the curves. Here  dim is the number of curves passed to PetscDrawSPCreate()
168 
169    Level: intermediate
170 
171    Notes:
172     the new points will not be displayed until a call to PetscDrawSPDraw() is made
173 
174 .seealso: PetscDrawSPAddPoints(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw(), PetscDrawSPAddPointColorized()
175 
176 @*/
177 PetscErrorCode  PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal *x,PetscReal *y)
178 {
179   PetscInt       i;
180 
181   PetscFunctionBegin;
182   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
183 
184   if (sp->loc+sp->dim >= sp->len) { /* allocate more space */
185     PetscReal *tmpx,*tmpy;
186     PetscCall(PetscMalloc2(sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpx,sp->len+sp->dim*PETSC_DRAW_SP_CHUNK_SIZE,&tmpy));
187     PetscCall(PetscLogObjectMemory((PetscObject)sp,2*sp->dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal)));
188     PetscCall(PetscArraycpy(tmpx,sp->x,sp->len));
189     PetscCall(PetscArraycpy(tmpy,sp->y,sp->len));
190     PetscCall(PetscFree2(sp->x,sp->y));
191     sp->x    = tmpx;
192     sp->y    = tmpy;
193     sp->len += sp->dim*PETSC_DRAW_SP_CHUNK_SIZE;
194   }
195   for (i=0; i<sp->dim; i++) {
196     if (x[i] > sp->xmax) sp->xmax = x[i];
197     if (x[i] < sp->xmin) sp->xmin = x[i];
198     if (y[i] > sp->ymax) sp->ymax = y[i];
199     if (y[i] < sp->ymin) sp->ymin = y[i];
200 
201     sp->x[sp->loc]   = x[i];
202     sp->y[sp->loc++] = y[i];
203   }
204   sp->nopts++;
205   PetscFunctionReturn(0);
206 }
207 
208 /*@C
209    PetscDrawSPAddPoints - Adds several points to each of the scatter plots.
210 
211    Logically Collective on PetscDrawSP
212 
213    Input Parameters:
214 +  sp - the LineGraph data structure
215 .  xx,yy - points to two arrays of pointers that point to arrays
216            containing the new x and y points for each curve.
217 -  n - number of points being added
218 
219    Level: intermediate
220 
221    Notes:
222     the new points will not be displayed until a call to PetscDrawSPDraw() is made
223 
224 .seealso: PetscDrawSPAddPoint(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw(), PetscDrawSPAddPointColorized()
225 @*/
226 PetscErrorCode  PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy)
227 {
228   PetscInt       i,j,k;
229   PetscReal      *x,*y;
230 
231   PetscFunctionBegin;
232   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
233 
234   if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */
235     PetscReal *tmpx,*tmpy;
236     PetscInt  chunk = PETSC_DRAW_SP_CHUNK_SIZE;
237     if (n > chunk) chunk = n;
238     PetscCall(PetscMalloc2(sp->len+sp->dim*chunk,&tmpx,sp->len+sp->dim*chunk,&tmpy));
239     PetscCall(PetscLogObjectMemory((PetscObject)sp,2*sp->dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal)));
240     PetscCall(PetscArraycpy(tmpx,sp->x,sp->len));
241     PetscCall(PetscArraycpy(tmpy,sp->y,sp->len));
242     PetscCall(PetscFree2(sp->x,sp->y));
243 
244     sp->x    = tmpx;
245     sp->y    = tmpy;
246     sp->len += sp->dim*PETSC_DRAW_SP_CHUNK_SIZE;
247   }
248   for (j=0; j<sp->dim; j++) {
249     x = xx[j]; y = yy[j];
250     k = sp->loc + j;
251     for (i=0; i<n; i++) {
252       if (x[i] > sp->xmax) sp->xmax = x[i];
253       if (x[i] < sp->xmin) sp->xmin = x[i];
254       if (y[i] > sp->ymax) sp->ymax = y[i];
255       if (y[i] < sp->ymin) sp->ymin = y[i];
256 
257       sp->x[k] = x[i];
258       sp->y[k] = y[i];
259       k       += sp->dim;
260     }
261   }
262   sp->loc   += n*sp->dim;
263   sp->nopts += n;
264   PetscFunctionReturn(0);
265 }
266 
267 /*@
268    PetscDrawSPAddPointColorized - Adds another point to each of the scatter plots as well as a numeric value to be used to colorize the scatter point.
269 
270    Logically Collective on PetscDrawSP
271 
272    Input Parameters:
273 +  sp - the scatter plot data structure
274 . x, y - two arrays of length dim containing the new x and y coordinate values for each of the curves. Here  dim is the number of curves passed to PetscDrawSPCreate()
275 - z - array of length dim containing the numeric values that will be mapped to [0,255] and used for scatter point colors.
276 
277    Level: intermediate
278 
279    Notes:
280     the new points will not be displayed until a call to PetscDrawSPDraw() is made
281 
282 .seealso: PetscDrawSPAddPoints(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw(), PetscDrawSPAddPoint()
283 
284 @*/
285 PetscErrorCode  PetscDrawSPAddPointColorized(PetscDrawSP sp,PetscReal *x,PetscReal *y,PetscReal *z)
286 {
287   PetscInt       i;
288 
289   PetscFunctionBegin;
290   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
291   sp->colorized = PETSC_TRUE;
292   if (sp->loc+sp->dim >= sp->len) { /* allocate more space */
293     PetscReal *tmpx,*tmpy,*tmpz;
294     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));
295     PetscCall(PetscLogObjectMemory((PetscObject)sp,2*sp->dim*PETSC_DRAW_SP_CHUNK_SIZE*sizeof(PetscReal)));
296     PetscCall(PetscArraycpy(tmpx,sp->x,sp->len));
297     PetscCall(PetscArraycpy(tmpy,sp->y,sp->len));
298     PetscCall(PetscArraycpy(tmpz,sp->z,sp->len));
299     PetscCall(PetscFree3(sp->x,sp->y,sp->z));
300     sp->x    = tmpx;
301     sp->y    = tmpy;
302     sp->z    = tmpz;
303     sp->len += sp->dim*PETSC_DRAW_SP_CHUNK_SIZE;
304   }
305   for (i=0; i<sp->dim; i++) {
306     if (x[i] > sp->xmax) sp->xmax = x[i];
307     if (x[i] < sp->xmin) sp->xmin = x[i];
308     if (y[i] > sp->ymax) sp->ymax = y[i];
309     if (y[i] < sp->ymin) sp->ymin = y[i];
310     if (z[i] < sp->zmin) sp->zmin = z[i];
311     if (z[i] > sp->zmax) sp->zmax = z[i];
312     // if (z[i] > sp->zmax && z[i] < 5.) sp->zmax = z[i];
313 
314     sp->x[sp->loc]   = x[i];
315     sp->y[sp->loc]   = y[i];
316     sp->z[sp->loc++] = z[i];
317   }
318   sp->nopts++;
319   PetscFunctionReturn(0);
320 }
321 
322 /*@
323    PetscDrawSPDraw - Redraws a scatter plot.
324 
325    Collective on PetscDrawSP
326 
327    Input Parameters:
328 +  sp - the line graph context
329 -  clear - clear the window before drawing the new plot
330 
331    Level: intermediate
332 
333 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints()
334 
335 @*/
336 PetscErrorCode  PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
337 {
338   PetscReal      xmin,xmax,ymin,ymax;
339   PetscMPIInt    rank;
340   PetscInt       color;
341   PetscBool      isnull;
342   PetscDraw      draw;
343   PetscErrorCode ierr;
344 
345   PetscFunctionBegin;
346   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
347   PetscCall(PetscDrawIsNull(sp->win,&isnull));
348   if (isnull) PetscFunctionReturn(0);
349   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank));
350 
351   if (sp->xmin > sp->xmax || sp->ymin > sp->ymax) PetscFunctionReturn(0);
352   if (sp->nopts < 1) PetscFunctionReturn(0);
353 
354   draw = sp->win;
355   if (clear) {
356     PetscCall(PetscDrawCheckResizedWindow(draw));
357     PetscCall(PetscDrawClear(draw));
358   }
359 
360   xmin = sp->xmin; xmax = sp->xmax; ymin = sp->ymin; ymax = sp->ymax;
361   PetscCall(PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax));
362   PetscCall(PetscDrawAxisDraw(sp->axis));
363 
364   ierr = PetscDrawCollectiveBegin(draw);PetscCall(ierr);
365   if (rank == 0) {
366     int i,j,dim=sp->dim,nopts=sp->nopts;
367     for (i=0; i<dim; i++) {
368       for (j=0; j<nopts; j++) {
369         if (sp->colorized) {
370           color = PetscDrawRealToColor(sp->z[j*dim],sp->zmin,sp->zmax);
371           PetscCall(PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],color));
372         } else {
373           PetscCall(PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED));
374         }
375       }
376     }
377   }
378   ierr = PetscDrawCollectiveEnd(draw);PetscCall(ierr);
379 
380   PetscCall(PetscDrawFlush(draw));
381   PetscCall(PetscDrawPause(draw));
382   PetscFunctionReturn(0);
383 }
384 
385 /*@
386    PetscDrawSPSave - Saves a drawn image
387 
388    Collective on PetscDrawSP
389 
390    Input Parameter:
391 .  sp - the scatter plot context
392 
393    Level: intermediate
394 
395 .seealso:  PetscDrawSPCreate(), PetscDrawSPGetDraw(), PetscDrawSetSave(), PetscDrawSave()
396 @*/
397 PetscErrorCode  PetscDrawSPSave(PetscDrawSP sp)
398 {
399   PetscFunctionBegin;
400   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
401   PetscCall(PetscDrawSave(sp->win));
402   PetscFunctionReturn(0);
403 }
404 
405 /*@
406    PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more
407    points are added after this call, the limits will be adjusted to
408    include those additional points.
409 
410    Logically Collective on PetscDrawSP
411 
412    Input Parameters:
413 +  xsp - the line graph context
414 -  x_min,x_max,y_min,y_max - the limits
415 
416    Level: intermediate
417 
418 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPGetAxis()
419 @*/
420 PetscErrorCode  PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
421 {
422   PetscFunctionBegin;
423   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
424   sp->xmin = x_min;
425   sp->xmax = x_max;
426   sp->ymin = y_min;
427   sp->ymax = y_max;
428   PetscFunctionReturn(0);
429 }
430 
431 /*@C
432    PetscDrawSPGetAxis - Gets the axis context associated with a line graph.
433    This is useful if one wants to change some axis property, such as
434    labels, color, etc. The axis context should not be destroyed by the
435    application code.
436 
437    Not Collective, if PetscDrawSP is parallel then PetscDrawAxis is parallel
438 
439    Input Parameter:
440 .  sp - the line graph context
441 
442    Output Parameter:
443 .  axis - the axis context
444 
445    Level: intermediate
446 
447 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawAxis, PetscDrawAxisCreate()
448 
449 @*/
450 PetscErrorCode  PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis)
451 {
452   PetscFunctionBegin;
453   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
454   PetscValidPointer(axis,2);
455   *axis = sp->axis;
456   PetscFunctionReturn(0);
457 }
458 
459 /*@C
460    PetscDrawSPGetDraw - Gets the draw context associated with a line graph.
461 
462    Not Collective, PetscDraw is parallel if PetscDrawSP is parallel
463 
464    Input Parameter:
465 .  sp - the line graph context
466 
467    Output Parameter:
468 .  draw - the draw context
469 
470    Level: intermediate
471 
472 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDraw
473 @*/
474 PetscErrorCode  PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw)
475 {
476   PetscFunctionBegin;
477   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
478   PetscValidPointer(draw,2);
479   *draw = sp->win;
480   PetscFunctionReturn(0);
481 }
482