plesty.lib.report.blocks

What an analysis says about its result: text, tables and figures.

A Report is an ordered list of blocks, and there are three kinds:

  • Text — a paragraph with inline markup: **bold**, *italic*, `code` and $math$ in LaTeX notation.

  • Table — header rows and body rows of Cell and Value, with rowspan/colspan as in HTML, notes, and a caption.

  • Figure — the same drawables a live view draws (plesty.lib.monitor.plots), so a figure in a report and a view on screen are one vocabulary.

A block holds structure, never markup. Report.to_html() and Report.to_latex() render the same report for a browser and for a paper; Table.raw() is the escape hatch for a table that structure cannot say.

Spans are written the HTML way. A spanning cell is written once, where it starts; the positions it covers are left out of the rows below it and to its right. Every row, counting what spans into it from above, must fill the table’s width exactly, and spans may not overlap — both are checked when the table is built, naming the row, so a miscounted table fails where it is written rather than rendering lopsided:

Table(
    header=[
        [Cell("QD", rowspan=2), Cell("Splitting", colspan=2)],
        [Cell(r"$\Delta E$ (µeV)"), Cell(r"$\Delta\lambda$ (pm)")],
    ],
    rows=[
        [Cell("QD 3", rowspan=2), Value(11.5, err=0.3), Value(5.52, err=0.14)],
        [Value(12.1, err=0.4), Value(5.81, err=0.19)],
    ],
)

A report is saved as JSON (Report.save()) beside the outputs it describes, so a reader renders it without importing the analyzer that wrote it — the reader’s plesty-lib is routinely older than the writer’s, which is what SCHEMA_VERSION is for.

Attributes

SCHEMA_VERSION

REPORT_KEY

REPORT_SUFFIX

ALIGNS

MARKUP_FORMATS

DRAWABLES

CellLike

CELLS

Block

BLOCKS

Exceptions

ReportError

Raised when a report, or a block in it, cannot be built or read.

Classes

_Spanning

What every table cell has: its span, its alignment, and a note mark.

Cell

A cell of text, with inline markup (see Text).

Value

A cell holding a number, and optionally its one-sigma uncertainty.

Slot

What occupies one position of a table's grid.

Table

Header rows and body rows of cells, with notes and a caption.

Text

Prose, with inline markup.

Figure

A plot, drawn from the drawables of plesty.lib.monitor.plots.

Report

What one analysis says about its result, in blocks, and who said it.

Functions

_number(→ Optional[float])

Return a number as a Python int or float; nan becomes None.

_engineering(→ int)

Return the power of ten to factor out of a number, 0 unless extreme.

_decimals(→ int)

Return the decimal places an uncertainty is quoted to.

_fixed(→ str)

Return value rounded to decimals places, which may be negative.

_cell(→ _Spanning)

Coerce what a table was given for one position into a cell.

_cell_from_dict(→ _Spanning)

Rebuild a cell saved by _Spanning.to_dict().

_layout(→ list[list[Slot]])

Place a section's cells on its grid, checking every row fills it.

_json_value(→ Any)

Return a drawable field as JSON: arrays as lists, nan as None.

_drawable_to_dict(→ dict[str, Any])

Return a drawable as JSON-ready values, named by its kind.

_drawable_from_dict(→ plesty.lib.monitor.plots.Drawable)

Rebuild a drawable saved by _drawable_to_dict().

Module Contents

plesty.lib.report.blocks.SCHEMA_VERSION = 1
plesty.lib.report.blocks.REPORT_KEY = '__plesty_report__'
plesty.lib.report.blocks.REPORT_SUFFIX = '.report.json'
plesty.lib.report.blocks.ALIGNS: tuple[str, Ellipsis] = ('l', 'c', 'r')
plesty.lib.report.blocks.MARKUP_FORMATS: tuple[str, Ellipsis] = ('html', 'latex')
plesty.lib.report.blocks.DRAWABLES: dict[str, type[plesty.lib.monitor.plots.Drawable]]
exception plesty.lib.report.blocks.ReportError

Bases: ValueError

Raised when a report, or a block in it, cannot be built or read.

Initialize self. See help(type(self)) for accurate signature.

class plesty.lib.report.blocks._Spanning

What every table cell has: its span, its alignment, and a note mark.

