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