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