Charts¶
A ChartView plots results, for example a quantity against time or a swept dimension. Its
series is a list of Series. Each series is a curve with its own x and y (as many of
each) and a name for the legend. A NaN leaves a gap in its curve.
from composeui.core.view import ChartView, Series, child
chart: ChartView = child(
ChartView, title="Pressure Drop", x_title="Flow Rate", x_unit="L/s", y_unit="kPa"
)
chart.series = [*chart.series, Series(name="D = 50 mm", x=flows, y=drops)]
As for the rows of a table, assign a new series list to draw the chart again. A job that
adds points does the same. The study saves the series.
Kinds of chart¶
The kind of the chart (ChartKind) draws the series as lines (LINE, the default) or
dots (SCATTER). The kind of a series overrides it, for example measurements as dots over
the curve of a model.
A BAR chart draws values per case: a group of bars for each of its categories, one bar
per series. The x of a series names a category by its index, and its y is the height of the
bar:
from composeui.core.view import ChartKind, ChartView, Series, child
energy: ChartView = child(
ChartView,
kind=ChartKind.BAR,
y_unit="kWh",
categories=["Kitchen", "Bedroom", "Office"],
series=[Series(name="Heating", x=[0, 1, 2], y=[120, 80, 95])],
)
Series.bars("Heating", [120, 80, 95]) makes the same series: a bar per value, in the
categories in order.
bar_chart, from composeui.core.dashboard, gives a view field a bar chart. It takes the
chart’s title and categories, and optionally its x_title, y_title, and height:
from composeui.core.dashboard import bar_chart
from composeui.core.view import ChartView
energy: ChartView = bar_chart("Energy", ["Kitchen", "Bedroom", "Office"], y_title="Energy")
With the dataframe extra, series_of(frame, x, y) from composeui.core.dataframesource
makes a series of two columns of a pandas, Polars, or PyArrow frame. It leaves out the rows
missing a value. Its name is the y column’s, or the name that you give.
Log axes¶
x_log and y_log make an axis a log axis. A log axis leaves out what it can’t show: the
chart doesn’t draw a point at an x of 0 or less, and a y of 0 or less leaves a gap.
Reference lines¶
reference_lines draws lines across the chart at values. Each line is a ReferenceLine:
A horizontal line at a y, for example a capacity.
With
vertical=True, a vertical line at an x, for example now. On a bar chart, the x is the index of a category.
from composeui.core.view import LineStyle, ReferenceLine
chart.reference_lines = [
ReferenceLine(40, "Max: 40", style=LineStyle.SOLID),
ReferenceLine(now, "Now", vertical=True),
]
Its
label(“Max: 40”) shows beside the line, not in the legend.Its
color("#rrggbb") defaults to the color of the theme’s text.Its
style(LineStyle) defaults toDASHED. The other styles areSOLID,DOTTED, andDASH_DOT.
The range of the chart includes the lines, so a line past the data still shows. On a log axis, the chart doesn’t draw a line at 0 or less. Textual draws each line solid, because a terminal has no dashes.
Colors, fill, steps, and height¶
The view holds data and labels. Each backend draws the chart in the colors of its theme, with these exceptions:
A series can have a
colorof its own ("#rrggbb"), the same in every theme, for example the color of a logo.fill=Truefills the area between the line of the series and 0, in its color.A series with
step=Trueholds each value until its next point, for example the number of jobs running over time. Withfill, it draws a step area. When the user hovers over the series, the chart shows the value held at the cursor.src/examples/taskview.pycharts its running tasks this way.
height sets the height of the chart on screen, in pixels, for example to keep the
proportions of a shape. A terminal row is about 16 pixels. None, the default, leaves the
height to the backend.
What each backend draws¶
Qt draws the chart with pyqtgraph (in the
pyside6extra). The mouse zooms and pans. When the user hovers over the chart, it shows the value of each series at the cursor.The web draws the chart with uPlot. The page loads uPlot once it shows a chart. A drag across the chart zooms, and a double click zooms back out. The legend shows the values at the cursor. Before the server sends a long series, it thins the series to the extremes of each bucket of its points.
Textual draws the chart with
textual-plotext(in thetuiextra), without zoom or hover.
A new series list keeps the user’s zoom.
src/examples/pipechart.py plots the pressure drop of a
pipe against its flow rate, with measurements over it, and the pressure of the pump as a
reference line (uv run python -m examples.pipechart --backend qt, or textual, or web).
Clicks on a chart¶
A click on the chart emits its point from clicked, in the values of the axes (x, then
y). Clicks work in Qt, and on the web, where a drag still zooms. A terminal has no pointer
to click with.
src/examples/batman.py draws the Batman logo, in its own
yellow and black, and says whether a click was on the bat
(uv run python -m examples.batman --backend web, or qt).
Report images¶
A chart on screen follows its window and its theme. The figure of a report has the size and
fonts of the page, and a light background. composeui.core.chartimage draws such a figure
from the data of the chart with matplotlib (the report extra). The figure is the same
whatever the backend, and needs no UI, for example in a batch run that writes the figures of
a report:
from pathlib import Path
from composeui.core.chartimage import ImageOptions, chart_figure, save_chart_image
save_chart_image(chart, Path("drop.pdf"), ImageOptions(width_mm=80, font_size=8))
figure = chart_figure(chart) # a matplotlib `Figure`, to annotate before saving it
The suffix of the file picks the format. PDF, SVG, and EPS keep their text as text. PNG is drawn at
dpi.x_rangeandy_rangeshow a region of the data.
Each backend offers this as Save Image. Its text is translated like the other built-in text.
Qt offers it in the context menu of the chart, at the region shown.
The web offers it in the corner of the figure, with a format to pick, at the user’s zoom.
Textual offers it with the
skey on a chart.
Without the report extra, Qt keeps the Export of pyqtgraph, and the web page draws a PNG
of the chart itself.