hvega-0.12.0.7: tests/MarkTests.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
--
-- random mark-related tests
--
module MarkTests (testSpecs) where
import qualified Data.Text as T
import Data.List (intercalate)
#if !(MIN_VERSION_base(4, 12, 0))
import Data.Monoid ((<>))
#endif
import Text.Printf (printf)
import Graphics.Vega.VegaLite
testSpecs :: [(String, VegaLite)]
testSpecs = [ ("blendmode", blendMode)
, ("pieChart", pieChart)
, ("pieChartWithLabels", pieChartWithLabels)
, ("donutChart", donutChart)
, ("radialChart", radialChart)
, ("pyramidChart", pyramidChart)
, ("histogram_binned_no_x2", histogramBinnedNoX2)
]
-- How does blend-mode work (added in Vega-Lite 4.6.0)?
-- This is based on
-- https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode#Examples
--
blendData :: Data
blendData =
dataFromColumns []
. dataColumn "x" (Numbers [0])
. dataColumn "y" (Numbers [0])
$ []
-- rotate an ellipse about the origin; it would be better if I learned
-- how to use the arc path segment
--
-- angle in degrees
ellipse :: Double -> Symbol
ellipse ang =
let rad = ang * pi / 180
cosRot = cos rad
sinRot = sin rad
rmajor = 1.0
rminor = 0.3
p = printf "%.2f"
-- could learn to use the Arc path segment, but just do it manually
pair t =
let x = rmajor * cos t * cosRot - rminor * sin t * sinRot
y = rmajor * cos t * sinRot + rminor * sin t * cosRot
in "L " <> p x <> " " <> p y
thetas = [0, 0.25 .. 2 * pi]
path = intercalate " " (map pair thetas)
in SymPath (T.pack path)
-- Is there a better way to do this?
blendMode :: VegaLite
blendMode =
let ax t f = position t [ PName f
, PmType Quantitative
, PScale [SDomain (DNumbers [-5, 5])]
]
-- randomly trying to get similar results to the Mozilla page
props 0 = [GrX1 0.5, GrX2 0.5, GrY1 1, GrY2 0]
props 1 = [GrX1 0.7, GrX2 0.3, GrY1 0.1, GrY2 1]
props _ = [GrX1 1, GrX2 0, GrY1 1, GrY2 0]
gradient f =
let c | f == 0 = "rgb(0,255,0)"
| f == 1 = "rgb(255,0,0)"
| otherwise = "rgb(0,0,255)"
in MFillGradient GrLinear [(0, "white"), (1, c)] (props f)
lyr bm f =
let a | f == 0 = 0
| f == 1 = 45
| otherwise = -45
in asSpec [ mark Point [ MShape (ellipse a)
, MBlend bm
, gradient f
]
]
createLayer (bm, ttl) =
asSpec [ encoding . ax X "x" . ax Y "y" $ []
, layer (map (lyr bm) [0::Int .. 2])
, title ttl []
]
layers = map createLayer [ (BMNormal, "Normal")
, (BMMultiply, "Multiply")
, (BMScreen, "Screen")
, (BMOverlay, "Overlay")
, (BMDarken, "Darken")
, (BMLighten, "Lighten")
, (BMColorDodge, "Color-Dodge")
, (BMColorBurn, "Color-Burn")
, (BMHardLight, "Hard-Light")
, (BMSoftLight, "Soft-Light")
, (BMDifference, "Difference")
, (BMExclusion, "Exclusion")
, (BMHue, "Hue")
, (BMSaturation, "Saturation")
, (BMColor, "Color")
, (BMLuminosity, "Luminosity")
]
in toVegaLite [ configure
. configuration (Axis [Domain False, Labels False, Ticks False, NoTitle])
. configuration (PointStyle [MOpacity 1, MSize 40000, MStroke ""])
-- note the interesting background
. configuration (BackgroundStyle "rgba(255,255,255,0)")
$ []
, blendData
, columns 4
, vlConcat layers
]
pieChart :: VegaLite
pieChart =
let desc = description "A simple pie chart with embedded data."
dvals = dataFromColumns []
. dataColumn "category" (Numbers [1, 2, 3, 4, 5, 6])
. dataColumn "value" (Numbers [4, 6, 10, 3, 7, 8])
$ []
in toVegaLite [ desc
, dvals
, mark Arc []
, encoding
. position Theta [PName "value", PmType Quantitative]
. color [MName "category", MmType Nominal]
$ []
, viewBackground [VBNoStroke]
]
pieChartWithLabels :: VegaLite
pieChartWithLabels =
let desc = description "A simple pie chart with labels."
dvals = dataFromColumns []
. dataColumn "category" (Strings ["a", "b", "c", "d", "e", "f"])
. dataColumn "value" (Numbers [4, 6, 10, 3, 7, 8])
$ []
plot = [mark Arc [MOuterRadius 80]]
label = [ mark Text [MRadius 90]
, encoding (text [TName "category", TmType Nominal] [])
]
in toVegaLite [ desc
, dvals
, encoding
-- can not get stack: true, but should be the same
. position Theta [PName "value", PmType Quantitative, PStack StZero]
. color [MName "category", MmType Nominal, MLegend []]
$ []
, layer [asSpec plot, asSpec label]
, viewBackground [VBNoStroke]
]
donutChart :: VegaLite
donutChart =
let desc = description "A simple donut chart with embedded data."
dvals = dataFromColumns []
. dataColumn "category" (Numbers [1, 2, 3, 4, 5, 6])
. dataColumn "value" (Numbers [4, 6, 10, 3, 7, 8])
$ []
in toVegaLite [ desc
, dvals
, mark Arc [MInnerRadius 50]
, encoding
. position Theta [PName "value", PmType Quantitative]
. color [MName "category", MmType Nominal]
$ []
, viewBackground [VBNoStroke]
]
radialChart :: VegaLite
radialChart =
let desc = description "A simple radial chart with embedded data."
dvals = dataFromColumns []
. dataColumn "data" (Numbers [12, 23, 47, 6, 52, 19])
$ []
plot = [mark Arc [MInnerRadius 20, MStroke "#fff"]]
label = [ mark Text [MRadiusOffset 10]
, encoding (text [TName "data", TmType Quantitative] [])
]
in toVegaLite [ desc
, dvals
, encoding
-- can not get stack: true, but should be the same
. position Theta [PName "data", PmType Quantitative, PStack StZero]
. position R [ PName "data"
, PmType Quantitative
, PScale [ SType ScSqrt
, SZero True
, SRange (RPair 20 100)
]
]
. color [MName "data", MmType Nominal, MLegend []]
$ []
, layer [asSpec plot, asSpec label]
, viewBackground [VBNoStroke]
]
-- https://vega.github.io/vega-lite/examples/arc_pie_pyramid.html
--
pyramidChart :: VegaLite
pyramidChart =
let desc = description "Reproducing http://robslink.com/SAS/democd91/pyramid_pie.htm"
dvals = dataFromColumns []
. dataColumn "value" (Numbers [75, 10, 15])
. dataColumn "order" (Numbers [3, 1, 2])
. dataColumn "category" (Strings ["Sky", "Shady side of a pyramid", "Sunny side of a pyramid"])
$ []
cmap = [ ("Sky", "#416D9D")
, ("Shady side of a pyramid", "#674028")
, ("Sunny side of a pyramid", "#DEAC58")
]
in toVegaLite [ desc
, dvals
, mark Arc [MOuterRadius 80]
, encoding
. position Theta [ PName "value"
, PmType Quantitative
, PScale [SRange (RPair 2.35619449 8.639379797)]
-- How to get "stack": True???
, PStack StZero
]
. color [ MName "category"
, MmType Nominal
, MScale (categoricalDomainMap cmap)
, MLegend [ LOrient LONone
, LNoTitle
, LColumns 1
, LeX 200
, LeY 80
]
]
. order [OName "order"]
$ []
, viewBackground [VBNoStroke]
]
-- https://github.com/vega/vega-lite/pull/6473
-- as part of https://github.com/vega/vega-lite/issues/6086
histogramBinnedNoX2 :: VegaLite
histogramBinnedNoX2 =
let dvals = dataFromColumns []
. dataColumn "bin_start" (Numbers [8, 10, 12, 14, 16, 18, 20, 22])
. dataColumn "count" (Numbers [7, 29, 71, 127, 94, 54, 17, 5])
$ []
in toVegaLite [ dvals
, mark Bar []
, encoding
. position X [ PName "bin_start"
, PmType Quantitative
, PBin [AlreadyBinned True, Step 2]
]
. position Y [PName "count", PmType Quantitative]
$ []
]