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