Actual source code: lgc.c

  1: #include <petsc/private/drawimpl.h>
  2: PetscClassId PETSC_DRAWLG_CLASSID = 0;

  4: /*@
  5:   PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
  6:   This is useful if one wants to change some axis property, such as
  7:   labels, color, etc. The axis context should not be destroyed by the
  8:   application code.

 10:   Not Collective, if lg is parallel then axis is parallel

 12:   Input Parameter:
 13: . lg - the line graph context

 15:   Output Parameter:
 16: . axis - the axis context

 18:   Level: advanced

 20: .seealso: `PetscDrawLGCreate()`, `PetscDrawAxis`, `PetscDrawLG`
 21: @*/
 22: PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg, PetscDrawAxis *axis)
 23: {
 24:   PetscFunctionBegin;
 26:   PetscAssertPointer(axis, 2);
 27:   *axis = lg->axis;
 28:   PetscFunctionReturn(PETSC_SUCCESS);
 29: }

 31: /*@
 32:   PetscDrawLGGetDraw - Gets the draw context associated with a line graph.

 34:   Not Collective, if lg is parallel then draw is parallel

 36:   Input Parameter:
 37: . lg - the line graph context

 39:   Output Parameter:
 40: . draw - the draw context

 42:   Level: intermediate

 44: .seealso: `PetscDrawLGCreate()`, `PetscDraw`, `PetscDrawLG`
 45: @*/
 46: PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg, PetscDraw *draw)
 47: {
 48:   PetscFunctionBegin;
 50:   PetscAssertPointer(draw, 2);
 51:   *draw = lg->win;
 52:   PetscFunctionReturn(PETSC_SUCCESS);
 53: }

 55: /*@
 56:   PetscDrawLGSPDraw - Redraws a line graph and a scatter plot on the same `PetscDraw` they must share

 58:   Collective

 60:   Input Parameters:
 61: + lg   - the line graph context
 62: - spin - the scatter plot

 64:   Level: intermediate

 66:   Developer Notes:
 67:   This code cheats and uses the fact that the `PetscDrawLG` and `PetscDrawSP` structs are the same

 69: .seealso: `PetscDrawLGDraw()`, `PetscDrawSPDraw()`
 70: @*/
 71: PetscErrorCode PetscDrawLGSPDraw(PetscDrawLG lg, PetscDrawSP spin)
 72: {
 73:   PetscDrawLG sp = (PetscDrawLG)spin;
 74:   PetscReal   xmin, xmax, ymin, ymax;
 75:   PetscBool   isnull;
 76:   PetscMPIInt rank;
 77:   PetscDraw   draw;

 79:   PetscFunctionBegin;
 82:   PetscCall(PetscDrawIsNull(lg->win, &isnull));
 83:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
 84:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank));

 86:   draw = lg->win;
 87:   PetscCall(PetscDrawCheckResizedWindow(draw));
 88:   PetscCall(PetscDrawClear(draw));

 90:   xmin = PetscMin(lg->xmin, sp->xmin);
 91:   ymin = PetscMin(lg->ymin, sp->ymin);
 92:   xmax = PetscMax(lg->xmax, sp->xmax);
 93:   ymax = PetscMax(lg->ymax, sp->ymax);
 94:   PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax));
 95:   PetscCall(PetscDrawAxisDraw(lg->axis));

 97:   PetscDrawCollectiveBegin(draw);
 98:   if (rank == 0) {
 99:     int i, j, dim, nopts;
100:     dim   = lg->dim;
101:     nopts = lg->nopts;
102:     for (i = 0; i < dim; i++) {
103:       for (j = 1; j < nopts; j++) {
104:         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));
105:         if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], PETSC_DRAW_RED));
106:       }
107:     }
108:     dim   = sp->dim;
109:     nopts = sp->nopts;
110:     for (i = 0; i < dim; i++) {
111:       for (j = 0; j < nopts; j++) PetscCall(PetscDrawMarker(draw, sp->x[j * dim + i], sp->y[j * dim + i], PETSC_DRAW_RED));
112:     }
113:   }
114:   PetscDrawCollectiveEnd(draw);

