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