plot-light 0.2.3 → 0.2.4
raw patch · 4 files changed
+95/−70 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Graphics.Rendering.Plot.Light: heatmap :: FigureData Rational -> [Colour Double] -> [[Scientific]] -> Svg
Files
- app/heatmap/Main.hs +7/−64
- plot-light.cabal +2/−2
- src/Graphics/Rendering/Plot/Light.hs +3/−1
- src/Graphics/Rendering/Plot/Light/PlotTypes/Heatmap.hs +83/−3
app/heatmap/Main.hs view
@@ -1,7 +1,7 @@ module Main where -import Control.Monad (forM_)-import Data.Ratio+-- import Control.Monad (forM_)+-- import Data.Ratio import Graphics.Rendering.Plot.Light import Graphics.Rendering.Plot.Light.PlotTypes@@ -17,7 +17,6 @@ import qualified Data.Colour as C import qualified Data.Colour.Palette.BrewerSet as CP --- main = print "hello" fname = "data/heatmap-bw"@@ -33,72 +32,16 @@ palette :: [C.Colour Double] palette = CP.brewerSet CP.GnBu nColors +main :: IO () main = do dat <- T.readFile fname let pd = A.parseOnly (gridNum space) dat case pd of Left e -> error e Right d -> do- let (nh, nw, vmin, vmax, d') = prepData d- w = xPlot / nw- h = yPlot / nh- from = Frame (Point 0 0) (Point 1 1)- to = frameFromFigData fdat- pixels = forM_ d' (mkPixel w h vmin vmax . toFigFrame from to)- svg_t = svgHeader (mkFrameOrigin xPlot yPlot) pixels--- -- putStrLn $ renderSvg svg_t- T.writeFile fnameOut $ T.pack $ renderSvg svg_t --toFigFrame- :: Fractional a =>- Frame a -> Frame a -> LabeledPoint l Rational -> LabeledPoint l a-toFigFrame from to = moveLabeledPointBwFrames from to False False . fromRationalLP--fromRationalLP :: Fractional a => LabeledPoint l Rational -> LabeledPoint l a-fromRationalLP (LabeledPoint (Point x y) l) = LabeledPoint (Point (fromRational x) (fromRational y)) l---mkPixel- :: (Show a, RealFrac a) =>- a- -> a- -> Scientific- -> Scientific- -> LabeledPoint Scientific a- -> Svg-mkPixel w h vmin vmax (LabeledPoint p l) = rect w h 0 Nothing (Just col) p where- col = pickColor (toFloat vmin) (toFloat vmax) (toFloat l)- --pickColor :: RealFrac t => t -> t -> t -> C.Colour Double-pickColor xmin xmax x = palette !! i- where- i = floor (x01 * fromIntegral (nColors - 1))- x01 = (x-xmin)/(xmax - xmin)-----prepData ::- Ord t => [[t]] -> (Rational, Rational, t, t, [LabeledPoint t Rational])-prepData ll = (nh, nw, valMin, valMax, d')- where- nh = toRational $ length ll- nw = toRational $ length (head ll)- d' = toUnitFramedLP nw nh <$> toCoord ll- valMin = minimum $ _lplabel <$> d'- valMax = maximum $ _lplabel <$> d'- - --toCoord :: (Num i, Enum i) => [[c]] -> [(i, i, c)]-toCoord ll = concat $ reverse $ go 0 ll [] where- go i (x:xs) acc = go (i + 1) xs $ zip3 (repeat i) [0 ..] x : acc- go _ [] acc = acc--toUnitFramedLP :: (Fractional t) =>- t -> t -> (t, t, l) -> LabeledPoint l t-toUnitFramedLP w h (i, j, x) = LabeledPoint p x- where p = Point (i/h) (j/w)+ let pixels = heatmap fdat palette d+ svg_t = svgHeader (mkFrameOrigin xPlot yPlot) pixels+ -- putStrLn $ renderSvg svg_t+ T.writeFile fnameOut $ T.pack $ renderSvg svg_t
plot-light.cabal view
@@ -1,7 +1,7 @@ name: plot-light-version: 0.2.3+version: 0.2.4 synopsis: A lightweight plotting library, exporting to SVG-description: A lightweight plotting library, exporting to SVG+description: This library provides drawing and plotting datastructures and functions; it is aimed in particular at scientific visualization, but it also exposes its plotting primitives and a general purpose 2D geometry library. homepage: https://github.com/ocramz/plot-light license: BSD3 license-file: LICENSE
src/Graphics/Rendering/Plot/Light.hs view
@@ -20,6 +20,8 @@ -- @import qualified Data.Colour.Names as C@ module Graphics.Rendering.Plot.Light (+ -- * Plot types+ heatmap, -- * Plot elements -- ** Geometrical primitives rect, rectCentered, circle, line, text, polyline, filledPolyline,@@ -66,7 +68,7 @@ -- import qualified Data.Colour.SRGB as C import Graphics.Rendering.Plot.Light.Internal-+import Graphics.Rendering.Plot.Light.PlotTypes
src/Graphics/Rendering/Plot/Light/PlotTypes/Heatmap.hs view
@@ -1,14 +1,94 @@-module Graphics.Rendering.Plot.Light.PlotTypes.Heatmap where-+module Graphics.Rendering.Plot.Light.PlotTypes.Heatmap (heatmap) where +import Data.Scientific (Scientific, toRealFloat) import Graphics.Rendering.Plot.Light.Internal +import Text.Blaze.Svg +import Control.Monad (forM_) +-- import qualified Data.Colour.Names as C+import qualified Data.Colour as C+import Data.Colour.Palette.BrewerSet+-- import Text.Blaze.Svg +-- | A 2D heatmap plot+--+-- `heatmap` assumes the input data corresponds to evenly sampled values of a scalar-valued field, and it maps the data values onto the provided `palette` (which can be created e.g. with `brewerSet`).+heatmap+ :: FigureData Rational -- ^ Figure data+ -> [C.Colour Double] -- ^ Colour palette+ -> [[Scientific]] -- ^ Data+ -> Svg+heatmap fdat palette d = do+ let (nh, nw, vmin, vmax, d') = prepData d+ w = figWidth fdat / nw+ h = figHeight fdat / nh+ from = Frame (Point 0 0) (Point 1 1)+ to = frameFromFigData fdat+ forM_ d' (mkPixel palette w h vmin vmax . toFigFrame from to) --- hmPlot fd++toFigFrame+ :: Fractional a =>+ Frame a -> Frame a -> LabeledPoint l Rational -> LabeledPoint l a+toFigFrame from to = moveLabeledPointBwFrames from to False False . fromRationalLP++fromRationalLP :: Fractional a => LabeledPoint l Rational -> LabeledPoint l a+fromRationalLP (LabeledPoint (Point x y) l) = LabeledPoint (Point (fromRational x) (fromRational y)) l+++mkPixel+ :: (Show a, RealFrac a) =>+ [C.Colour Double]+ -> a+ -> a+ -> Scientific+ -> Scientific+ -> LabeledPoint Scientific a+ -> Svg+mkPixel palette w h vmin vmax (LabeledPoint p l) = rect w h 0 Nothing (Just col) p where+ col = pickColor palette (toFloat vmin) (toFloat vmax) (toFloat l)+ ++pickColor :: RealFrac t => [C.Colour Double] -> t -> t -> t -> C.Colour Double+pickColor palette xmin xmax x = palette !! i+ where+ i = floor (x01 * fromIntegral (nColors - 1))+ x01 = (x-xmin)/(xmax - xmin)+ nColors = length palette++++-- | `prepData d` assumes the input lists correspond to evenly sampled values of a scalar-valued field.+--+-- The function extracts the pixel mesh size, the data ranges and places the data points within the unit square [0,1] x [0,1]+prepData ::+ (Ord t, Fractional a, Enum a) =>+ [[t]] -- ^ Data+ -> (a, a, t, t, [LabeledPoint t a]) -- ^ (# of pixel rows, # of pixel columns, data minimum, data maximum, data points)+prepData ll = (nh, nw, valMin, valMax, d')+ where+ nh = fromIntegral $ length ll+ nw = fromIntegral $ length (head ll)+ -- nh = toRational $ length ll+ -- nw = toRational $ length (head ll) + d' = toUnitFramedLP nw nh <$> toCoord ll+ valMin = minimum $ _lplabel <$> d'+ valMax = maximum $ _lplabel <$> d'+ + ++toCoord :: (Num i, Enum i) => [[c]] -> [(i, i, c)]+toCoord ll = concat $ reverse $ go 0 ll [] where+ go i (x:xs) acc = go (i + 1) xs $ zip3 (repeat i) [0 ..] x : acc+ go _ [] acc = acc++toUnitFramedLP :: (Fractional t) =>+ t -> t -> (t, t, l) -> LabeledPoint l t+toUnitFramedLP w h (i, j, x) = LabeledPoint p x+ where p = Point (i/h) (j/w)