xref: /petsc/src/sys/classes/draw/utils/dscatter.c (revision af0996ce37bc06907c37d8d91773840993d61e62)
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   PetscErrorCode ierr;
49   PetscBool      isnull;
50   PetscObject    obj = (PetscObject)draw;
51   PetscDrawSP    sp;
52 
53   PetscFunctionBegin;
54   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
55   PetscValidPointer(drawsp,3);
56   ierr = PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);CHKERRQ(ierr);
57   if (isnull) {
58     ierr = PetscDrawOpenNull(PetscObjectComm((PetscObject)obj),(PetscDraw*)drawsp);CHKERRQ(ierr);
59     PetscFunctionReturn(0);
60   }
61   ierr = PetscHeaderCreate(sp,_p_PetscDrawSP,int,PETSC_DRAWSP_CLASSID,"PetscDrawSP","Scatter plot","Draw",PetscObjectComm((PetscObject)obj),PetscDrawSPDestroy,0);CHKERRQ(ierr);
62 
63   sp->view    = 0;
64   sp->destroy = 0;
65   sp->nopts   = 0;
66   sp->win     = draw;
67   sp->dim     = dim;
68   sp->xmin    = 1.e20;
69   sp->ymin    = 1.e20;
70   sp->xmax    = -1.e20;
71   sp->ymax    = -1.e20;
72 
73   ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr);
74   ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
75 
76   sp->len     = dim*CHUNCKSIZE;
77   sp->loc     = 0;
78 
79   ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr);
80   ierr = PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis);CHKERRQ(ierr);
81 
82   *drawsp = sp;
83   PetscFunctionReturn(0);
84 }
85 
86 #undef __FUNCT__
87 #define __FUNCT__ "PetscDrawSPSetDimension"
88 /*@
89    PetscDrawSPSetDimension - Change the number of sets of points  that are to be drawn.
90 
91    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
92 
93    Input Parameter:
94 +  sp - the line graph context.
95 -  dim - the number of curves.
96 
97    Level: intermediate
98 
99    Concepts: scatter plot^setting number of data types
100 
101 @*/
102 PetscErrorCode  PetscDrawSPSetDimension(PetscDrawSP sp,int dim)
103 {
104   PetscErrorCode ierr;
105 
106   PetscFunctionBegin;
107   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
108   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
109   if (sp->dim == dim) PetscFunctionReturn(0);
110 
111   ierr    = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
112   sp->dim = dim;
113   ierr    = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr);
114   ierr    = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
115   sp->len = dim*CHUNCKSIZE;
116   PetscFunctionReturn(0);
117 }
118 
119 #undef __FUNCT__
120 #define __FUNCT__ "PetscDrawSPReset"
121 /*@
122    PetscDrawSPReset - Clears line graph to allow for reuse with new data.
123 
124    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
125 
126    Input Parameter:
127 .  sp - the line graph context.
128 
129    Level: intermediate
130 
131   Concepts: scatter plot^resetting
132 
133 @*/
134 PetscErrorCode  PetscDrawSPReset(PetscDrawSP sp)
135 {
136   PetscFunctionBegin;
137   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
138   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
139   sp->xmin  = 1.e20;
140   sp->ymin  = 1.e20;
141   sp->xmax  = -1.e20;
142   sp->ymax  = -1.e20;
143   sp->loc   = 0;
144   sp->nopts = 0;
145   PetscFunctionReturn(0);
146 }
147 
148 #undef __FUNCT__
149 #define __FUNCT__ "PetscDrawSPDestroy"
150 /*@C
151    PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
152 
153    Collective over PetscDrawSP
154 
155    Input Parameter:
156 .  sp - the line graph context
157 
158    Level: intermediate
159 
160 .seealso:  PetscDrawSPCreate()
161 @*/
162 PetscErrorCode  PetscDrawSPDestroy(PetscDrawSP *sp)
163 {
164   PetscErrorCode ierr;
165 
166   PetscFunctionBegin;
167   if (!*sp) PetscFunctionReturn(0);
168   PetscValidHeader(*sp,1);
169 
170   if (--((PetscObject)(*sp))->refct > 0) PetscFunctionReturn(0);
171   if (((PetscObject)(*sp))->classid == PETSC_DRAW_CLASSID) {
172     ierr = PetscDrawDestroy((PetscDraw*) sp);CHKERRQ(ierr);
173     PetscFunctionReturn(0);
174   }
175   ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr);
176   ierr = PetscFree2((*sp)->x,(*sp)->y);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    Not Collective (ignored on all processors except processor 0 of 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 && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
206 
207   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
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    Not Collective (ignored on all processors except processor 0 of 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 && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) 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    Not Collective (ignored on all processors except processor 0 of 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=sp->xmin,xmax=sp->xmax,ymin=sp->ymin,ymax=sp->ymax;
314   PetscErrorCode ierr;
315   PetscInt       i,j,dim = sp->dim,nopts = sp->nopts;
316   PetscMPIInt    rank;
317   PetscDraw      draw = sp->win;
318 
319   PetscFunctionBegin;
320   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
321   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
322 
323   if (nopts < 1) PetscFunctionReturn(0);
324   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0);
325   if (clear) {
326     ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
327     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
328   }
329   ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
330   ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr);
331 
332   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRQ(ierr);
333   if (!rank) {
334     for (i=0; i<dim; i++) {
335       for (j=0; j<nopts; j++) {
336         ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr);
337       }
338     }
339   }
340   ierr = PetscDrawFlush(sp->win);CHKERRQ(ierr);
341   ierr = PetscDrawPause(sp->win);CHKERRQ(ierr);
342   PetscFunctionReturn(0);
343 }
344 
345 #undef __FUNCT__
346 #define __FUNCT__ "PetscDrawSPSetLimits"
347 /*@
348    PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more
349    points are added after this call, the limits will be adjusted to
350    include those additional points.
351 
352    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
353 
354    Input Parameters:
355 +  xsp - the line graph context
356 -  x_min,x_max,y_min,y_max - the limits
357 
358    Level: intermediate
359 
360    Concepts: scatter plot^setting axis
361 
362 @*/
363 PetscErrorCode  PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
364 {
365   PetscFunctionBegin;
366   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
367   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
368   sp->xmin = x_min;
369   sp->xmax = x_max;
370   sp->ymin = y_min;
371   sp->ymax = y_max;
372   PetscFunctionReturn(0);
373 }
374 
375 #undef __FUNCT__
376 #define __FUNCT__ "PetscDrawSPGetAxis"
377 /*@C
378    PetscDrawSPGetAxis - Gets the axis context associated with a line graph.
379    This is useful if one wants to change some axis property, such as
380    labels, color, etc. The axis context should not be destroyed by the
381    application code.
382 
383    Not Collective (except PetscDrawAxis can only be used on processor 0 of PetscDrawSP)
384 
385    Input Parameter:
386 .  sp - the line graph context
387 
388    Output Parameter:
389 .  axis - the axis context
390 
391    Level: intermediate
392 
393 @*/
394 PetscErrorCode  PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis)
395 {
396   PetscFunctionBegin;
397   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) {
398     *axis = 0;
399     PetscFunctionReturn(0);
400   }
401   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
402   *axis = sp->axis;
403   PetscFunctionReturn(0);
404 }
405 
406 #undef __FUNCT__
407 #define __FUNCT__ "PetscDrawSPGetDraw"
408 /*@C
409    PetscDrawSPGetDraw - Gets the draw context associated with a line graph.
410 
411    Not Collective, PetscDraw is parallel if PetscDrawSP is parallel
412 
413    Input Parameter:
414 .  sp - the line graph context
415 
416    Output Parameter:
417 .  draw - the draw context
418 
419    Level: intermediate
420 
421 @*/
422 PetscErrorCode  PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw)
423 {
424   PetscFunctionBegin;
425   PetscValidHeader(sp,1);
426   PetscValidPointer(draw,2);
427   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) *draw = (PetscDraw)sp;
428   else *draw = sp->win;
429   PetscFunctionReturn(0);
430 }
431