|
| 1 | +""" |
| 2 | +(Re)create the `geometries.rst` document. |
| 3 | +""" |
| 4 | + |
| 5 | +import datetime |
| 6 | +import pathlib |
| 7 | +from collections import defaultdict |
| 8 | + |
| 9 | +from pyRestTable import Table |
| 10 | + |
| 11 | +import hklpy2 |
| 12 | + |
| 13 | +DOCS_DIR = pathlib.Path(__file__).parent / "source" |
| 14 | +GEO_DOC = DOCS_DIR / "geometry_tables.rst" |
| 15 | +H1, H2, H3, H4 = "= - ^ ~".split() |
| 16 | + |
| 17 | +PREFACE = """ |
| 18 | +Tables are provided for the different geometries (sorted by number of real axes) |
| 19 | +and then, for each geometry, the calculation engines, modes of operation, pseudo |
| 20 | +axes required, and any additional parameters required by the |
| 21 | +:meth:`~hklpy2.backends.base.SolverBase.mode`. The mode defines which axes will |
| 22 | +be computed, which will be held constant, and any relationships between axes. |
| 23 | +""" |
| 24 | + |
| 25 | + |
| 26 | +def title(text: str, underchar: str = H1, both: bool = False) -> str: |
| 27 | + bars = underchar * len(text) |
| 28 | + result = f"{text}\n{bars}\n" |
| 29 | + if both: |
| 30 | + result = f"{bars}\n{result}" |
| 31 | + return result |
| 32 | + |
| 33 | + |
| 34 | +def page_header(): |
| 35 | + text = [ |
| 36 | + f".. author: {__file__.split('/')[-1]}", |
| 37 | + f".. date: {datetime.datetime.now()}", |
| 38 | + "", |
| 39 | + ".. _geometries:", |
| 40 | + "", |
| 41 | + title("Diffractometer Geometries", underchar=H1, both=True), |
| 42 | + ".. index:: geometries", |
| 43 | + "", |
| 44 | + ] |
| 45 | + return "\n".join(text) |
| 46 | + |
| 47 | + |
| 48 | +def rst_anchor(sname: str, gname: str) -> str: |
| 49 | + safe_gname = gname.replace(" ", "_") |
| 50 | + return f"geometries.{sname}.{safe_gname}" |
| 51 | + |
| 52 | + |
| 53 | +def table_of_reals(): |
| 54 | + # Count the reals. |
| 55 | + circles = defaultdict(list) |
| 56 | + for sname in sorted(hklpy2.solvers()): |
| 57 | + Solver = hklpy2.get_solver(sname) |
| 58 | + geometries = Solver.geometries() |
| 59 | + if len(geometries) == 0: |
| 60 | + continue |
| 61 | + for gname in sorted(Solver.geometries()): |
| 62 | + solver = Solver(gname) |
| 63 | + n = len(solver.real_axis_names) |
| 64 | + anchor = f":ref:`{sname}, {gname} <{rst_anchor(sname, gname)}>`" |
| 65 | + circles[n].append(anchor) |
| 66 | + |
| 67 | + # Build the table, sorted by number of reals. |
| 68 | + table = Table() |
| 69 | + table.labels = ["#reals", "solver, geometry"] |
| 70 | + for n, anchors in sorted(circles.items()): |
| 71 | + for anchor in anchors: |
| 72 | + table.addRow((n, anchor)) |
| 73 | + |
| 74 | + # Build the report. |
| 75 | + text = [ |
| 76 | + ".. _geometries.number_of_reals:", |
| 77 | + "", |
| 78 | + title("Geometries, by number of real axes", H1), |
| 79 | + ".. index:: geometries; by number of reals", |
| 80 | + "", |
| 81 | + "The different diffractometer geometries are distinguished,", |
| 82 | + "primarily, by the number of real axes. This", |
| 83 | + "table is sorted first by the number of real axes, then by", |
| 84 | + "solver and geometry names.", |
| 85 | + "", |
| 86 | + str(table), |
| 87 | + ] |
| 88 | + return "\n".join(text) |
| 89 | + |
| 90 | + |
| 91 | +def geometry_summary_table(solver_name, geometry_name: str) -> str: |
| 92 | + text = [ |
| 93 | + f".. _{rst_anchor(solver_name, geometry_name)}:", |
| 94 | + "", |
| 95 | + title(f"solver={solver_name!r}, geometry={geometry_name!r}", H2), |
| 96 | + f".. index:: geometries; {solver_name}; {geometry_name}", |
| 97 | + "", |
| 98 | + str(hklpy2.get_solver(solver_name)(geometry=geometry_name).summary), |
| 99 | + ] |
| 100 | + return "\n".join(text) |
| 101 | + |
| 102 | + |
| 103 | +def all_summary_tables(): |
| 104 | + text = [ |
| 105 | + ".. _geometries.summary_tables:", |
| 106 | + "", |
| 107 | + title("Available Solver Geometry Tables", H1), |
| 108 | + ".. index:: geometries; tables", |
| 109 | + "", |
| 110 | + ".. seealso:: :func:`hklpy2.user.solver_summary()`", |
| 111 | + "", |
| 112 | + ] |
| 113 | + |
| 114 | + for sname in sorted(hklpy2.solvers()): |
| 115 | + Solver = hklpy2.get_solver(sname) |
| 116 | + geometries = Solver.geometries() |
| 117 | + if len(geometries) == 0: |
| 118 | + continue |
| 119 | + for gname in sorted(Solver.geometries()): |
| 120 | + text.append(geometry_summary_table(sname, gname)) |
| 121 | + |
| 122 | + return "\n".join(text) |
| 123 | + |
| 124 | + |
| 125 | +def main(): |
| 126 | + text = [ |
| 127 | + page_header(), |
| 128 | + PREFACE, |
| 129 | + table_of_reals(), |
| 130 | + all_summary_tables(), |
| 131 | + ] |
| 132 | + with open(GEO_DOC, "w") as f: |
| 133 | + f.write("\n".join(text)) |
| 134 | + |
| 135 | + |
| 136 | +if __name__ == "__main__": |
| 137 | + main() |
0 commit comments