116:   PetscCall(PetscDrawFlush(draw));
117:   PetscCall(PetscDrawPause(draw));
118:   PetscFunctionReturn(PETSC_SUCCESS);
119: }

121: /*@
122:   PetscDrawLGCreate - Creates a line graph data structure.

124:   Collective

126:   Input Parameters:
127: + draw - the window where the graph will be made.
128: - dim  - the number of curves which will be drawn

130:   Output Parameter:
131: . outlg - the line graph context

133:   Level: intermediate

135:   Notes:
136:   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
137:   zeroth MPI process in the communicator.

139:   All MPI ranks in the communicator must call `PetscDrawLGDraw()` to display the updated graph.

141: .seealso: `PetscDrawLGDestroy()`, `PetscDrawLGAddPoint()`, `PetscDrawLGAddCommonPoint()`, `PetscDrawLGAddPoints()`, `PetscDrawLGDraw()`, `PetscDrawLGSave()`,
142:           `PetscDrawLGView()`, `PetscDrawLGReset()`, `PetscDrawLGSetDimension()`, `PetscDrawLGGetDimension()`, `PetscDrawLGSetLegend()`, `PetscDrawLGGetAxis()`,
143:           `PetscDrawLGGetDraw()`, `PetscDrawLGSetUseMarkers()`, `PetscDrawLGSetLimits()`, `PetscDrawLGSetColors()`, `PetscDrawLGSetOptionsPrefix()`, `PetscDrawLGSetFromOptions()`
144: @*/
145: PetscErrorCode PetscDrawLGCreate(PetscDraw draw, PetscInt dim, PetscDrawLG *outlg)
146: {
147:   PetscDrawLG lg;

149:   PetscFunctionBegin;
152:   PetscAssertPointer(outlg, 3);

154:   PetscCall(PetscHeaderCreate(lg, PETSC_DRAWLG_CLASSID, "DrawLG", "Line Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawLGDestroy, NULL));
155:   PetscCall(PetscDrawLGSetOptionsPrefix(lg, ((PetscObject)draw)->prefix));

157:   PetscCall(PetscObjectReference((PetscObject)draw));
158:   lg->win = draw;

160:   lg->view    = NULL;
161:   lg->destroy = NULL;
162:   lg->nopts   = 0;
163:   lg->xmin    = 1.e20;
164:   lg->ymin    = 1.e20;
165:   lg->xmax    = -1.e20;
166:   lg->ymax    = -1.e20;
167:   PetscCall(PetscCIntCast(dim, &lg->dim));
168:   PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y));

170:   lg->len         = lg->dim * PETSC_DRAW_LG_CHUNK_SIZE;
171:   lg->loc         = 0;
172:   lg->use_markers = PETSC_FALSE;

174:   PetscCall(PetscDrawAxisCreate(draw, &lg->axis));

176:   *outlg = lg;
177:   PetscFunctionReturn(PETSC_SUCCESS);
178: }

180: /*@
181:   PetscDrawLGSetColors - Sets the color of each line graph drawn

183:   Logically Collective

185:   Input Parameters:
186: + lg     - the line graph context.
187: - colors - the colors, an array of length the value set with `PetscDrawLGSetDimension()`

189:   Level: intermediate

191: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`, `PetscDrawLGSetDimension()`, `PetscDrawLGGetDimension()`
192: @*/
193: PetscErrorCode PetscDrawLGSetColors(PetscDrawLG lg, const int colors[])
194: {
195:   PetscFunctionBegin;
197:   if (lg->dim) PetscAssertPointer(colors, 2);

199:   PetscCall(PetscFree(lg->colors));
200:   PetscCall(PetscMalloc1(lg->dim, &lg->colors));
201:   PetscCall(PetscArraycpy(lg->colors, colors, lg->dim));
202:   PetscFunctionReturn(PETSC_SUCCESS);
203: }

