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