Skip to content

Commit

Permalink
Merge pull request #36 from wirhabenzeit/main
Browse files Browse the repository at this point in the history
Bug fix for continuous legends, support for format-options and pdf exports in Plot.plot
  • Loading branch information
juba authored Jun 16, 2024
2 parents 03ea280 + c26ada1 commit afbee04
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 9 deletions.
9 changes: 7 additions & 2 deletions src/pyobsplot/js_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def plot(
spec: dict,
format: Literal["widget", "html", "svg", "png"] | None = None, # noqa: A002
path: str | None = None,
format_options: dict | None = None,
) -> ObsplotWidget | None:
"""
Plot.plot static method. If called directly, create an ObsplotWidget
Expand All @@ -36,18 +37,22 @@ def plot(
path : str | io.StringIO | None, optional
if provided, plot is saved to disk to an HTML file instead of displayed
as a jupyter widget, by default None
format_options : dict, optional
default output format options for typst formatter. Currently
possible keys are 'font' (name of font family), 'scale' (font scaling)
and 'margin' (margin around the plot, e.g. '1in' or '10pt')
"""
format_value = format
if path is not None and not isinstance(path, io.StringIO):
extension = Path(path).suffix.lower()[1:]
allowed_extensions = ["html", "svg", "pdf", "png"]
allowed_extensions = ["html", "svg", "pdf", "png", "pdf"]
if extension not in allowed_extensions:
msg = f"Output file extension should be one of {allowed_extensions}"
raise ValueError(msg)
format_value = format_value or extension

format_value = format_value or _plot_format
op = Obsplot(format=format_value) # type: ignore
op = Obsplot(format=format_value if format_value != "pdf" else "svg", format_options=format_options) # type: ignore
return op(spec, path=path)


Expand Down
7 changes: 5 additions & 2 deletions src/pyobsplot/obsplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def __init__(
format_options : dict, optional
default output format options for typst formatter. Currently
possible keys are 'font' (name of font family), 'scale' (font scaling)
and 'margin' (margin in pt around the plot)
and 'margin' (margin around the plot, e.g. '1in' or '10pt')
debug : bool, optional
activate debug mode, by default False
renderer : str, optional
Expand Down Expand Up @@ -395,13 +395,16 @@ def typst_render(
)
if "margin" in options:
value = options["margin"]
typst_content += f"margin: {value}pt,"
typst_content += f"margin: {value},"
if "font" in options:
value = options["font"]
typst_content += f'font-family: "{value}",'
if "scale" in options:
value = options["scale"]
typst_content += f"scale: {value},"
if "legend-padding" in options:
value = options["legend-padding"]
typst_content += f"legend-padding: {value},"
typst_content += ")"
typst_file.write(typst_content)

Expand Down
17 changes: 13 additions & 4 deletions src/pyobsplot/static/template.typ
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
file,
margin: 10pt,
font-family: ("San Francisco", "Segoe UI", "Noto Sans", "Roboto", "Cantarell", "Ubuntu", "Lucida Grande", "Arial"),
scale: 1
scale: 1,
legend-padding: 20,
) = {

set text(
Expand Down Expand Up @@ -54,8 +55,15 @@
let title = find-child(figure, "h2")
let subtitle = find-child(figure, "h3")
let caption = find-child(figure, "figcaption")
let figuresvg = find-child(figure, "svg")
let figurewidth = int(figuresvg.attrs.width)
let figuresvgs = figure.children.filter(e => "tag" in e and e.tag == "svg")
let legends = figuresvgs
.filter(svg => "ramp" in svg.attrs.class)
.map(svg => (..svg, attrs: (..svg.attrs,
width: str(int(svg.attrs.width) + 2*legend-padding),
viewbox: "-"+str(legend-padding)+" 0 "+str(int(svg.attrs.width)+legend-padding)+" "+str(int(svg.attrs.height)))
))
let mainfigure = figuresvgs.find(svg => "ramp" not in svg.attrs.class)
let figurewidth = calc.max(..figuresvgs.map(svg => int(svg.attrs.width)))

set page(
width: 1in*figurewidth/dpi + 2*margin,
Expand All @@ -78,7 +86,8 @@
v(1in * 8/dpi)
},
..figure.children.filter(e => e.tag == "div").map(swatch),
image.decode(encode-xml(figuresvg)),
..legends.map(svg => image.decode(encode-xml(svg), height: 1in * int(svg.attrs.height) / dpi)),
image.decode(encode-xml(mainfigure), height: 1in * int(mainfigure.attrs.height) / dpi),
if (caption != none) {
set text(size: 1in * 13/dpi, fill: rgb(85, 85, 85), weight: 500)
text(caption.children.first())
Expand Down
2 changes: 1 addition & 1 deletion src/pyobsplot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
]

# Allowed format options
ALLOWED_FORMAT_OPTIONS = ["font", "scale", "margin"]
ALLOWED_FORMAT_OPTIONS = ["font", "scale", "margin", "legend-padding"]

# Themes
AVAILABLE_THEMES = ["light", "dark", "current"]
Expand Down

0 comments on commit afbee04

Please sign in to comment.