205: /*@
206:   PetscDrawLGSetLegend - sets the names of each curve plotted

208:   Logically Collective

210:   Input Parameters:
211: + lg    - the line graph context.
212: - names - the names for each curve

214:   Level: intermediate

216:   Note:
217:   Call `PetscDrawLGGetAxis()` and then change properties of the `PetscDrawAxis` for detailed control of the plot

219: .seealso: `PetscDrawLGGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetHoldLimits()`
220: @*/
221: PetscErrorCode PetscDrawLGSetLegend(PetscDrawLG lg, const char *const names[])
222: {
223:   PetscInt i;

225:   PetscFunctionBegin;
227:   if (names) PetscAssertPointer(names, 2);

229:   if (lg->legend) {
230:     for (i = 0; i < lg->dim; i++) PetscCall(PetscFree(lg->legend[i]));
231:     PetscCall(PetscFree(lg->legend));
232:   }
233:   if (names) {
234:     PetscCall(PetscMalloc1(lg->dim, &lg->legend));
235:     for (i = 0; i < lg->dim; i++) PetscCall(PetscStrallocpy(names[i], &lg->legend[i]));
236:   }
237:   PetscFunctionReturn(PETSC_SUCCESS);
238: }

240: /*@
241:   PetscDrawLGGetDimension - Get the number of curves that are to be drawn.

243:   Not Collective

245:   Input Parameter:
246: . lg - the line graph context.

248:   Output Parameter:
249: . dim - the number of curves.

251:   Level: intermediate

253: .seealso: `PetscDrawLGC`, `PetscDrawLGCreate()`, `PetscDrawLGSetDimension()`
254: @*/
255: PetscErrorCode PetscDrawLGGetDimension(PetscDrawLG lg, PetscInt *dim)
256: {
257:   PetscFunctionBegin;
259:   PetscAssertPointer(dim, 2);
260:   *dim = lg->dim;
261:   PetscFunctionReturn(PETSC_SUCCESS);
262: }

264: /*@
265:   PetscDrawLGSetDimension - Change the number of curves that are to be drawn.

267:   Logically Collective

269:   Input Parameters:
270: + lg  - the line graph context.
271: - dim - the number of curves.

273:   Level: intermediate

275: .seealso: `PetscDrawLGCreate()`, `PetscDrawLGGetDimension()`
276: @*/
277: PetscErrorCode PetscDrawLGSetDimension(PetscDrawLG lg, PetscInt dim)
278: {
279:   PetscInt i;

281:   PetscFunctionBegin;
284:   if (lg->dim == dim) PetscFunctionReturn(PETSC_SUCCESS);

286:   PetscCall(PetscFree2(lg->x, lg->y));
287:   if (lg->legend) {
288:     for (i = 0; i < lg->dim; i++) PetscCall(PetscFree(lg->legend[i]));
289:     PetscCall(PetscFree(lg->legend));
290:   }
291:   PetscCall(PetscFree(lg->colors));
292:   PetscCall(PetscCIntCast(dim, &lg->dim));
293:   PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y));
294:   lg->len = lg->dim * PETSC_DRAW_LG_CHUNK_SIZE;
295:   PetscFunctionReturn(PETSC_SUCCESS);
296: }

