figure.py

4.7 kB · python · 144 lines

1import os23# STYLE45FONT = "Helvetica,Arial,sans-serif"6# PALETTE7INK = "#000000"8MUTED = "#8e8e93"9PALE = "#bababf"10PAPER = "#ffffff"11CONCEPT = {12    "gasket": "#00cad8",13    "carpet": "#008cff",14    "sponge": "#6768fa",15    "prime": "#ff325a",16    "bound": "#ff8f2c",17    "window": "#ff3d40",18    "control": "#8e8e93",19}20PALETTE = {21    "black": "#000000",22    "white": "#ffffff",23    "red": "#ff3d40",24    "red-light": "#ff9d95",25    "red-dark": "#a80016",26    "orange": "#ff8f2c",27    "orange-light": "#ffc093",28    "orange-dark": "#a25400",29    "yellow": "#ffd100",30    "yellow-light": "#ffe591",31    "yellow-dark": "#9e8100",32    "green": "#32cc58",33    "green-light": "#5eee79",34    "green-dark": "#007f2c",35    "mint": "#00d1bb",36    "mint-light": "#48efd8",37    "mint-dark": "#008173",38    "teal": "#00cad8",39    "teal-light": "#48e9f7",40    "teal-dark": "#007c85",41    "cyan": "#1ec9f3",42    "cyan-light": "#86e2ff",43    "cyan-dark": "#007c98",44    "blue": "#008cff",45    "blue-light": "#84bdff",46    "blue-dark": "#00559f",47    "indigo": "#6768fa",48    "indigo-light": "#9ea9ff",49    "indigo-dark": "#3c2abc",50    "purple": "#d332e9",51    "purple-light": "#f08aff",52    "purple-dark": "#870097",53    "pink": "#ff325a",54    "pink-light": "#ff9a9f",55    "pink-dark": "#a50030",56    "brown": "#b18462",57    "brown-light": "#dfaf8c",58    "brown-dark": "#754c2b",59    "gray": "#8e8e93",60    "gray-light": "#bababf",61    "gray-dark": "#56565a",62}63# PALETTE END64STROKE = 1.265THIN = 0.666MARGIN = 366768def esc(s):69    return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")7071def header(width, height):72    return ['<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d" width="%d" height="%d">' % (width, height, width, height), '<rect width="%d" height="%d" fill="%s"/>' % (width, height, PAPER)]7374def text(x, y, s, size=11, fill=INK, anchor="start", weight=None):75    w = ' font-weight="%s"' % weight if weight else ""76    return '<text x="%.1f" y="%.1f" font-family="%s" font-size="%d" fill="%s" text-anchor="%s"%s>%s</text>' % (x, y, FONT, size, fill, anchor, w, esc(s))7778def line(x1, y1, x2, y2, stroke=INK, width=STROKE):79    return '<line x1="%.1f" y1="%.1f" x2="%.1f" y2="%.1f" stroke="%s" stroke-width="%.1f"/>' % (x1, y1, x2, y2, stroke, width)8081def rect(x, y, w, h, fill, opacity=1.0):82    return '<rect x="%.1f" y="%.1f" width="%.1f" height="%.1f" fill="%s" opacity="%.2f"/>' % (x, y, w, h, fill, opacity)8384def circle(x, y, r, fill):85    return '<circle cx="%.1f" cy="%.1f" r="%.1f" fill="%s"/>' % (x, y, r, fill)8687def save(parts, path):88    with open(path, "w") as handle:89        handle.write("\n".join(parts + ["</svg>"]) + "\n")9091# STYLE END9293# PINCER9495W = 90096H = 25097X0 = 6098X1 = 84099Y = 96100LOW = 0.4475978101HIGH = 0.640212102WINDOW = CONCEPT["window"]103104def px(t):105    return X0 + (X1 - X0) * t106107def build():108    p = header(W, H)109    p.append(rect(px(0), Y - 5, px(LOW) - px(0), 10, PALE))110    p.append(rect(px(HIGH), Y - 5, px(1) - px(HIGH), 10, PALE))111    p.append(rect(px(LOW), Y - 5, px(HIGH) - px(LOW), 10, WINDOW))112    p.append(line(px(0), Y, px(1) + 18, Y, INK, 1.5))113    for t, lab in ((0.0, "0"), (1.0, "1")):114        p.append(line(px(t), Y - 14, px(t), Y + 14, INK, 1.5))115        p.append(text(px(t), Y - 22, lab, 15, anchor="middle"))116    for t in (LOW, HIGH):117        p.append(line(px(t), Y - 20, px(t), Y + 20, INK, 2))118    p.append(text(px(0.22), Y - 22, "closed", 15, MUTED, "middle"))119    p.append(text(px(0.82), Y - 22, "closed", 15, MUTED, "middle"))120    p.append(text(px((LOW + HIGH) / 2), Y - 22, "open window", 15, WINDOW, "middle", weight="bold"))121    p.append(text(px(LOW) - 6, Y + 42, "0.4475978", 15, anchor="end"))122    p.append(text(px(LOW) - 6, Y + 60, "moment ladder", 12, MUTED, "end"))123    p.append(text(px(HIGH), Y + 42, "0.640212", 15, anchor="middle"))124    p.append(text(px(HIGH), Y + 60, "burst certificate", 12, MUTED, "middle"))125    for t, lab, dy, anchor in (126        (0.447931, "0.447931  ladder cap, only 0.00034 above the edge", 96, "start"),127        (0.5, "1/2  per-ray wall", 118, "start"),128        (0.605303, "0.605303  supergolden target", 140, "end"),129    ):130        p.append('<line x1="%.1f" y1="%.1f" x2="%.1f" y2="%.1f" stroke="%s" stroke-width="1" stroke-dasharray="4 4"/>' % (px(t), Y + 12, px(t), Y + dy - 12, PALE))131        off = 6 if anchor == "start" else -6132        p.append(text(px(t) + off, Y + dy, lab, 12, MUTED, anchor))133    p.append(text(px(0.5), 30, "Lemma G, the gasket case: the prime exponent beta = log_3 p / n", 16, anchor="middle", weight="bold"))134    return p135136def main():137    here = os.path.dirname(os.path.abspath(__file__))138    out = os.path.join(here, "..", "figures")139    os.makedirs(out, exist_ok=True)140    save(build(), os.path.join(out, "pincer.svg"))141    print("wrote figures/pincer.svg")142143if __name__ == "__main__":144    main()