add "fill" action to the CLI, consolidate config generation
This commit is contained in:
@@ -10,7 +10,7 @@ def main() -> None:
|
||||
configure_logging(args.log_level)
|
||||
|
||||
if "func" in args:
|
||||
args.func(args)
|
||||
args.func(args, parser)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
import argparse
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from monobiome.cli import scheme, palette
|
||||
from monobiome.cli import fill, scheme, palette
|
||||
|
||||
logger: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -12,8 +12,8 @@ def configure_logging(log_level: int) -> None:
|
||||
|
||||
logger.setLevel(log_level)
|
||||
|
||||
def create_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
def create_parser() -> ArgumentParser:
|
||||
parser = ArgumentParser(
|
||||
description="Accent modeling CLI",
|
||||
)
|
||||
parser.add_argument(
|
||||
@@ -26,7 +26,8 @@ def create_parser() -> argparse.ArgumentParser:
|
||||
|
||||
subparsers = parser.add_subparsers(help="subcommand help")
|
||||
|
||||
palette.register_parser(subparsers)
|
||||
fill.register_parser(subparsers)
|
||||
scheme.register_parser(subparsers)
|
||||
palette.register_parser(subparsers)
|
||||
|
||||
return parser
|
||||
|
||||
78
monobiome/cli/fill.py
Normal file
78
monobiome/cli/fill.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
from argparse import Namespace, ArgumentParser
|
||||
|
||||
from symconf.template import Template, TOMLTemplate
|
||||
|
||||
from monobiome.util import _SubparserType
|
||||
from monobiome.palette import generate_palette
|
||||
|
||||
|
||||
def register_parser(subparsers: _SubparserType) -> None:
|
||||
parser = subparsers.add_parser(
|
||||
"fill",
|
||||
help="fill scheme templates for applications"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"scheme",
|
||||
type=str,
|
||||
help="scheme file path"
|
||||
)
|
||||
parser.add_argument(
|
||||
"template",
|
||||
nargs="?",
|
||||
help="template file path (defaults to stdin)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--palette",
|
||||
type=str,
|
||||
help="palette file to use for color definitions",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output",
|
||||
type=str,
|
||||
help="output file to write filled template",
|
||||
)
|
||||
|
||||
parser.set_defaults(func=handle_fill)
|
||||
|
||||
|
||||
def handle_fill(args: Namespace, parser: ArgumentParser) -> None:
|
||||
scheme = Path(args.scheme)
|
||||
output = args.output
|
||||
|
||||
if args.template is None:
|
||||
if sys.stdin.isatty():
|
||||
parser.error("no template provided (file or stdin)")
|
||||
return
|
||||
template_content = sys.stdin.read()
|
||||
elif args.template == "-":
|
||||
template_content = sys.stdin.read()
|
||||
else:
|
||||
try:
|
||||
template_content = Path(args.template).read_text()
|
||||
except OSError as e:
|
||||
parser.error(f"cannot read template file: {e}")
|
||||
|
||||
if args.palette:
|
||||
try:
|
||||
palette_toml = Path(args.palette).read_text()
|
||||
except OSError as e:
|
||||
parser.error(f"cannot read palette file: {e}")
|
||||
return
|
||||
else:
|
||||
palette_toml = generate_palette("hex", "toml")
|
||||
|
||||
palette_dict = tomllib.loads(palette_toml)
|
||||
concrete_scheme = TOMLTemplate(scheme).fill_dict(palette_dict)
|
||||
filled_template = Template(template_content).fill(concrete_scheme)
|
||||
|
||||
if output is None:
|
||||
print(filled_template)
|
||||
else:
|
||||
with Path(output).open("w") as f:
|
||||
f.write(filled_template)
|
||||
@@ -1,5 +1,5 @@
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from argparse import Namespace, ArgumentParser
|
||||
|
||||
from monobiome.util import _SubparserType
|
||||
from monobiome.palette import generate_palette
|
||||
@@ -37,7 +37,7 @@ def register_parser(subparsers: _SubparserType) -> None:
|
||||
parser.set_defaults(func=handle_palette)
|
||||
|
||||
|
||||
def handle_palette(args: argparse.Namespace) -> None:
|
||||
def handle_palette(args: Namespace, parser: ArgumentParser) -> None:
|
||||
notation = args.notation
|
||||
file_format = args.format
|
||||
output = args.output
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from argparse import Namespace, ArgumentParser
|
||||
|
||||
from monobiome.util import _SubparserType
|
||||
from monobiome.scheme import generate_scheme
|
||||
@@ -90,7 +90,7 @@ def register_parser(subparsers: _SubparserType) -> None:
|
||||
parser.set_defaults(func=handle_scheme)
|
||||
|
||||
|
||||
def handle_scheme(args: argparse.Namespace) -> None:
|
||||
def handle_scheme(args: Namespace, parser: ArgumentParser) -> None:
|
||||
output = args.output
|
||||
|
||||
mode = args.mode
|
||||
|
||||
@@ -9,8 +9,8 @@ def quad_bezier_rational(
|
||||
P1: float,
|
||||
P2: float,
|
||||
w: float,
|
||||
t: np.array,
|
||||
) -> np.array:
|
||||
t: np.ndarray,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Compute the point values of a quadratic rational Bezier curve.
|
||||
|
||||
@@ -32,7 +32,7 @@ def bezier_y_at_x(
|
||||
w: float,
|
||||
x: float,
|
||||
n: int = 400,
|
||||
) -> np.array:
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
For the provided QBR parameters, provide the curve value at the given
|
||||
input.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import json
|
||||
from typing import Any
|
||||
from functools import cache
|
||||
from importlib.metadata import version
|
||||
|
||||
@@ -12,7 +13,7 @@ from monobiome.constants import (
|
||||
|
||||
|
||||
@cache
|
||||
def compute_hlc_map(notation: str) -> dict[str, dict[int, str]]:
|
||||
def compute_hlc_map(notation: str) -> dict[str, Any]:
|
||||
hlc_map = {}
|
||||
|
||||
for h_str, Lpoints_Cstar in Lpoints_Cstar_Hmap.items():
|
||||
@@ -44,7 +45,7 @@ def generate_palette(
|
||||
hlc_map["version"] = mb_version
|
||||
return json.dumps(hlc_map, indent=4)
|
||||
else:
|
||||
toml_lines = [f"version = {mb_version}", ""]
|
||||
toml_lines = [f"version = \"{mb_version}\"", ""]
|
||||
for _h, _lc_map in hlc_map.items():
|
||||
toml_lines.append(f"[{_h}]")
|
||||
for _l, _c in _lc_map.items():
|
||||
|
||||
@@ -99,7 +99,7 @@ def palette_image(
|
||||
palette: dict[str, dict[int, str]],
|
||||
cell_size: int = 40,
|
||||
keys: list[str] | None = None
|
||||
) -> None:
|
||||
) -> tuple[np.ndarray, list[str], list[list[int]], int, int]:
|
||||
names = list(palette.keys()) if keys is None else keys
|
||||
|
||||
row_count = len(names)
|
||||
@@ -114,9 +114,9 @@ def palette_image(
|
||||
|
||||
for r, name in enumerate(names):
|
||||
shades = palette[name]
|
||||
keys = sorted(shades.keys())
|
||||
lightness_keys_per_row.append(keys)
|
||||
for c, k in enumerate(keys):
|
||||
lkeys = sorted(shades.keys())
|
||||
lightness_keys_per_row.append(lkeys)
|
||||
for c, k in enumerate(lkeys):
|
||||
col = Color(shades[k]).convert("srgb").fit(method="clip")
|
||||
rgb = [col["r"], col["g"], col["b"]]
|
||||
r0, r1 = r * cell_size, (r + 1) * cell_size
|
||||
@@ -129,26 +129,45 @@ def palette_image(
|
||||
def show_palette(
|
||||
palette: dict[str, dict[int, str]],
|
||||
cell_size: int = 40,
|
||||
keys: list[str] | None = None
|
||||
) -> None:
|
||||
keys: list[str] | None = None,
|
||||
show_labels: bool = True,
|
||||
dpi: int = 100,
|
||||
) -> tuple[plt.Figure, plt.Axes]:
|
||||
img, names, keys, cell_size, max_cols = palette_image(
|
||||
palette, cell_size, keys=keys
|
||||
)
|
||||
|
||||
fig_w = img.shape[1] / 100
|
||||
fig_h = img.shape[0] / 100
|
||||
fig, ax = plt.subplots(figsize=(fig_w, fig_h))
|
||||
|
||||
ax.imshow(img, interpolation="none", origin="upper")
|
||||
ax.set_xticks([])
|
||||
if show_labels:
|
||||
fig, ax = plt.subplots(figsize=(fig_w, fig_h), dpi=dpi)
|
||||
|
||||
ytick_pos = [(i + 0.5) * cell_size for i in range(len(names))]
|
||||
ax.set_yticks(ytick_pos)
|
||||
ax.set_yticklabels(names)
|
||||
ax.set_ylim(img.shape[0], 0) # ensures rows render w/o half-cells
|
||||
ax.imshow(img, interpolation="none", origin="upper")
|
||||
ax.set_xticks([])
|
||||
|
||||
plt.show()
|
||||
ytick_pos = [(i + 0.5) * cell_size for i in range(len(names))]
|
||||
ax.set_yticks(ytick_pos)
|
||||
ax.set_yticklabels(names)
|
||||
ax.set_ylim(img.shape[0], 0) # ensures rows render w/o half-cells
|
||||
|
||||
return fig, ax
|
||||
|
||||
fig = plt.figure(figsize=(fig_w, fig_h), dpi=dpi, frameon=False)
|
||||
ax = fig.add_axes((0, 0, 1, 1), frame_on=False)
|
||||
ax.imshow(
|
||||
img,
|
||||
interpolation="nearest",
|
||||
origin="upper",
|
||||
extent=(0, img.shape[1], img.shape[0], 0),
|
||||
aspect="auto",
|
||||
)
|
||||
ax.set_xlim(0, img.shape[1])
|
||||
ax.set_ylim(img.shape[0], 0)
|
||||
ax.axis("off")
|
||||
fig.subplots_adjust(0, 0, 1, 1, hspace=0, wspace=0)
|
||||
|
||||
return fig, ax
|
||||
|
||||
if __name__ == "__main__":
|
||||
keys = [
|
||||
|
||||
Reference in New Issue
Block a user