xref: /petsc/src/sys/classes/draw/utils/dscatter.c (revision 00d931fe9835bef04c3bcd2a9a1bf118d64cc4c2)
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 over 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    Concepts: scatter plot^creating
43 
44 .seealso:  PetscDrawSPDestroy()
45 @*/
46 PetscErrorCode  PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp)
47 {
48   PetscBool      isnull;
49   PetscDrawSP    sp;
50   PetscErrorCode ierr;
51 
52   PetscFunctionBegin;
53   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
54   PetscValidLogicalCollectiveInt(draw,dim,2);
55   PetscValidPointer(drawsp,3);
56 
57   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
58   if (isnull) {*drawsp = NULL; PetscFunctionReturn(0);}
59 
60   ierr = PetscHeaderCreate(sp,PETSC_DRAWSP_CLASSID,"PetscDrawSP","Scatter plot","Draw",PetscObjectComm((PetscObject)draw),PetscDrawSPDestroy,NULL);CHKERRQ(ierr);
61   ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)sp);CHKERRQ(ierr);
62 
63   ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr);
64   sp->win = draw;
65 
66   sp->view    = NULL;
67   sp->destroy = NULL;
68   sp->nopts   = 0;
69   sp->dim     = dim;
70   sp->xmin    = 1.e20;
71   sp->ymin    = 1.e20;
72   sp->xmax    = -1.e20;
73   sp->ymax    = -1.e20;
74 
75   ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr);
76   ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
77 
78   sp->len     = dim*CHUNCKSIZE;
79   sp->loc     = 0;
80 
81   ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr);
82   ierr = PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis);CHKERRQ(ierr);
83 
84   *drawsp = sp;
85   PetscFunctionReturn(0);
86 }
87 
88 #undef __FUNCT__
89 #define __FUNCT__ "PetscDrawSPSetDimension"
90 /*@
91    PetscDrawSPSetDimension - Change the number of sets of points  that are to be drawn.
92 
93    Logically Collective over 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 @*/
104 PetscErrorCode  PetscDrawSPSetDimension(PetscDrawSP sp,int dim)
105 {
106   PetscErrorCode ierr;
107 
108   PetscFunctionBegin;
109   if (!sp) PetscFunctionReturn(0);
110   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
111   PetscValidLogicalCollectiveInt(sp,dim,2);
112   if (sp->dim == dim) PetscFunctionReturn(0);
113 
114   ierr    = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
115   sp->dim = dim;
116   ierr    = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr);
117   ierr    = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
118   sp->len = dim*CHUNCKSIZE;
119   PetscFunctionReturn(0);
120 }
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "PetscDrawSPReset"
124 /*@
125    PetscDrawSPReset - Clears line graph to allow for reuse with new data.
126 
127    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
128 
129    Input Parameter:
130 .  sp - the line graph context.
131 
132    Level: intermediate
133 
134   Concepts: scatter plot^resetting
135 
136 @*/
137 PetscErrorCode  PetscDrawSPReset(PetscDrawSP sp)
138 {
139   PetscFunctionBegin;
140   if (!sp) PetscFunctionReturn(0);
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 #undef __FUNCT__
152 #define __FUNCT__ "PetscDrawSPDestroy"
153 /*@C
154    PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
155 
156    Collective over PetscDrawSP
157 
158    Input Parameter:
159 .  sp - the line graph context
160 
161    Level: intermediate
162 
163 .seealso:  PetscDrawSPCreate()
164 @*/
165 PetscErrorCode  PetscDrawSPDestroy(PetscDrawSP *sp)
166 {
167   PetscErrorCode ierr;
168 
169   PetscFunctionBegin;
170   if (!*sp) PetscFunctionReturn(0);
171   PetscValidHeaderSpecific(*sp,PETSC_DRAWSP_CLASSID,1);
172   if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);}
173 
174   ierr = PetscFree2((*sp)->x,(*sp)->y);CHKERRQ(ierr);
175   ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr);
176   ierr = PetscDrawDestroy(&(*sp)->win);CHKERRQ(ierr);
177   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
178   PetscFunctionReturn(0);
179 }
180 
181 #undef __FUNCT__
182 #define __FUNCT__ "PetscDrawSPAddPoint"
183 /*@
184    PetscDrawSPAddPoint - Adds another point to each of the scatter plots.
185 
186    Logically Collective over PetscDrawSP
187 
188    Input Parameters:
189 +  sp - the scatter plot data structure
190 -  x, y - the points to two vectors containing the new x and y
191           point for each curve.
192 
193    Level: intermediate
194 
195    Concepts: scatter plot^adding points
196 
197 .seealso: PetscDrawSPAddPoints()
198 @*/
199 PetscErrorCode  PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal *x,PetscReal *y)
200 {
201   PetscErrorCode ierr;
202   PetscInt       i;
203 
204   PetscFunctionBegin;
205   if (!sp) PetscFunctionReturn(0);
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 #undef __FUNCT__
234 #define __FUNCT__ "PetscDrawSPAddPoints"
235 /*@C
236    PetscDrawSPAddPoints - Adds several points to each of the scatter plots.
237 
238    Logically Collective over PetscDrawSP
239 
240    Input Parameters:
241 +  sp - the LineGraph data structure
242 .  xx,yy - points to two arrays of pointers that point to arrays
243            containing the new x and y points for each curve.
244 -  n - number of points being added
245 
246    Level: intermediate
247 
248    Concepts: scatter plot^adding points
249 
250 .seealso: PetscDrawSPAddPoint()
251 @*/
252 PetscErrorCode  PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy)
253 {
254   PetscErrorCode ierr;
255   PetscInt       i,j,k;
256   PetscReal      *x,*y;
257 
258   PetscFunctionBegin;
259   if (!sp) PetscFunctionReturn(0);
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 #undef __FUNCT__
296 #define __FUNCT__ "PetscDrawSPDraw"
297 /*@
298    PetscDrawSPDraw - Redraws a scatter plot.
299 
300    Collective, but ignored by all processors except processor 0 in PetscDrawSP
301 
302    Input Parameter:
303 +  sp - the line graph context
304 -  clear - clear the window before drawing the new plot
305 
306    Level: intermediate
307 
308 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw()
309 
310 @*/
311 PetscErrorCode  PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
312 {
313   PetscReal      xmin,xmax,ymin,ymax;
314   PetscErrorCode ierr;
315   PetscMPIInt    rank;
316   PetscBool      isnull;
317   PetscDraw      draw;
318 
319   PetscFunctionBegin;
320   if (!sp) PetscFunctionReturn(0);
321   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
322 
323   draw = sp->win;
324   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
325   if (isnull) PetscFunctionReturn(0);
326   if (sp->xmin > sp->xmax || sp->ymin > sp->ymax) PetscFunctionReturn(0);
327   if (sp->nopts < 1) PetscFunctionReturn(0);
328   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRQ(ierr);
329 
330   if (clear) {
331     ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
332     ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);
333   }
334   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
335 
336   xmin = sp->xmin; xmax = sp->xmax; ymin = sp->ymin; ymax = sp->ymax;
337   ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
338   ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr);
339 
340   if (!rank) {
341     int i,j,dim=sp->dim,nopts=sp->nopts;
342     for (i=0; i<dim; i++) {
343       for (j=0; j<nopts; j++) {
344         ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr);
345       }
346     }
347   }
348 
349   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
350   ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
351   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
352   PetscFunctionReturn(0);
353 }
354 
355 #undef __FUNCT__
356 #define __FUNCT__ "PetscDrawSPSetLimits"
357 /*@
358    PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more
359    points are added after this call, the limits will be adjusted to
360    include those additional points.
361 
362    Logically Collective over PetscDrawSP
363 
364    Input Parameters:
365 +  xsp - the line graph context
366 -  x_min,x_max,y_min,y_max - the limits
367 
368    Level: intermediate
369 
370    Concepts: scatter plot^setting axis
371 
372 @*/
373 PetscErrorCode  PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
374 {
375   PetscFunctionBegin;
376   if (!sp) PetscFunctionReturn(0);
377   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
378   sp->xmin = x_min;
379   sp->xmax = x_max;
380   sp->ymin = y_min;
381   sp->ymax = y_max;
382   PetscFunctionReturn(0);
383 }
384 
385 #undef __FUNCT__
386 #define __FUNCT__ "PetscDrawSPGetAxis"
387 /*@C
388    PetscDrawSPGetAxis - Gets the axis context associated with a line graph.
389    This is useful if one wants to change some axis property, such as
390    labels, color, etc. The axis context should not be destroyed by the
391    application code.
392 
393    Not Collective, if PetscDrawSP is parallel then PetscDrawAxis is parallel
394 
395    Input Parameter:
396 .  sp - the line graph context
397 
398    Output Parameter:
399 .  axis - the axis context
400 
401    Level: intermediate
402 
403 @*/
404 PetscErrorCode  PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis)
405 {
406   PetscFunctionBegin;
407   PetscValidPointer(axis,2);
408   if (!sp) {*axis = NULL; PetscFunctionReturn(0);}
409   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
410   *axis = sp->axis;
411   PetscFunctionReturn(0);
412 }
413 
414 #undef __FUNCT__
415 #define __FUNCT__ "PetscDrawSPGetDraw"
416 /*@C
417    PetscDrawSPGetDraw - Gets the draw context associated with a line graph.
418 
419    Not Collective, PetscDraw is parallel if PetscDrawSP is parallel
420 
421    Input Parameter:
422 .  sp - the line graph context
423 
424    Output Parameter:
425 .  draw - the draw context
426 
427    Level: intermediate
428 
429 @*/
430 PetscErrorCode  PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw)
431 {
432   PetscFunctionBegin;
433   PetscValidPointer(draw,2);
434   if (!sp) {*draw = NULL; PetscFunctionReturn(0);}
435   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
436   *draw = sp->win;
437   PetscFunctionReturn(0);
438 }
439