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