Variables:
  • rowspan – Rows the cell covers, downwards from its own.

  • colspan – Columns the cell covers, rightwards from its own.

  • align – One of ALIGNS; None leaves it to the renderer — left for text, centred for values.

  • note – Mark of a table note this cell refers to, e.g. "†".

kind: ClassVar[str] = ''
rowspan: int = 1
colspan: int = 1
align: str | None = None
note: str | None = None
__post_init__() → None

Check the span and the alignment.

Raises:

ReportError – If a span is not a positive integer or the alignment is not one of ALIGNS.

Return type:

None

to_dict() → dict[str, Any]

Return the cell as JSON-ready values, leaving out every default.

Return type:

dict[str, Any]

class plesty.lib.report.blocks.Cell

Bases: _Spanning

A cell of text, with inline markup (see Text).

Variables:

content – What the cell says.

kind: ClassVar[str] = 'cell'
content: str = ''
class plesty.lib.report.blocks.Value

Bases: _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.

Variables:
  • value – The number; None or nan renders as a dash.

  • err – Its one-sigma uncertainty.

  • digits – Significant digits of a value without an uncertainty.

kind: ClassVar[str] = 'value'
value: float | None = None
err: float | None = None
digits: int = 4
__post_init__() → None

Store plain Python numbers, so the cell saves as JSON as it is.

Return type:

None

formatted() → tuple[str, str | None, int] | None

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.

Return type:

Optional[tuple[str, Optional[str], int]]

plesty.lib.report.blocks.CellLike
plesty.lib.report.blocks.CELLS: dict[str, type[_Spanning]]
plesty.lib.report.blocks._number(value: Any) → float | None

Return a number as a Python int or float; nan becomes None.

Parameters:

value (Any)

Return type:

Optional[float]

plesty.lib.report.blocks._engineering(magnitude: float) → int

Return the power of ten to factor out of a number, 0 unless extreme.

Parameters:

magnitude (float)

Return type:

int

plesty.lib.report.blocks._decimals(err: float) → int

Return the decimal places an uncertainty is quoted to.

Parameters:

err (float)

Return type:

int

plesty.lib.report.blocks._fixed(value: float, decimals: int) → str

Return value rounded to decimals places, which may be negative.

Parameters:
  • value (float)

  • decimals (int)

Return type:

str

plesty.lib.report.blocks._cell(value: Any) → _Spanning

Coerce what a table was given for one position into a cell.

Parameters:

value (Any)

Return type:

_Spanning

class plesty.lib.report.blocks.Slot

What occupies one position of a table’s grid.

Variables:
  • state – "cell" where a cell starts; "below" in the first column of a cell spanning down from an earlier row; "covered" anywhere else a span reaches.

  • cell – The cell that starts at, or spans over, this position.

state: str
cell: _Spanning
class plesty.lib.report.blocks.Table

Header rows and body rows of cells, with notes and a caption.

Variables:
  • header – Header rows, each a list of cells. Spans stay within the header; they never reach into the body.

  • rows – Body rows, each a list of cells.

  • title – What the table shows, set above it.

  • caption – A sentence below it.

  • 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.

  • columns – The table’s width. Taken from the first row when left out.

  • markup – Format → finished markup, for a raw() table only.

kind: ClassVar[str] = 'table'
header: list[list[Any]] = []
rows: list[list[Any]] = []
title: str = ''
caption: str = ''
notes: dict[str, str]
columns: int | None = None
markup: dict[str, str]
__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.

Return type:

None

footnotes() → set[str]

Return the note marks some cell refers to — the footnotes among the notes.

Return type:

set[str]

classmethod raw(html: str | None = None, latex: str | None = None, *, title: str = '', caption: str = '') → Table

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.

Parameters:
  • html (Optional[str]) – The table as HTML.

  • latex (Optional[str]) – The table as LaTeX, a tabular or anything that goes inside a table environment.

  • title (str) – What the table shows.

  • caption (str) – A sentence below it.

Returns:

The table.

Raises:

ReportError – If neither format is given.

Return type:

Table

layout(section: str) → list[list[Slot]]

Return a section’s grid: one Slot per row and column.

Parameters:

section (str) – "header" or "body".

Returns:

The rows of the section, each exactly columns wide.

Return type:

list[list[Slot]]

to_dict() → dict[str, Any]

Return the table as JSON-ready values.

Return type:

dict[str, Any]

classmethod from_dict(document: Mapping[str, Any]) → Table