298: /*@
299:   PetscDrawLGGetData - Get the data being plotted.

301:   Not Collective

303:   Input Parameter:
304: . lg - the line graph context

306:   Output Parameters:
307: + dim - the number of curves
308: . n   - the number of points on each line
309: . x   - The x-value of each point, x[p * dim + c]
310: - y   - The y-value of each point, y[p * dim + c]

312:   Level: intermediate

314: .seealso: `PetscDrawLGC`, `PetscDrawLGCreate()`, `PetscDrawLGGetDimension()`
315: @*/
316: PetscErrorCode PetscDrawLGGetData(PetscDrawLG lg, PetscInt *dim, PetscInt *n, const PetscReal *x[], const PetscReal *y[])
317: {
318:   PetscFunctionBegin;
320:   if (dim) {
321:     PetscAssertPointer(dim, 2);
322:     *dim = lg->dim;
323:   }
324:   if (n) {
325:     PetscAssertPointer(n, 3);
326:     *n = lg->nopts;
327:   }
328:   if (x) {
329:     PetscAssertPointer(x, 4);
330:     *x = lg->x;
331:   }
332:   if (y) {
333:     PetscAssertPointer(y, 5);
334:     *y = lg->y;
335:   }
336:   PetscFunctionReturn(PETSC_SUCCESS);
337: }

339: /*@
340:   PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
341:   points are added after this call, the limits will be adjusted to
342:   include those additional points.

344:   Logically Collective

346:   Input Parameters:
347: + lg    - the line graph context
348: . x_min - the horizontal lower limit
349: . x_max - the horizontal upper limit
350: . y_min - the vertical lower limit
351: - y_max - the vertical upper limit

353:   Level: intermediate

355: .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawAxis`
356: @*/
357: PetscErrorCode PetscDrawLGSetLimits(PetscDrawLG lg, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max)
358: {
359:   PetscFunctionBegin;

362:   lg->xmin = x_min;
363:   lg->xmax = x_max;
364:   lg->ymin = y_min;
365:   lg->ymax = y_max;
366:   PetscFunctionReturn(PETSC_SUCCESS);
367: }

369: /*@
370:   PetscDrawLGReset - Clears line graph to allow for reuse with new data.

372:   Logically Collective

374:   Input Parameter:
375: . lg - the line graph context.

377:   Level: intermediate

379: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
380: @*/
381: PetscErrorCode PetscDrawLGReset(PetscDrawLG lg)
382: {
383:   PetscFunctionBegin;
385:   lg->xmin  = 1.e20;
386:   lg->ymin  = 1.e20;
387:   lg->xmax  = -1.e20;
388:   lg->ymax  = -1.e20;
389:   lg->loc   = 0;
390:   lg->nopts = 0;
391:   PetscFunctionReturn(PETSC_SUCCESS);
392: }

394: /*@
395:   PetscDrawLGDestroy - Frees all space taken up by line graph data structure.

397:   Collective

399:   Input Parameter:
400: . lg - the line graph context

402:   Level: intermediate

404: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
405: @*/
406: PetscErrorCode PetscDrawLGDestroy(PetscDrawLG *lg)
407: {
408:   PetscInt i;

410:   PetscFunctionBegin;
411:   if (!*lg) PetscFunctionReturn(PETSC_SUCCESS);
413:   if (--((PetscObject)*lg)->refct > 0) {
414:     *lg = NULL;
415:     PetscFunctionReturn(PETSC_SUCCESS);
416:   }

418:   if ((*lg)->legend) {
419:     for (i = 0; i < (*lg)->dim; i++) PetscCall(PetscFree((*lg)->legend[i]));
420:     PetscCall(PetscFree((*lg)->legend));
421:   }
422:   PetscCall(PetscFree((*lg)->colors));
423:   PetscCall(PetscFree2((*lg)->x, (*lg)->y));
424:   PetscCall(PetscDrawAxisDestroy(&(*lg)->axis));
425:   PetscCall(PetscDrawDestroy(&(*lg)->win));
426:   PetscCall(PetscHeaderDestroy(lg));
427:   PetscFunctionReturn(PETSC_SUCCESS);
428: }
429: /*@
430:   PetscDrawLGSetUseMarkers - Causes the line graph object to draw a marker for each data-point.

432:   Logically Collective

434:   Input Parameters:
435: + lg  - the linegraph context
436: - flg - should mark each data point

438:   Options Database Key:
439: . -lg_use_markers (true|false) - true means it draws a marker for each point

441:   Level: intermediate

443: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
444: @*/
445: PetscErrorCode PetscDrawLGSetUseMarkers(PetscDrawLG lg, PetscBool flg)
446: {
447:   PetscFunctionBegin;
450:   lg->use_markers = flg;
451:   PetscFunctionReturn(PETSC_SUCCESS);
452: }

