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