xref: /petsc/src/sys/classes/draw/utils/lgc.c (revision 3db8ccc792d4bd10df0da905a21f07b40f720d8c) !
1 #include <petscviewer.h>
2 #include <petsc/private/drawimpl.h> /*I   "petscdraw.h"  I*/
3 PetscClassId PETSC_DRAWLG_CLASSID = 0;
4 
5 /*@
6   PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
7   This is useful if one wants to change some axis property, such as
8   labels, color, etc. The axis context should not be destroyed by the
9   application code.
10 
11   Not Collective, if lg is parallel then axis is parallel
12 
13   Input Parameter:
14 . lg - the line graph context
15 
16   Output Parameter:
17 . axis - the axis context
18 
19   Level: advanced
20 
21 .seealso: `PetscDrawLGCreate()`, `PetscDrawAxis`, `PetscDrawLG`
22 @*/
23 PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg, PetscDrawAxis *axis)
24 {
25   PetscFunctionBegin;
26   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
27   PetscAssertPointer(axis, 2);
28   *axis = lg->axis;
29   PetscFunctionReturn(PETSC_SUCCESS);
30 }
31 
32 /*@
33   PetscDrawLGGetDraw - Gets the draw context associated with a line graph.
34 
35   Not Collective, if lg is parallel then draw is parallel
36 
37   Input Parameter:
38 . lg - the line graph context
39 
40   Output Parameter:
41 . draw - the draw context
42 
43   Level: intermediate
44 
45 .seealso: `PetscDrawLGCreate()`, `PetscDraw`, `PetscDrawLG`
46 @*/
47 PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg, PetscDraw *draw)
48 {
49   PetscFunctionBegin;
50   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
51   PetscAssertPointer(draw, 2);
52   *draw = lg->win;
53   PetscFunctionReturn(PETSC_SUCCESS);
54 }
55 
56 /*@
57   PetscDrawLGSPDraw - Redraws a line graph and a scatter plot on the same `PetscDraw` they must share
58 
59   Collective
60 
61   Input Parameters:
62 + lg   - the line graph context
63 - spin - the scatter plot
64 
65   Level: intermediate
66 
67   Developer Notes:
68   This code cheats and uses the fact that the `PetscDrawLG` and `PetscDrawSP` structs are the same
69 
70 .seealso: `PetscDrawLGDraw()`, `PetscDrawSPDraw()`
71 @*/
72 PetscErrorCode PetscDrawLGSPDraw(PetscDrawLG lg, PetscDrawSP spin)
73 {
74   PetscDrawLG sp = (PetscDrawLG)spin;
75   PetscReal   xmin, xmax, ymin, ymax;
76   PetscBool   isnull;
77   PetscMPIInt rank;
78   PetscDraw   draw;
79 
80   PetscFunctionBegin;
81   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
82   PetscValidHeaderSpecific(sp, PETSC_DRAWLG_CLASSID, 2);
83   PetscCall(PetscDrawIsNull(lg->win, &isnull));
84   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
85   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank));
86 
87   draw = lg->win;
88   PetscCall(PetscDrawCheckResizedWindow(draw));
89   PetscCall(PetscDrawClear(draw));
90 
91   xmin = PetscMin(lg->xmin, sp->xmin);
92   ymin = PetscMin(lg->ymin, sp->ymin);
93   xmax = PetscMax(lg->xmax, sp->xmax);
94   ymax = PetscMax(lg->ymax, sp->ymax);
95   PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax));
96   PetscCall(PetscDrawAxisDraw(lg->axis));
97 
98   PetscDrawCollectiveBegin(draw);
99   if (rank == 0) {
100     int i, j, dim, nopts;
101     dim   = lg->dim;
102     nopts = lg->nopts;
103     for (i = 0; i < dim; i++) {
104       for (j = 1; j < nopts; j++) {
105         PetscCall(PetscDrawLine(draw, lg->x[(j - 1) * dim + i], lg->y[(j - 1) * dim + i], lg->x[j * dim + i], lg->y[j * dim + i], PETSC_DRAW_BLACK + i));
106         if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], PETSC_DRAW_RED));
107       }
108     }
109     dim   = sp->dim;
110     nopts = sp->nopts;
111     for (i = 0; i < dim; i++) {
112       for (j = 0; j < nopts; j++) PetscCall(PetscDrawMarker(draw, sp->x[j * dim + i], sp->y[j * dim + i], PETSC_DRAW_RED));
113     }
114   }
115   PetscDrawCollectiveEnd(draw);
116 
117   PetscCall(PetscDrawFlush(draw));
118   PetscCall(PetscDrawPause(draw));
119   PetscFunctionReturn(PETSC_SUCCESS);
120 }
121 
122 /*@
123   PetscDrawLGCreate - Creates a line graph data structure.
124 
125   Collective
126 
127   Input Parameters:
128 + draw - the window where the graph will be made.
129 - dim  - the number of curves which will be drawn
130 
131   Output Parameter:
132 . outlg - the line graph context
133 
134   Level: intermediate
135 
136   Notes:
137   The MPI communicator that owns the `PetscDraw` owns this `PetscDrawLG`, but the calls to set options and add points are ignored on all processes except the
138   zeroth MPI process in the communicator.
139 
140   All MPI ranks in the communicator must call `PetscDrawLGDraw()` to display the updated graph.
141 
142 .seealso: `PetscDrawLGDestroy()`, `PetscDrawLGAddPoint()`, `PetscDrawLGAddCommonPoint()`, `PetscDrawLGAddPoints()`, `PetscDrawLGDraw()`, `PetscDrawLGSave()`,
143           `PetscDrawLGView()`, `PetscDrawLGReset()`, `PetscDrawLGSetDimension()`, `PetscDrawLGGetDimension()`, `PetscDrawLGSetLegend()`, `PetscDrawLGGetAxis()`,
144           `PetscDrawLGGetDraw()`, `PetscDrawLGSetUseMarkers()`, `PetscDrawLGSetLimits()`, `PetscDrawLGSetColors()`, `PetscDrawLGSetOptionsPrefix()`, `PetscDrawLGSetFromOptions()`
145 @*/
146 PetscErrorCode PetscDrawLGCreate(PetscDraw draw, PetscInt dim, PetscDrawLG *outlg)
147 {
148   PetscDrawLG lg;
149 
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
152   PetscValidLogicalCollectiveInt(draw, dim, 2);
153   PetscAssertPointer(outlg, 3);
154 
155   PetscCall(PetscHeaderCreate(lg, PETSC_DRAWLG_CLASSID, "DrawLG", "Line Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawLGDestroy, NULL));
156   PetscCall(PetscDrawLGSetOptionsPrefix(lg, ((PetscObject)draw)->prefix));
157 
158   PetscCall(PetscObjectReference((PetscObject)draw));
159   lg->win = draw;
160 
161   lg->view    = NULL;
162   lg->destroy = NULL;
163   lg->nopts   = 0;
164   lg->xmin    = 1.e20;
165   lg->ymin    = 1.e20;
166   lg->xmax    = -1.e20;
167   lg->ymax    = -1.e20;
168   PetscCall(PetscCIntCast(dim, &lg->dim));
169   PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y));
170 
171   lg->len         = lg->dim * PETSC_DRAW_LG_CHUNK_SIZE;
172   lg->loc         = 0;
173   lg->use_markers = PETSC_FALSE;
174 
175   PetscCall(PetscDrawAxisCreate(draw, &lg->axis));
176 
177   *outlg = lg;
178   PetscFunctionReturn(PETSC_SUCCESS);
179 }
180 
181 /*@
182   PetscDrawLGSetColors - Sets the color of each line graph drawn
183 
184   Logically Collective
185 
186   Input Parameters:
187 + lg     - the line graph context.
188 - colors - the colors
189 
190   Level: intermediate
191 
192 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
193 @*/
194 PetscErrorCode PetscDrawLGSetColors(PetscDrawLG lg, const int colors[])
195 {
196   PetscFunctionBegin;
197   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
198   if (lg->dim) PetscAssertPointer(colors, 2);
199 
200   PetscCall(PetscFree(lg->colors));
201   PetscCall(PetscMalloc1(lg->dim, &lg->colors));
202   PetscCall(PetscArraycpy(lg->colors, colors, lg->dim));
203   PetscFunctionReturn(PETSC_SUCCESS);
204 }
205 
206 /*@C
207   PetscDrawLGSetLegend - sets the names of each curve plotted
208 
209   Logically Collective
210 
211   Input Parameters:
212 + lg    - the line graph context.
213 - names - the names for each curve
214 
215   Level: intermediate
216 
217   Note:
218   Call `PetscDrawLGGetAxis()` and then change properties of the `PetscDrawAxis` for detailed control of the plot
219 
220 .seealso: `PetscDrawLGGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetHoldLimits()`
221 @*/
222 PetscErrorCode PetscDrawLGSetLegend(PetscDrawLG lg, const char *const names[])
223 {
224   PetscInt i;
225 
226   PetscFunctionBegin;
227   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
228   if (names) PetscAssertPointer(names, 2);
229 
230   if (lg->legend) {
231     for (i = 0; i < lg->dim; i++) PetscCall(PetscFree(lg->legend[i]));
232     PetscCall(PetscFree(lg->legend));
233   }
234   if (names) {
235     PetscCall(PetscMalloc1(lg->dim, &lg->legend));
236     for (i = 0; i < lg->dim; i++) PetscCall(PetscStrallocpy(names[i], &lg->legend[i]));
237   }
238   PetscFunctionReturn(PETSC_SUCCESS);
239 }
240 
241 /*@
242   PetscDrawLGGetDimension - Get the number of curves that are to be drawn.
243 
244   Not Collective
245 
246   Input Parameter:
247 . lg - the line graph context.
248 
249   Output Parameter:
250 . dim - the number of curves.
251 
252   Level: intermediate
253 
254 .seealso: `PetscDrawLGC`, `PetscDrawLGCreate()`, `PetscDrawLGSetDimension()`
255 @*/
256 PetscErrorCode PetscDrawLGGetDimension(PetscDrawLG lg, PetscInt *dim)
257 {
258   PetscFunctionBegin;
259   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
260   PetscAssertPointer(dim, 2);
261   *dim = lg->dim;
262   PetscFunctionReturn(PETSC_SUCCESS);
263 }
264 
265 /*@
266   PetscDrawLGSetDimension - Change the number of curves that are to be drawn.
267 
268   Logically Collective
269 
270   Input Parameters:
271 + lg  - the line graph context.
272 - dim - the number of curves.
273 
274   Level: intermediate
275 
276 .seealso: `PetscDrawLGCreate()`, `PetscDrawLGGetDimension()`
277 @*/
278 PetscErrorCode PetscDrawLGSetDimension(PetscDrawLG lg, PetscInt dim)
279 {
280   PetscInt i;
281 
282   PetscFunctionBegin;
283   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
284   PetscValidLogicalCollectiveInt(lg, dim, 2);
285   if (lg->dim == dim) PetscFunctionReturn(PETSC_SUCCESS);
286 
287   PetscCall(PetscFree2(lg->x, lg->y));
288   if (lg->legend) {
289     for (i = 0; i < lg->dim; i++) PetscCall(PetscFree(lg->legend[i]));
290     PetscCall(PetscFree(lg->legend));
291   }
292   PetscCall(PetscFree(lg->colors));
293   PetscCall(PetscCIntCast(dim, &lg->dim));
294   PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y));
295   lg->len = lg->dim * PETSC_DRAW_LG_CHUNK_SIZE;
296   PetscFunctionReturn(PETSC_SUCCESS);
297 }
298 
299 /*@
300   PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
301   points are added after this call, the limits will be adjusted to
302   include those additional points.
303 
304   Logically Collective
305 
306   Input Parameters:
307 + lg    - the line graph context
308 . x_min - the horizontal lower limit
309 . x_max - the horizontal upper limit
310 . y_min - the vertical lower limit
311 - y_max - the vertical upper limit
312 
313   Level: intermediate
314 
315 .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawAxis`
316 @*/
317 PetscErrorCode PetscDrawLGSetLimits(PetscDrawLG lg, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max)
318 {
319   PetscFunctionBegin;
320   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
321 
322   (lg)->xmin = x_min;
323   (lg)->xmax = x_max;
324   (lg)->ymin = y_min;
325   (lg)->ymax = y_max;
326   PetscFunctionReturn(PETSC_SUCCESS);
327 }
328 
329 /*@
330   PetscDrawLGReset - Clears line graph to allow for reuse with new data.
331 
332   Logically Collective
333 
334   Input Parameter:
335 . lg - the line graph context.
336 
337   Level: intermediate
338 
339 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
340 @*/
341 PetscErrorCode PetscDrawLGReset(PetscDrawLG lg)
342 {
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
345   lg->xmin  = 1.e20;
346   lg->ymin  = 1.e20;
347   lg->xmax  = -1.e20;
348   lg->ymax  = -1.e20;
349   lg->loc   = 0;
350   lg->nopts = 0;
351   PetscFunctionReturn(PETSC_SUCCESS);
352 }
353 
354 /*@
355   PetscDrawLGDestroy - Frees all space taken up by line graph data structure.
356 
357   Collective
358 
359   Input Parameter:
360 . lg - the line graph context
361 
362   Level: intermediate
363 
364 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
365 @*/
366 PetscErrorCode PetscDrawLGDestroy(PetscDrawLG *lg)
367 {
368   PetscInt i;
369 
370   PetscFunctionBegin;
371   if (!*lg) PetscFunctionReturn(PETSC_SUCCESS);
372   PetscValidHeaderSpecific(*lg, PETSC_DRAWLG_CLASSID, 1);
373   if (--((PetscObject)*lg)->refct > 0) {
374     *lg = NULL;
375     PetscFunctionReturn(PETSC_SUCCESS);
376   }
377 
378   if ((*lg)->legend) {
379     for (i = 0; i < (*lg)->dim; i++) PetscCall(PetscFree((*lg)->legend[i]));
380     PetscCall(PetscFree((*lg)->legend));
381   }
382   PetscCall(PetscFree((*lg)->colors));
383   PetscCall(PetscFree2((*lg)->x, (*lg)->y));
384   PetscCall(PetscDrawAxisDestroy(&(*lg)->axis));
385   PetscCall(PetscDrawDestroy(&(*lg)->win));
386   PetscCall(PetscHeaderDestroy(lg));
387   PetscFunctionReturn(PETSC_SUCCESS);
388 }
389 /*@
390   PetscDrawLGSetUseMarkers - Causes the line graph object to draw a marker for each data-point.
391 
392   Logically Collective
393 
394   Input Parameters:
395 + lg  - the linegraph context
396 - flg - should mark each data point
397 
398   Options Database Key:
399 . -lg_use_markers  <true,false> - true means it draws a marker for each point
400 
401   Level: intermediate
402 
403 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
404 @*/
405 PetscErrorCode PetscDrawLGSetUseMarkers(PetscDrawLG lg, PetscBool flg)
406 {
407   PetscFunctionBegin;
408   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
409   PetscValidLogicalCollectiveBool(lg, flg, 2);
410   lg->use_markers = flg;
411   PetscFunctionReturn(PETSC_SUCCESS);
412 }
413 
414 /*@
415   PetscDrawLGDraw - Redraws a line graph.
416 
417   Collective
418 
419   Input Parameter:
420 . lg - the line graph context
421 
422   Level: intermediate
423 
424 .seealso: `PetscDrawLG`, `PetscDrawSPDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawLGReset()`
425 @*/
426 PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg)
427 {
428   PetscReal   xmin, xmax, ymin, ymax;
429   PetscMPIInt rank;
430   PetscDraw   draw;
431   PetscBool   isnull;
432 
433   PetscFunctionBegin;
434   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
435   PetscCall(PetscDrawIsNull(lg->win, &isnull));
436   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
437   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank));
438 
439   draw = lg->win;
440   PetscCall(PetscDrawCheckResizedWindow(draw));
441   PetscCall(PetscDrawClear(draw));
442 
443   xmin = lg->xmin;
444   xmax = lg->xmax;
445   ymin = lg->ymin;
446   ymax = lg->ymax;
447   PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax));
448   PetscCall(PetscDrawAxisDraw(lg->axis));
449 
450   PetscDrawCollectiveBegin(draw);
451   if (rank == 0) {
452     int i, j, dim = lg->dim, nopts = lg->nopts, cl;
453     for (i = 0; i < dim; i++) {
454       for (j = 1; j < nopts; j++) {
455         cl = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR);
456         PetscCall(PetscDrawLine(draw, lg->x[(j - 1) * dim + i], lg->y[(j - 1) * dim + i], lg->x[j * dim + i], lg->y[j * dim + i], cl));
457         if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], cl));
458       }
459     }
460   }
461   if (rank == 0 && lg->legend) {
462     PetscBool right = PETSC_FALSE;
463     int       i, dim = lg->dim, cl;
464     PetscReal xl, yl, xr, yr, tw, th;
465     size_t    slen, len = 0;
466 
467     PetscCall(PetscDrawAxisGetLimits(lg->axis, &xl, &xr, &yl, &yr));
468     PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
469     for (i = 0; i < dim; i++) {
470       PetscCall(PetscStrlen(lg->legend[i], &slen));
471       len = PetscMax(len, slen);
472     }
473     if (right) {
474       xr = xr - 1.5 * tw;
475       xl = xr - ((PetscReal)len + 7) * tw;
476     } else {
477       xl = xl + 1.5 * tw;
478       xr = xl + ((PetscReal)len + 7) * tw;
479     }
480     yr = yr - 1.0 * th;
481     yl = yr - (dim + 1) * th;
482     PetscCall(PetscDrawLine(draw, xl, yl, xr, yl, PETSC_DRAW_BLACK));
483     PetscCall(PetscDrawLine(draw, xr, yl, xr, yr, PETSC_DRAW_BLACK));
484     PetscCall(PetscDrawLine(draw, xr, yr, xl, yr, PETSC_DRAW_BLACK));
485     PetscCall(PetscDrawLine(draw, xl, yr, xl, yl, PETSC_DRAW_BLACK));
486     for (i = 0; i < dim; i++) {
487       cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i);
488       PetscCall(PetscDrawLine(draw, xl + 1 * tw, yr - (i + 1) * th, xl + 5 * tw, yr - (i + 1) * th, cl));
489       PetscCall(PetscDrawString(draw, xl + 6 * tw, yr - (i + 1.5) * th, PETSC_DRAW_BLACK, lg->legend[i]));
490     }
491   }
492   PetscDrawCollectiveEnd(draw);
493 
494   PetscCall(PetscDrawFlush(draw));
495   PetscCall(PetscDrawPause(draw));
496   PetscFunctionReturn(PETSC_SUCCESS);
497 }
498 
499 /*@
500   PetscDrawLGSave - Saves a drawn image
501 
502   Collective
503 
504   Input Parameter:
505 . lg - The line graph context
506 
507   Level: intermediate
508 
509 .seealso: `PetscDrawLG`, `PetscDrawSave()`, `PetscDrawLGCreate()`, `PetscDrawLGGetDraw()`, `PetscDrawSetSave()`
510 @*/
511 PetscErrorCode PetscDrawLGSave(PetscDrawLG lg)
512 {
513   PetscFunctionBegin;
514   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
515   PetscCall(PetscDrawSave(lg->win));
516   PetscFunctionReturn(PETSC_SUCCESS);
517 }
518 
519 /*@
520   PetscDrawLGView - Prints a line graph.
521 
522   Collective
523 
524   Input Parameters:
525 + lg     - the line graph context
526 - viewer - the viewer to view it with
527 
528   Level: beginner
529 
530 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
531 @*/
532 PetscErrorCode PetscDrawLGView(PetscDrawLG lg, PetscViewer viewer)
533 {
534   PetscReal xmin = lg->xmin, xmax = lg->xmax, ymin = lg->ymin, ymax = lg->ymax;
535   PetscInt  i, j, dim = lg->dim, nopts = lg->nopts;
536 
537   PetscFunctionBegin;
538   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
539 
540   if (nopts < 1) PetscFunctionReturn(PETSC_SUCCESS);
541   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(PETSC_SUCCESS);
542 
543   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg), &viewer));
544   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)lg, viewer));
545   for (i = 0; i < dim; i++) {
546     PetscCall(PetscViewerASCIIPrintf(viewer, "Line %" PetscInt_FMT ">\n", i));
547     for (j = 0; j < nopts; j++) PetscCall(PetscViewerASCIIPrintf(viewer, "  X: %g Y: %g\n", (double)lg->x[j * dim + i], (double)lg->y[j * dim + i]));
548   }
549   PetscFunctionReturn(PETSC_SUCCESS);
550 }
551 
552 /*@
553   PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all
554   `PetscDrawLG` options in the database.
555 
556   Logically Collective
557 
558   Input Parameters:
559 + lg     - the line graph context
560 - prefix - the prefix to prepend to all option names
561 
562   Level: advanced
563 
564 .seealso: `PetscDrawLG`, `PetscDrawLGSetFromOptions()`, `PetscDrawLGCreate()`
565 @*/
566 PetscErrorCode PetscDrawLGSetOptionsPrefix(PetscDrawLG lg, const char prefix[])
567 {
568   PetscFunctionBegin;
569   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
570   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lg, prefix));
571   PetscFunctionReturn(PETSC_SUCCESS);
572 }
573 
574 /*@
575   PetscDrawLGSetFromOptions - Sets options related to the line graph object
576 
577   Collective
578 
579   Input Parameters:
580 . lg - the line graph context
581 
582   Options Database Key:
583 . -lg_use_markers  <true,false> - true means it draws a marker for each point
584 
585   Level: intermediate
586 
587 .seealso: `PetscDrawLG`, `PetscDrawLGDestroy()`, `PetscDrawLGCreate()`
588 @*/
589 PetscErrorCode PetscDrawLGSetFromOptions(PetscDrawLG lg)
590 {
591   PetscBool           usemarkers, set;
592   PetscDrawMarkerType markertype;
593 
594   PetscFunctionBegin;
595   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1);
596 
597   PetscCall(PetscDrawGetMarkerType(lg->win, &markertype));
598   PetscCall(PetscOptionsGetEnum(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_marker_type", PetscDrawMarkerTypes, (PetscEnum *)&markertype, &set));
599   if (set) {
600     PetscCall(PetscDrawLGSetUseMarkers(lg, PETSC_TRUE));
601     PetscCall(PetscDrawSetMarkerType(lg->win, markertype));
602   }
603   usemarkers = lg->use_markers;
604   PetscCall(PetscOptionsGetBool(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_use_markers", &usemarkers, &set));
605   if (set) PetscCall(PetscDrawLGSetUseMarkers(lg, usemarkers));
606   PetscFunctionReturn(PETSC_SUCCESS);
607 }
608