Rebuild a table from to_dict().

Parameters:

document (Mapping[str, Any])

Return type:

Table

plesty.lib.report.blocks._cell_from_dict(document: Any) → _Spanning

Rebuild a cell saved by _Spanning.to_dict().

Parameters:

document (Any)

Return type:

_Spanning

plesty.lib.report.blocks._layout(rows: Sequence[Sequence[_Spanning]], width: int, section: str) → list[list[Slot]]

Place a section’s cells on its grid, checking every row fills it.

Raises:

ReportError – Naming the section and the row (from 1) that is wrong.

Parameters:
  • rows (Sequence[Sequence[_Spanning]])

  • width (int)

  • section (str)

Return type:

list[list[Slot]]

class plesty.lib.report.blocks.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.

Variables:

content – The text.

kind: ClassVar[str] = 'text'
content: str = ''
to_dict() → dict[str, Any]

Return the text as JSON-ready values.

Return type:

dict[str, Any]

classmethod from_dict(document: Mapping[str, Any]) → Text

Rebuild a text block from to_dict().

Parameters:

document (Mapping[str, Any])

Return type:

Text

class plesty.lib.report.blocks.Figure

A plot, drawn from the drawables of 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.

Variables:
  • drawables – What to draw, in the order it is layered.

  • title – What the figure shows.

  • caption – A sentence below it.

kind: ClassVar[str] = 'figure'
drawables: list[plesty.lib.monitor.plots.Drawable] = []
title: str = ''
caption: str = ''
__post_init__() → None

Check every item is a drawable.

Raises:

ReportError – If one is not.

Return type:

None

to_dict() → dict[str, Any]

Return the figure as JSON-ready values; arrays become lists.

Return type:

dict[str, Any]

classmethod from_dict(document: Mapping[str, Any]) → Figure

Rebuild a figure from to_dict().

Parameters:

document (Mapping[str, Any])

Return type:

Figure

plesty.lib.report.blocks._json_value(value: Any) → Any

Return a drawable field as JSON: arrays as lists, nan as None.

Parameters:

value (Any)

Return type:

Any

plesty.lib.report.blocks._drawable_to_dict(item: plesty.lib.monitor.plots.Drawable) → dict[str, Any]

Return a drawable as JSON-ready values, named by its kind.

Parameters:

item (plesty.lib.monitor.plots.Drawable)

Return type:

dict[str, Any]

plesty.lib.report.blocks._drawable_from_dict(document: Mapping[str, Any]) → plesty.lib.monitor.plots.Drawable

Rebuild a drawable saved by _drawable_to_dict().

Parameters:

document (Mapping[str, Any])

Return type:

plesty.lib.monitor.plots.Drawable

plesty.lib.report.blocks.Block
plesty.lib.report.blocks.BLOCKS: dict[str, Any]
class plesty.lib.report.blocks.Report

What one analysis says about its result, in blocks, and who said it.

Variables:
  • blocks – Text, tables and figures, in reading order.

  • title – What the analysis is, as a heading.

  • provenance – The analyzer’s stamp — its class, module, version and parameters (provenance()).

blocks: list[Any] = []
title: str = ''
provenance: dict[str, Any]
__post_init__() → None

Turn each string into a Text, then check every block.

Raises:

ReportError – If a block is not a text, table or figure.

Return type:

None

to_html(level: int = 2) → str

Render as an HTML fragment; see plesty.lib.report.html.to_html().

Parameters:

level (int)

Return type:

str

to_latex() → str

Render as LaTeX; see plesty.lib.report.latex.to_latex().

Return type:

str

to_dict() → dict[str, Any]

Return the saved document: the blocks under REPORT_KEY.

Return type:

dict[str, Any]

classmethod from_dict(document: Mapping[str, Any]) → Report

Rebuild a report from 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.

Parameters:

document (Mapping[str, Any])

Return type:

Report

save(path: str | pathlib.Path) → pathlib.Path

Write the report as JSON, atomically.

Parameters:

path (str | pathlib.Path) – Destination; by convention the outputs’ stem plus REPORT_SUFFIX.

Returns:

The written path.

Return type:

pathlib.Path

classmethod load(path: str | pathlib.Path) → Report

Read a report written by save().

Raises:

ReportError – As from_dict(), or when the file is not JSON.

Parameters:

path (str | pathlib.Path)

Return type:

Report