-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathelement_print.py
More file actions
89 lines (73 loc) · 3.48 KB
/
Copy pathelement_print.py
File metadata and controls
89 lines (73 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env python3
"""Print a chemical element card on the S01 thermal printer.
Draws a random (or chosen) element as a classic periodic-table tile -- atomic
number, big symbol, name, atomic mass -- then lists its properties and a summary.
Data: Bowserinator's Periodic-Table-JSON.
Examples:
python element_print.py # random element
python element_print.py --symbol Au
python element_print.py --number 26 # Iron
python element_print.py --no-print
"""
from __future__ import annotations
import argparse
from pathlib import Path
import random
from PIL import Image, ImageDraw
from print_common import ROOT, Card, font, get_json
DATA = "https://raw.githubusercontent.com/Bowserinator/Periodic-Table-JSON/master/PeriodicTableJSON.json"
def draw_tile(e: dict, size: int = 180) -> Image.Image:
img = Image.new("L", (size, size), 255)
d = ImageDraw.Draw(img)
d.rectangle((2, 2, size - 3, size - 3), outline=0, width=3)
d.text((12, 8), str(e["number"]), fill=0, font=font(True, 24))
d.text((size / 2, size * 0.46), e["symbol"], fill=0, font=font(True, 80), anchor="mm")
d.text((size / 2, size - 44), e["name"], fill=0, font=font(False, 18), anchor="mm")
d.text((size / 2, size - 22), f"{e['atomic_mass']:.3f}", fill=0, font=font(False, 16), anchor="mm")
return img
def pick(elements: list[dict], args) -> dict:
if args.symbol:
m = next((e for e in elements if e["symbol"].lower() == args.symbol.lower()), None)
if not m:
raise SystemExit(f"No element with symbol {args.symbol!r}")
return m
if args.number:
m = next((e for e in elements if e["number"] == args.number), None)
if not m:
raise SystemExit(f"No element with number {args.number}")
return m
return random.choice(elements)
def main() -> int:
parser = argparse.ArgumentParser(description="Print a chemical element card on the S01 thermal printer.")
g = parser.add_mutually_exclusive_group()
g.add_argument("--symbol", help="Element symbol (e.g. Au).")
g.add_argument("--number", type=int, help="Atomic number.")
parser.add_argument("--out", type=Path, default=ROOT / "element.png")
parser.add_argument("--darkness", type=int, choices=range(1, 6), default=3)
parser.add_argument("--bottom-feed", type=int, default=24)
parser.add_argument("--no-print", action="store_true")
args = parser.parse_args()
print("Fetching element data ...")
elements = get_json(DATA)["elements"]
e = pick(elements, args)
print(f" {e['number']} {e['symbol']} - {e['name']}")
group = e.get("group")
card = Card()
card.title("ELEMENT")
card.gap(2).image(draw_tile(e), border=False)
card.gap(4).divider()
card.kv("Atomic no.", str(e["number"]))
card.kv("Mass", f"{e['atomic_mass']:.3f} u")
card.kv("Category", e.get("category", "?"))
card.kv("Phase (STP)", e.get("phase", "?"))
card.kv("Period / Group", f"{e.get('period', '?')} / {group if group else '-'}")
if e.get("electron_configuration_semantic"):
card.kv("Config", e["electron_configuration_semantic"])
if e.get("discovered_by"):
card.kv("Discovered by", e["discovered_by"])
if e.get("summary"):
card.gap(2).divider(dashed=True).para(" ".join(e["summary"].split()), size=13, max_lines=7)
card.footer("periodic-table-json")
return card.finish(args.out, args.bottom_feed, args.darkness, do_print=not args.no_print)
if __name__ == "__main__":
raise SystemExit(main())