Draw a chart

A how-to guide: a bar or a line chart in block graphics, from values given as fractions of the height.

from sextile import Custom, OnOneFrame, Page, PageLayout, PageRequest, PageRouter, Sextile
from sextile.viewdata.blocks import block_runs
from sextile.viewdata.canvas import Canvas
from sextile.viewdata.charting import bars
from sextile.viewdata.controls import Colour

router = PageRouter()

_RAINFALL = [0.2, 0.5, 0.9, 1.0, 0.6, 0.3]


@router.page("1", name="chart", title="Rainfall")
async def chart(request: PageRequest) -> Page:
    columns = block_runs(bars(_RAINFALL, across=12, down=9))

    def draw(canvas: Canvas, row: int) -> None:
        for offset, patterns in enumerate(columns):
            canvas.row(row + offset).mosaic(patterns, Colour.CYAN)

    return PageLayout(parts=[OnOneFrame(Custom(rows=len(columns), draw=draw))]).build(request)


app = Sextile(name="Weather", pages=[*router])
 RAINFALL                             1a
  
   🬹█                                   
  🬭██🬹                                  
 🬹█████                                 
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
  
 0 index                                

bars(values, across=, down=) takes each value as a fraction of the height — deciding what the top and bottom mean is the caller’s — and returns a grid of bits. block_runs turns any such grid into the six-bit mosaic patterns a row of cells holds, which canvas.row(n).mosaic(patterns, colour) draws.

curve draws a line instead of columns: it lights one block to a column and breaks the line at a missing value, rather than filling the blocks between two heights, so the line reads as a line and not a wall. For a fixed picture rather than data see Draw an icon; for the cost of the colour attribute see the graphics explanation.