plesty.lib.report ================= .. py:module:: plesty.lib.report .. autoapi-nested-parse:: Reports: what an analysis says about its result, in text, tables and figures. An analyzer returns a :class:`Report` from :meth:`~plesty.lib.analyzer.Analyzer.report`; the experiment saves it beside the outputs (:meth:`Report.save`); a reader — the bench's run export, a script writing a paper — loads it and renders it as HTML or LaTeX without importing the analyzer. See :mod:`plesty.lib.report.blocks` for the blocks and how table spans are written. Submodules ---------- .. toctree:: :maxdepth: 1 /reference/plesty/lib/report/blocks/index /reference/plesty/lib/report/html/index /reference/plesty/lib/report/latex/index /reference/plesty/lib/report/markup/index /reference/plesty/lib/report/svg/index /reference/plesty/lib/report/tables/index Attributes ---------- .. autoapisummary:: plesty.lib.report.REPORT_SUFFIX plesty.lib.report.SCHEMA_VERSION Exceptions ---------- .. autoapisummary:: plesty.lib.report.ReportError Classes ------- .. autoapisummary:: plesty.lib.report.Cell plesty.lib.report.Figure plesty.lib.report.Report plesty.lib.report.Table plesty.lib.report.Text plesty.lib.report.Value Functions --------- .. autoapisummary:: plesty.lib.report.array_table plesty.lib.report.data_table Package Contents ---------------- .. py:data:: REPORT_SUFFIX :value: '.report.json' .. py:data:: SCHEMA_VERSION :value: 1 .. py:class:: Cell Bases: :py:obj:`_Spanning` A cell of text, with inline markup (see :class:`Text`). :ivar content: What the cell says. .. py:attribute:: kind :type: ClassVar[str] :value: 'cell' .. py:attribute:: content :type: str :value: '' .. py:class:: Figure A plot, drawn from the drawables of :mod:`plesty.lib.monitor.plots`. ``Line`` and ``Scatter`` share one pair of axes; an ``Image`` fills them; ``Scalar`` and ``Text`` marks are set in the corner, as on screen. :ivar drawables: What to draw, in the order it is layered. :ivar title: What the figure shows. :ivar caption: A sentence below it. .. py:attribute:: kind :type: ClassVar[str] :value: 'figure' .. py:attribute:: drawables :type: list[plesty.lib.monitor.plots.Drawable] :value: [] .. py:attribute:: title :type: str :value: '' .. py:attribute:: caption :type: str :value: '' .. py:method:: __post_init__() -> None Check every item is a drawable. :raises ReportError: If one is not. .. py:method:: to_dict() -> dict[str, Any] Return the figure as JSON-ready values; arrays become lists. .. py:method:: from_dict(document: Mapping[str, Any]) -> Figure :classmethod: Rebuild a figure from :meth:`to_dict`. .. py:class:: Report What one analysis says about its result, in blocks, and who said it. :ivar blocks: Text, tables and figures, in reading order. :ivar title: What the analysis is, as a heading. :ivar provenance: The analyzer's stamp — its class, module, version and parameters (:meth:`~plesty.lib.analyzer.Analyzer.provenance`). .. py:attribute:: blocks :type: list[Any] :value: [] .. py:attribute:: title :type: str :value: '' .. py:attribute:: provenance :type: dict[str, Any] .. py:method:: __post_init__() -> None Turn each string into a :class:`Text`, then check every block. :raises ReportError: If a block is not a text, table or figure. .. py:method:: to_html(level: int = 2) -> str Render as an HTML fragment; see :func:`plesty.lib.report.html.to_html`. .. py:method:: to_latex() -> str Render as LaTeX; see :func:`plesty.lib.report.latex.to_latex`. .. py:method:: to_dict() -> dict[str, Any] Return the saved document: the blocks under :data:`REPORT_KEY`. .. py:method:: from_dict(document: Mapping[str, Any]) -> Report :classmethod: Rebuild a report from :meth:`to_dict`. :raises ReportError: If the document is not a report, was written by a newer plesty-lib than this one, or holds a block kind this one does not know. .. py:method:: save(path: str | pathlib.Path) -> pathlib.Path Write the report as JSON, atomically. :param path: Destination; by convention the outputs' stem plus :data:`REPORT_SUFFIX`. :returns: The written path. .. py:method:: load(path: str | pathlib.Path) -> Report :classmethod: Read a report written by :meth:`save`. :raises ReportError: As :meth:`from_dict`, or when the file is not JSON. .. py:exception:: ReportError Bases: :py:obj:`ValueError` Raised when a report, or a block in it, cannot be built or read. Initialize self. See help(type(self)) for accurate signature. .. py:class:: Table Header rows and body rows of cells, with notes and a caption. :ivar header: Header rows, each a list of cells. Spans stay within the header; they never reach into the body. :ivar rows: Body rows, each a list of cells. :ivar title: What the table shows, set above it. :ivar caption: A sentence below it. :ivar notes: Mark → text. A mark some cell refers to with ``note=`` is a footnote, set as a superscript (``"†"``); any other mark is a term being defined, such as a column label. :ivar columns: The table's width. Taken from the first row when left out. :ivar markup: Format → finished markup, for a :meth:`raw` table only. .. py:attribute:: kind :type: ClassVar[str] :value: 'table' .. py:attribute:: header :type: list[list[Any]] :value: [] .. py:attribute:: rows :type: list[list[Any]] :value: [] .. py:attribute:: title :type: str :value: '' .. py:attribute:: caption :type: str :value: '' .. py:attribute:: notes :type: dict[str, str] .. py:attribute:: columns :type: Optional[int] :value: None .. py:attribute:: markup :type: dict[str, str] .. py:method:: __post_init__() -> None Coerce every cell, take the width, and lay out the grid. :raises ReportError: If a row does not fill the width, spans overlap, a rowspan runs past its section, a note is referred to but never given, or a raw table also has cells. .. py:method:: footnotes() -> set[str] Return the note marks some cell refers to — the footnotes among the notes. .. py:method:: raw(html: Optional[str] = None, latex: Optional[str] = None, *, title: str = '', caption: str = '') -> Table :classmethod: Return a table given as finished markup, in one format or both. The escape hatch, for a table the cell structure cannot express. Each renderer uses the format it writes; a renderer whose format is missing says so instead of guessing. HTML from here is sanitised before it is shown, since a report is written by a third-party package. :param html: The table as HTML. :param latex: The table as LaTeX, a ``tabular`` or anything that goes inside a ``table`` environment. :param title: What the table shows. :param caption: A sentence below it. :returns: The table. :raises ReportError: If neither format is given. .. py:method:: layout(section: str) -> list[list[Slot]] Return a section's grid: one :class:`Slot` per row and column. :param section: ``"header"`` or ``"body"``. :returns: The rows of the section, each exactly :attr:`columns` wide. .. py:method:: to_dict() -> dict[str, Any] Return the table as JSON-ready values. .. py:method:: from_dict(document: Mapping[str, Any]) -> Table :classmethod: Rebuild a table from :meth:`to_dict`. .. py:class:: Text Prose, with inline markup. Paragraphs are separated by a blank line. Inside one: ``**bold**``, ``*italic*``, ```code``` and ``$math$`` in LaTeX notation — rendered as MathML in HTML and passed through unchanged to LaTeX. ``\$`` is a literal dollar sign. :ivar content: The text. .. py:attribute:: kind :type: ClassVar[str] :value: 'text' .. py:attribute:: content :type: str :value: '' .. py:method:: to_dict() -> dict[str, Any] Return the text as JSON-ready values. .. py:method:: from_dict(document: Mapping[str, Any]) -> Text :classmethod: Rebuild a text block from :meth:`to_dict`. .. py:class:: Value Bases: :py:obj:`_Spanning` A cell holding a number, and optionally its one-sigma uncertainty. The number is written once and each renderer formats it: ``11.5 ± 0.3`` in HTML, ``$11.5 \pm 0.3$`` in LaTeX. With an uncertainty, the precision follows it — two significant digits of the uncertainty when it starts with 1, 2 or 3, one otherwise — so a value never claims more digits than it has. :ivar value: The number; ``None`` or ``nan`` renders as a dash. :ivar err: Its one-sigma uncertainty. :ivar digits: Significant digits of a value without an uncertainty. .. py:attribute:: kind :type: ClassVar[str] :value: 'value' .. py:attribute:: value :type: Optional[float] :value: None .. py:attribute:: err :type: Optional[float] :value: None .. py:attribute:: digits :type: int :value: 4 .. py:method:: __post_init__() -> None Store plain Python numbers, so the cell saves as JSON as it is. .. py:method:: formatted() -> Optional[tuple[str, Optional[str], int]] Return the value and uncertainty as digits, and a shared power of ten. :returns: ``(value, err, exponent)`` — ``err`` is ``None`` without an uncertainty, and ``exponent`` is the power of ten both are scaled by (``0`` for most numbers). ``None`` when there is no value. .. py:function:: array_table(array: plesty.lib.data.array.PlestyArray, title: str = '', *, max_rows: int = MAX_ROWS) -> Optional[plesty.lib.report.blocks.Table] Tabulate one one-dimensional array as a single column. :param array: The array; its name, unit and description head the column. :param title: The table's title. :param max_rows: Refuse arrays longer than this. :returns: The table, or ``None`` for an array that is not 1-D or too long. .. py:function:: data_table(data: plesty.lib.data.experiment_data.ExperimentData, title: str = '', *, result_only: bool = True, max_rows: int = MAX_ROWS) -> Optional[plesty.lib.report.blocks.Table] Tabulate a piece of data from its kind's declared columns. Only the declared, one-dimensional arrays of one common length are tabulated, in declaration order. An array named as another's ``error`` is shown in that column rather than as its own. :param data: The data. :param title: The table's title. :param result_only: Leave out the columns declared ``result: False``. :param max_rows: Refuse arrays longer than this. :returns: The table, or ``None`` when the kind declares no columns or none of them can be tabulated.