latest development:

`scratch $ pad 1.1 $ beside (r2 (-1,0)) (beside (r2 (0,-1)) (((unitSquare # fcA (color $ Color 0.2 0.2 0.2 0.05) # lw 0) <> (centerXY $ scaleX (1/1.5) $ scaleY (1/10) $ (clipped (pathFromTrail $ (closeTrail $ fromVertices (p2 <$> [(0.5,0),(0.5,10),(2,10),(2,0)]))) $ ((mconcat . zipWith line1 (zipWith LineConfig [0.01,0.02,0.03] (opacs 0.5 palette1)))) (fmap r2 <$> [ [(0.0,1.0),(1.0,1.0),(2.0,5.0)], [(0.0,0.0),(3.0,3.0)]]))))) (axis def (Range (0.5,2)))) (axis (axisOrientation .~ Y $ def) (Range (0,2)))`

This is my manual hack of what should happen to the line chart example when drawn using a scale different to the data scale.

Next step is to refactor back into the chartHub

This slowly growing collection of charts:

- renders nicely in svg over a wide chart size. png is not so good.
- renders similarly at different scale
- are opinionated minimalism
- are unit shapes in the spirit of the diagrams design space, making combining a snap.
- can be quickly integrated into ad-hoc haskell data analytics, providing a visual feedback loop.

Scatter

Scatters

Histogram

Histograms

Line

Lines

Labelled Bar Chart

Arrows Chart

Most of the api can be seen in the chartWith sig:

```
chartWith :: (Traversable f, Traversable g, R2 r) =>
ChartConfig
-> (g (f (r Double)) -> Chart b) -- double-containered R? chart renderer
-> V2 (Range Double) -- render range
-> (V2 (Range Double) -> g (f (r Double)) -> g (f (r Double))) -- scaler
-> g (f (r Double)) -- data
-> Chart b
chartWith (ChartConfig p axes) renderer range' scaler ms =
```

Double-containered dimensioned data covers what a chart charts - one or more data sets with at least an x and y dimension (called R2 in the linear library).

Most chart variations are about what to do with the extra dimensions in the data. A rectangle, for example, is built from 4 dimensions, an anchoring of position in XY space, with a width (W) and height (Z). A contour map is three dimensional data (V3 in linear), with placement as XY and color as Z.

A range represents boundaries of a space. Diagrams often uses unit to refer to a `V2 (Range (-0.5,0.5)) (Range (-0.5,0.5))`

.

A scaler converts data to other ranges, and helps get everything on the same page (literally).

Starting with the lowest level scatter chart (see examples/examples.hs for complete code):

`scatter1 def (xys 1000 0.7)`

The size of the dots scale with the data, so to bring it back, we run the data through a scaling routine, which normalises the data according to the diagrams unit, which is `V2 (-0.5,0.5) (-0.5,0.5)`

:

`scatter1 def $ ((\x -> scaleR2 (rangeR2 x) x) <$> (xys 1000 0.7))`

This scaling ensures that configuration paramters such as dot size, and axis look-n-feel is invariant to data scale. Hiding the scaling and axes creation in a more general function:

`scatter def [def] [xys 1000 0.7]`

The chart is then robust to a wide range of magnitudes:

`scatter def [def] $ fmap (1e-8 *) <$> [xys 1000 0.7]`

It's useful to separate a chart into two distinct bits:

the Chart. A concrete manifestation of data on the XY plane, with extra dimensions as aethestics (color, size, time, 1D or 3D projections into 2D)

the HUD. A Heads-Up-Display aka decoration around the chart designed to help users interpret and navigate the data representation.

The code below, for example, draws an X and Y axis without any data:

`chartHud def (const mempty) (V2 (Range (-1e8,1e8)) (Range (-1e-8,1e-8))) rescaleR2s ([[]] :: [[V2 Double]])`

HUDs can be built with chart routines. Here's a grid overlay that can be attached to any unit chart. Note how the axis ticks line up exactly with middle of the dots. I now think of the axes as a small subset of possible HUDs to help users interpret data.

`unitScatter def [def] [V2 <$> [0..10] <*> [0..10]]`

In constructing new chart units, I keep this list around:

- diagrams go from abstract to concrete
- start with the unitSquare: 4 points, 1x1, origin in the center
- work out where the origin should be, given the scaling needed.
- turn the pointful shape into a Trail
- close the Trail into a SVG-like loop
- turn the Trail into a QDiagram

You can slide up and down the various diagrams abstraction levels creating transformations at each level. For example, here's something I use to work at the point level:

`unitp f = unitSquare # f # fromVertices # closeTrail # strokeTrail`

```
scratch :: Chart SVG -> IO ()
scratch = fileSvg "other/scratchpad.svg" (400,400)
```

I tend to work in ghci a lot, using scratch to try code out, and mashing the refresh button in the browser.

As new charts emerge I then includ ethem in examples and integrate them with readme.md:

`stack install && chart-unit-examples && pandoc -f markdown -t html -i readme.md -o index.html --mathjax --filter pandoc-include`

Until I can work out a space leak, I'm letting png slide.

-- import Diagrams.Backend.Rasterific (Rasterific) -- scratchPng :: Chart Rasterific -> IO () -- scratchPng = filePng "other/scratchpad.png" (400,400) -- filePng "other/bar.png" s exampleBar