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