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