xref: /petsc/src/sys/classes/draw/utils/dscatter.c (revision 519f805a543c2a7f195bcba21173bb2cdfadb956)
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 <petscsys.h>         /*I "petscsys.h" I*/
9 
10 PetscClassId PETSC_DRAWSP_CLASSID = 0;
11 
12 struct _p_PetscDrawSP {
13   PETSCHEADER(int);
14   PetscErrorCode (*destroy)(PetscDrawSP);
15   PetscErrorCode (*view)(PetscDrawSP,PetscViewer);
16   int           len,loc;
17   PetscDraw     win;
18   PetscDrawAxis axis;
19   PetscReal     xmin,xmax,ymin,ymax,*x,*y;
20   int           nopts,dim;
21 };
22 
23 #define CHUNCKSIZE 100
24 
25 #undef __FUNCT__
26 #define __FUNCT__ "PetscDrawSPCreate"
27 /*@C
28     PetscDrawSPCreate - Creates a scatter plot data structure.
29 
30     Collective over PetscDraw
31 
32     Input Parameters:
33 +   win - the window where the graph will be made.
34 -   dim - the number of sets of points which will be drawn
35 
36     Output Parameters:
37 .   drawsp - the scatter plot context
38 
39    Level: intermediate
40 
41    Concepts: scatter plot^creating
42 
43 .seealso:  PetscDrawSPDestroy()
44 @*/
45 PetscErrorCode  PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp)
46 {
47   PetscErrorCode ierr;
48   PetscBool      isnull;
49   PetscObject    obj = (PetscObject)draw;
50   PetscDrawSP    sp;
51 
52   PetscFunctionBegin;
53   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
54   PetscValidPointer(drawsp,3);
55   ierr = PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);CHKERRQ(ierr);
56   if (isnull) {
57     ierr = PetscDrawOpenNull(((PetscObject)obj)->comm,(PetscDraw*)drawsp);CHKERRQ(ierr);
58     PetscFunctionReturn(0);
59   }
60   ierr = PetscHeaderCreate(sp,_p_PetscDrawSP,int,PETSC_DRAWSP_CLASSID,0,"PetscDrawSP","Scatter plot","Draw",((PetscObject)obj)->comm,PetscDrawSPDestroy,0);CHKERRQ(ierr);
61   sp->view    = 0;
62   sp->destroy = 0;
63   sp->nopts   = 0;
64   sp->win     = draw;
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   ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&sp->x,dim*CHUNCKSIZE,PetscReal,&sp->y);CHKERRQ(ierr);
71   ierr = PetscLogObjectMemory(sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
72   sp->len     = dim*CHUNCKSIZE;
73   sp->loc     = 0;
74   ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr);
75   ierr = PetscLogObjectParent(sp,sp->axis);CHKERRQ(ierr);
76   *drawsp = sp;
77   PetscFunctionReturn(0);
78 }
79 
80 #undef __FUNCT__
81 #define __FUNCT__ "PetscDrawSPSetDimension"
82 /*@
83    PetscDrawSPSetDimension - Change the number of sets of points  that are to be drawn.
84 
85    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
86 
87    Input Parameter:
88 +  sp - the line graph context.
89 -  dim - the number of curves.
90 
91    Level: intermediate
92 
93    Concepts: scatter plot^setting number of data types
94 
95 @*/
96 PetscErrorCode  PetscDrawSPSetDimension(PetscDrawSP sp,int dim)
97 {
98   PetscErrorCode ierr;
99 
100   PetscFunctionBegin;
101   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
102   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
103   if (sp->dim == dim) PetscFunctionReturn(0);
104 
105   ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
106   sp->dim     = dim;
107   ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&sp->x,dim*CHUNCKSIZE,PetscReal,&sp->y);CHKERRQ(ierr);
108   ierr = PetscLogObjectMemory(sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
109   sp->len     = dim*CHUNCKSIZE;
110   PetscFunctionReturn(0);
111 }
112 
113 #undef __FUNCT__
114 #define __FUNCT__ "PetscDrawSPReset"
115 /*@
116    PetscDrawSPReset - Clears line graph to allow for reuse with new data.
117 
118    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
119 
120    Input Parameter:
121 .  sp - the line graph context.
122 
123    Level: intermediate
124 
125   Concepts: scatter plot^resetting
126 
127 @*/
128 PetscErrorCode  PetscDrawSPReset(PetscDrawSP sp)
129 {
130   PetscFunctionBegin;
131   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
132   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
133   sp->xmin  = 1.e20;
134   sp->ymin  = 1.e20;
135   sp->xmax  = -1.e20;
136   sp->ymax  = -1.e20;
137   sp->loc   = 0;
138   sp->nopts = 0;
139   PetscFunctionReturn(0);
140 }
141 
142 #undef __FUNCT__
143 #define __FUNCT__ "PetscDrawSPDestroy"
144 /*@C
145    PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
146 
147    Collective over PetscDrawSP
148 
149    Input Parameter:
150 .  sp - the line graph context
151 
152    Level: intermediate
153 
154 .seealso:  PetscDrawSPCreate()
155 @*/
156 PetscErrorCode  PetscDrawSPDestroy(PetscDrawSP *sp)
157 {
158   PetscErrorCode ierr;
159 
160   PetscFunctionBegin;
161   if (!*sp) PetscFunctionReturn(0);
162   PetscValidHeader(*sp,1);
163 
164   if (--((PetscObject)(*sp))->refct > 0) PetscFunctionReturn(0);
165   if (((PetscObject)(*sp))->classid == PETSC_DRAW_CLASSID) {
166     ierr = PetscDrawDestroy((PetscDraw*) sp);CHKERRQ(ierr);
167     PetscFunctionReturn(0);
168   }
169   ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr);
170   ierr = PetscFree2((*sp)->x,(*sp)->y);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    Not Collective (ignored on all processors except processor 0 of 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   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
200 
201   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
202   if (sp->loc+sp->dim >= sp->len) { /* allocate more space */
203     PetscReal *tmpx,*tmpy;
204     ierr = PetscMalloc2(sp->len+sp->dim*CHUNCKSIZE,PetscReal,&tmpx,sp->len+sp->dim*CHUNCKSIZE,PetscReal,&tmpy);CHKERRQ(ierr);
205     ierr = PetscLogObjectMemory(sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
206     ierr = PetscMemcpy(tmpx,sp->x,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
207     ierr = PetscMemcpy(tmpy,sp->y,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
208     ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
209     sp->x = tmpx;
210     sp->y = tmpy;
211     sp->len += sp->dim*CHUNCKSIZE;
212   }
213   for (i=0; i<sp->dim; i++) {
214     if (x[i] > sp->xmax) sp->xmax = x[i];
215     if (x[i] < sp->xmin) sp->xmin = x[i];
216     if (y[i] > sp->ymax) sp->ymax = y[i];
217     if (y[i] < sp->ymin) sp->ymin = y[i];
218 
219     sp->x[sp->loc]   = x[i];
220     sp->y[sp->loc++] = y[i];
221   }
222   sp->nopts++;
223   PetscFunctionReturn(0);
224 }
225 
226 
227 #undef __FUNCT__
228 #define __FUNCT__ "PetscDrawSPAddPoints"
229 /*@C
230    PetscDrawSPAddPoints - Adds several points to each of the scatter plots.
231 
232    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
233 
234    Input Parameters:
235 +  sp - the LineGraph data structure
236 .  xx,yy - points to two arrays of pointers that point to arrays
237            containing the new x and y points for each curve.
238 -  n - number of points being added
239 
240    Level: intermediate
241 
242    Concepts: scatter plot^adding points
243 
244 .seealso: PetscDrawSPAddPoint()
245 @*/
246 PetscErrorCode  PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy)
247 {
248   PetscErrorCode ierr;
249   PetscInt       i,j,k;
250   PetscReal      *x,*y;
251 
252   PetscFunctionBegin;
253   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
254   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
255 
256   if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */
257     PetscReal *tmpx,*tmpy;
258     PetscInt  chunk = CHUNCKSIZE;
259     if (n > chunk) chunk = n;
260     ierr = PetscMalloc2(sp->len+sp->dim*chunk,PetscReal,&tmpx,sp->len+sp->dim*chunk,PetscReal,&tmpy);CHKERRQ(ierr);
261     ierr = PetscLogObjectMemory(sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
262     ierr = PetscMemcpy(tmpx,sp->x,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
263     ierr = PetscMemcpy(tmpy,sp->y,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
264     ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
265     sp->x    = tmpx;
266     sp->y    = tmpy;
267     sp->len += sp->dim*CHUNCKSIZE;
268   }
269   for (j=0; j<sp->dim; j++) {
270     x = xx[j]; y = yy[j];
271     k = sp->loc + j;
272     for (i=0; i<n; i++) {
273       if (x[i] > sp->xmax) sp->xmax = x[i];
274       if (x[i] < sp->xmin) sp->xmin = x[i];
275       if (y[i] > sp->ymax) sp->ymax = y[i];
276       if (y[i] < sp->ymin) sp->ymin = y[i];
277 
278       sp->x[k] = x[i];
279       sp->y[k] = y[i];
280       k += sp->dim;
281     }
282   }
283   sp->loc   += n*sp->dim;
284   sp->nopts += n;
285   PetscFunctionReturn(0);
286 }
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "PetscDrawSPDraw"
290 /*@
291    PetscDrawSPDraw - Redraws a scatter plot.
292 
293    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
294 
295    Input Parameter:
296 +  sp - the line graph context
297 -  clear - clear the window before drawing the new plot
298 
299    Level: intermediate
300 
301 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw()
302 
303 @*/
304 PetscErrorCode  PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
305 {
306   PetscReal      xmin=sp->xmin,xmax=sp->xmax,ymin=sp->ymin,ymax=sp->ymax;
307   PetscErrorCode ierr;
308   PetscInt       i,j,dim = sp->dim,nopts = sp->nopts;
309   PetscMPIInt    rank;
310   PetscDraw      draw = sp->win;
311 
312   PetscFunctionBegin;
313   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
314   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
315 
316   if (nopts < 1) PetscFunctionReturn(0);
317   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0);
318   if (clear) {
319     ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
320     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
321   }
322   ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
323   ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr);
324 
325   ierr = MPI_Comm_rank(((PetscObject)sp)->comm,&rank);CHKERRQ(ierr);
326   if (!rank) {
327     for (i=0; i<dim; i++) {
328       for (j=0; j<nopts; j++) {
329         ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr);
330       }
331     }
332   }
333   ierr = PetscDrawFlush(sp->win);CHKERRQ(ierr);
334   ierr = PetscDrawPause(sp->win);CHKERRQ(ierr);
335   PetscFunctionReturn(0);
336 }
337 
338 #undef __FUNCT__
339 #define __FUNCT__ "PetscDrawSPSetLimits"
340 /*@
341    PetscDrawSPSetLimits - Sets the axis limits for a line graph. If more
342    points are added after this call, the limits will be adjusted to
343    include those additional points.
344 
345    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
346 
347    Input Parameters:
348 +  xsp - the line graph context
349 -  x_min,x_max,y_min,y_max - the limits
350 
351    Level: intermediate
352 
353    Concepts: scatter plot^setting axis
354 
355 @*/
356 PetscErrorCode  PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
357 {
358   PetscFunctionBegin;
359   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
360   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
361   sp->xmin = x_min;
362   sp->xmax = x_max;
363   sp->ymin = y_min;
364   sp->ymax = y_max;
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "PetscDrawSPGetAxis"
370 /*@C
371    PetscDrawSPGetAxis - Gets the axis context associated with a line graph.
372    This is useful if one wants to change some axis property, such as
373    labels, color, etc. The axis context should not be destroyed by the
374    application code.
375 
376    Not Collective (except PetscDrawAxis can only be used on processor 0 of PetscDrawSP)
377 
378    Input Parameter:
379 .  sp - the line graph context
380 
381    Output Parameter:
382 .  axis - the axis context
383 
384    Level: intermediate
385 
386 @*/
387 PetscErrorCode  PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis)
388 {
389   PetscFunctionBegin;
390   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) {
391     *axis = 0;
392     PetscFunctionReturn(0);
393   }
394   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
395   *axis = sp->axis;
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "PetscDrawSPGetDraw"
401 /*@C
402    PetscDrawSPGetDraw - Gets the draw context associated with a line graph.
403 
404    Not Collective, PetscDraw is parallel if PetscDrawSP is parallel
405 
406    Input Parameter:
407 .  sp - the line graph context
408 
409    Output Parameter:
410 .  draw - the draw context
411 
412    Level: intermediate
413 
414 @*/
415 PetscErrorCode  PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw)
416 {
417   PetscFunctionBegin;
418   PetscValidHeader(sp,1);
419   PetscValidPointer(draw,2);
420   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) {
421     *draw = (PetscDraw)sp;
422   } else {
423     *draw = sp->win;
424   }
425   PetscFunctionReturn(0);
426 }
427