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