454: /*@
455:   PetscDrawLGDraw - Redraws a line graph.

457:   Collective

459:   Input Parameter:
460: . lg - the line graph context

462:   Level: intermediate

464: .seealso: `PetscDrawLG`, `PetscDrawSPDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawLGReset()`
465: @*/
466: PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg)
467: {
468:   PetscReal   xmin, xmax, ymin, ymax;
469:   PetscMPIInt rank;
470:   PetscDraw   draw;
471:   PetscBool   isnull;

473:   PetscFunctionBegin;
475:   PetscCall(PetscDrawIsNull(lg->win, &isnull));
476:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
477:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank));

479:   draw = lg->win;
480:   PetscCall(PetscDrawCheckResizedWindow(draw));
481:   PetscCall(PetscDrawClear(draw));

483:   xmin = lg->xmin;
484:   xmax = lg->xmax;
485:   ymin = lg->ymin;
486:   ymax = lg->ymax;
487:   // Try not to freak out the axis
488:   if (ymax - ymin < PETSC_SMALL) {
489:     ymin -= 0.1 * ymax;
490:     ymax += 0.1 * ymax;
491:   }
492:   PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax));
493:   PetscCall(PetscDrawAxisDraw(lg->axis));

495:   PetscDrawCollectiveBegin(draw);
496:   if (rank == 0) {
497:     int i, j, dim = lg->dim, nopts = lg->nopts, cl;
498:     for (i = 0; i < dim; i++) {
499:       for (j = 1; j < nopts; j++) {
500:         cl = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR);
501:         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));
502:         if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], cl));
503:       }
504:     }
505:   }
506:   if (rank == 0 && lg->legend) {
507:     PetscBool right = PETSC_FALSE;
508:     int       i, dim = lg->dim, cl;
509:     PetscReal xl, yl, xr, yr, tw, th;
510:     size_t    slen, len = 0;

512:     PetscCall(PetscDrawAxisGetLimits(lg->axis, &xl, &xr, &yl, &yr));
513:     PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
514:     for (i = 0; i < dim; i++) {
515:       PetscCall(PetscStrlen(lg->legend[i], &slen));
516:       len = PetscMax(len, slen);
517:     }
518:     if (right) {
519:       xr = xr - 1.5 * tw;
520:       xl = xr - ((PetscReal)len + 7) * tw;
521:     } else {
522:       xl = xl + 1.5 * tw;
523:       xr = xl + ((PetscReal)len + 7) * tw;
524:     }
525:     yr = yr - 1.0 * th;
526:     yl = yr - (dim + 1) * th;
527:     PetscCall(PetscDrawLine(draw, xl, yl, xr, yl, PETSC_DRAW_BLACK));
528:     PetscCall(PetscDrawLine(draw, xr, yl, xr, yr, PETSC_DRAW_BLACK));
529:     PetscCall(PetscDrawLine(draw, xr, yr, xl, yr, PETSC_DRAW_BLACK));
530:     PetscCall(PetscDrawLine(draw, xl, yr, xl, yl, PETSC_DRAW_BLACK));
531:     for (i = 0; i < dim; i++) {
532:       cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i);
533:       PetscCall(PetscDrawLine(draw, xl + 1 * tw, yr - (i + 1) * th, xl + 5 * tw, yr - (i + 1) * th, cl));
534:       PetscCall(PetscDrawString(draw, xl + 6 * tw, yr - (i + 1.5) * th, PETSC_DRAW_BLACK, lg->legend[i]));
535:     }
536:   }
537:   PetscDrawCollectiveEnd(draw);

539:   PetscCall(PetscDrawFlush(draw));
540:   PetscCall(PetscDrawPause(draw));
541:   PetscFunctionReturn(PETSC_SUCCESS);
542: }

