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