544: /*@
545:   PetscDrawLGSave - Saves a drawn image

547:   Collective

549:   Input Parameter:
550: . lg - The line graph context

552:   Level: intermediate

554: .seealso: `PetscDrawLG`, `PetscDrawSave()`, `PetscDrawLGCreate()`, `PetscDrawLGGetDraw()`, `PetscDrawSetSave()`
555: @*/
556: PetscErrorCode PetscDrawLGSave(PetscDrawLG lg)
557: {
558:   PetscFunctionBegin;
560:   PetscCall(PetscDrawSave(lg->win));
561:   PetscFunctionReturn(PETSC_SUCCESS);
562: }

564: /*@
565:   PetscDrawLGView - Prints a line graph.

567:   Collective

569:   Input Parameters:
570: + lg     - the line graph context
571: - viewer - the viewer to view it with

573:   Level: beginner

575: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
576: @*/
577: PetscErrorCode PetscDrawLGView(PetscDrawLG lg, PetscViewer viewer)
578: {
579:   PetscReal xmin = lg->xmin, xmax = lg->xmax, ymin = lg->ymin, ymax = lg->ymax;
580:   PetscInt  i, j, dim = lg->dim, nopts = lg->nopts;

582:   PetscFunctionBegin;

585:   if (nopts < 1) PetscFunctionReturn(PETSC_SUCCESS);
586:   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(PETSC_SUCCESS);

588:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg), &viewer));
589:   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)lg, viewer));
590:   for (i = 0; i < dim; i++) {
591:     PetscCall(PetscViewerASCIIPrintf(viewer, "Line %" PetscInt_FMT ">\n", i));
592:     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]));
593:   }
594:   PetscFunctionReturn(PETSC_SUCCESS);
595: }

597: /*@
598:   PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all
599:   `PetscDrawLG` options in the database.

601:   Logically Collective

603:   Input Parameters:
604: + lg     - the line graph context
605: - prefix - the prefix to prepend to all option names

607:   Level: advanced

609: .seealso: `PetscDrawLG`, `PetscDrawLGSetFromOptions()`, `PetscDrawLGCreate()`
610: @*/
611: PetscErrorCode PetscDrawLGSetOptionsPrefix(PetscDrawLG lg, const char prefix[])
612: {
613:   PetscFunctionBegin;
615:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lg, prefix));
616:   PetscFunctionReturn(PETSC_SUCCESS);
617: }

619: /*@
620:   PetscDrawLGSetFromOptions - Sets options related to the line graph object

622:   Collective

624:   Input Parameters:
625: . lg - the line graph context

627:   Options Database Key:
628: . -lg_use_markers (true|false) - true means it draws a marker for each point

630:   Level: intermediate

632: .seealso: `PetscDrawLG`, `PetscDrawLGDestroy()`, `PetscDrawLGCreate()`
633: @*/
634: PetscErrorCode PetscDrawLGSetFromOptions(PetscDrawLG lg)
635: {
636:   PetscBool           usemarkers, set;
637:   PetscDrawMarkerType markertype;

639:   PetscFunctionBegin;

642:   PetscCall(PetscDrawGetMarkerType(lg->win, &markertype));
643:   PetscCall(PetscOptionsGetEnum(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_marker_type", PetscDrawMarkerTypes, (PetscEnum *)&markertype, &set));
644:   if (set) {
645:     PetscCall(PetscDrawLGSetUseMarkers(lg, PETSC_TRUE));
646:     PetscCall(PetscDrawSetMarkerType(lg->win, markertype));
647:   }
648:   usemarkers = lg->use_markers;
649:   PetscCall(PetscOptionsGetBool(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_use_markers", &usemarkers, &set));
650:   if (set) PetscCall(PetscDrawLGSetUseMarkers(lg, usemarkers));
651:   PetscFunctionReturn(PETSC_SUCCESS);
652: }