hsparklines (empty) → 0.1.0
raw patch · 11 files changed
+355/−0 lines, 11 filesdep +basedep +bytestringdep +dataencsetup-changed
Dependencies added: base, bytestring, dataenc, gd
Files
- Graphics/Rendering/HSparklines.hs +179/−0
- LICENSE +30/−0
- README +39/−0
- Setup.lhs +9/−0
- examples/Makefile +17/−0
- examples/bar.hs +14/−0
- examples/bar.html +10/−0
- examples/dataurl.hs +12/−0
- examples/smooth.hs +14/−0
- examples/smooth.html +10/−0
- hsparklines.cabal +21/−0
+ Graphics/Rendering/HSparklines.hs view
@@ -0,0 +1,179 @@+---------------------------------------------------------------+-- |+-- Module : Graphics.Rendering.HSparklines+-- Copyright : (c) Hitesh Jasani, 2008+-- License : BSD3+--+-- Maintainer : Hitesh Jasani <hitesh.jasani@gmail.com>+-- Stability : experimental+-- Portability : portable+--+-- Created : 2008-02-26+-- Version : 0.1+--+-- Sparklines implementation in Haskell. Sparklines are+-- mini graphs inspired by Edward Tufte.+--+-- > dp :: [Float]+-- > dp = [24,21,32.3,24,15,34,43,55,57,72,74,75,73,72,55,44]+-- >+-- > make barSpark dp >>= savePngFile "bar_spark.png"+-- >+---------------------------------------------------------------++module Graphics.Rendering.HSparklines+ (+ -- * Types+ SparkOptions(..)+ ,rgb+ -- * Drawing functions+ ,make+ ,smoothSpark+ ,barSpark+ -- * Saving functions+ ,savePngFile+ ,encodePngAsDataUrl+ ) where+++import Codec.Binary.Base64 ( encode )+import Control.Monad+import Data.ByteString ( unpack )+import Data.List+import Data.Ord+import Graphics.GD++++make :: SparkOptions -> [Float] -> IO Image+make so@(SmoothOptions {}) dp = renderSmooth so dp+make so@(BarOptions {}) dp = renderBar so dp+++data SparkOptions = SmoothOptions+ {+ step :: Int -- ^ step size+ ,height :: Int -- ^ graph height (pixels)+ ,limits :: (Int,Int) -- ^ data point limits+ ,bgColor :: Color -- ^ background color+ ,minColor :: Color -- ^ color of minimum datapoint+ ,maxColor :: Color -- ^ color of maximum datapoint+ ,lastColor :: Color -- ^ color of last datapoint+ ,minMarker :: Bool -- ^ display minimum marker+ ,maxMarker :: Bool -- ^ display maximum marker+ ,lastMarker :: Bool -- ^ display last marker+ }+ | BarOptions+ {+ step :: Int -- ^ step size+ ,height :: Int -- ^ graph height (pixels)+ ,limits :: (Int,Int) -- ^ data point limits+ ,bgColor :: Color -- ^ background color+ ,minColor :: Color -- ^ color of minimum datapoint+ ,maxColor :: Color -- ^ color of maximum datapoint+ ,lastColor :: Color -- ^ color of last datapoint+ ,minMarker :: Bool -- ^ display minimum marker+ ,maxMarker :: Bool -- ^ display maximum marker+ ,lastMarker :: Bool -- ^ display last marker+ }+ deriving (Show)+++smoothSpark :: SparkOptions+smoothSpark = SmoothOptions+ {+ step = 2+ ,height = 20+ ,limits = (0,100)+ ,bgColor = white+ ,minColor = red+ ,maxColor = green+ ,lastColor = blue+ ,minMarker = True+ ,maxMarker = True+ ,lastMarker = True+ }+++barSpark :: SparkOptions+barSpark = BarOptions+ {+ step = 2+ ,height = 20+ ,limits = (0,100)+ ,bgColor = white+ ,minColor = red+ ,maxColor = green+ ,lastColor = blue+ ,minMarker = True+ ,maxMarker = True+ ,lastMarker = True+ }+++renderSmooth :: SparkOptions -> [Float] -> IO Image+renderSmooth opt ds = do+ let w = 4 + (step opt) * (length ds - 1)+ h = height opt + dmin = fst (limits opt)+ dmax = snd (limits opt)+ coords = zip [1,(1+(step opt))..(1+(step opt)*(length ds))]+ [h - round( (y-(fi dmin)) / ((fi (dmax-dmin+1)) / (fi (h-4))) )+ | y <- ds ]+ minpt = maximumBy (comparing snd) coords -- because y increases as we go down+ maxpt = minimumBy (comparing snd) coords+ endpt = last coords++ img <- newImage (w,h)+ drawFilledRectangle (0,0) (w,h) (bgColor opt) img+ zipWithM_ (\p1 p2 -> antiAliased (drawLine p1 p2) grey img)+ coords (drop 1 coords)+ when (minMarker opt) (uncurry drawFilledRectangle (boxpt minpt) (minColor opt) img)+ when (maxMarker opt) (uncurry drawFilledRectangle (boxpt maxpt) (maxColor opt) img)+ when (lastMarker opt) (uncurry drawFilledRectangle (boxpt endpt) (lastColor opt)+ img)+ return img+++renderBar :: SparkOptions -> [Float] -> IO Image+renderBar opt ds = do+ let w = 4 + (step opt) * (length ds - 1) + bw2 * length ds+ h = height opt+ dmin = fst (limits opt)+ dmax = snd (limits opt)+ bw = 1+ bw2 = 2 * bw+ coords = zip [1,(1+(step opt)+bw2)..(1+((step opt)+bw2)*(length ds))]+ [h - round( (y-(fi dmin)) / ((fi (dmax-dmin+1)) / (fi (h-4))) )+ | y <- ds ]+ minpt = maximumBy (comparing snd) coords -- because y increases as we go down+ maxpt = minimumBy (comparing snd) coords+ endpt = last coords++ img <- newImage (w,h)+ drawFilledRectangle (0,0) (w,h) (bgColor opt) img+ forM_ coords $ \(x,y) ->+ antiAliased (drawFilledRectangle (x-bw,y) (x+bw,h)) grey img+ when (minMarker opt) (uncurry drawFilledRectangle (boxpt minpt) (minColor opt) img)+ when (maxMarker opt) (uncurry drawFilledRectangle (boxpt maxpt) (maxColor opt) img)+ when (lastMarker opt) (uncurry drawFilledRectangle (boxpt endpt) (lastColor opt)+ img)+ return img+++encodePngAsDataUrl :: Image -> IO String+encodePngAsDataUrl img = savePngByteString img >>= return . encode . unpack++fi :: (Num b, Integral a) => a -> b+fi x = fromIntegral x++boxpt :: (Num a) => (a,a) -> ((a,a),(a,a))+boxpt (x,y) = (,) (x-1,y-1) (x+1,y+1)++white,grey,red,green,blue :: Color+white = rgb 0xff 0xff 0xff+grey = rgb 0x88 0x88 0x88+red = rgb 0xff 0x00 0x00+green = rgb 0x00 0xff 0x00+blue = rgb 0x00 0x00 0xff+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) Hitesh Jasani <hitesh.jasani@gmail.com>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,39 @@++INTRO++Sparklines are high content to size ratio minigraphs inspired by Edward Tufte.++The focus of a sparkline is to provide additional context inline with text+so users can do more informed analysis and make better decisions. To make+them fit with inline text, sparklines are generally small (100px x 30px)+and dispense with axis labels and units.+++REFERENCES++o http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR&topic_id=1+o http://bitworking.org/projects/sparklines/+++++INSTALL++ % runhaskell Setup.lhs configure+ % runhaskell Setup.lhs build+ % runhaskell Setup.lhs haddock+ % sudo runhaskell Setup.lhs install+++NOTES++You may encounter problems building the documentation if you're using+a version of haddock before version 2.0.0.0.+++ACKNOWLEDGEMENTS++Joe Gregorio's Python implementation of Sparklines served as an inspiration+for doing a Haskell version. He's done some good work, make sure to check+out his site http://bitworking.org/+
+ Setup.lhs view
@@ -0,0 +1,9 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple++> main :: IO ()+> main = defaultMain++
+ examples/Makefile view
@@ -0,0 +1,17 @@++FLAGS = -Wall -Werror -O2 -i..+LIBS = -lgd -L/opt/local/lib+SRCS = $(wildcard *.hs)+EXES = $(subst .hs,.exe,$(SRCS))++.PHONY: all clean++default: $(EXES)++all: $(EXES)++%.exe: %.hs+ ghc --make $(FLAGS) $< -o $@ $(LIBS)++clean:+ -rm *.png *.exe *.o *.hi *~ dataurl.html
+ examples/bar.hs view
@@ -0,0 +1,14 @@++import Graphics.Rendering.HSparklines++dp :: [Float]+dp = [24,21,32.3,24,15,34,43,55,57,72,74,75,73,72,55,44]++main :: IO ()+main = do+ make (barSpark) dp >>= savePngFile "bar_spark.png"+ make (barSpark {step = 5}) dp >>= savePngFile "bar_spark_s5.png"+ make (barSpark {bgColor = rgb 0xee 0xee 0xee}) dp >>=+ savePngFile "bar_spark_bg.png"+ make (barSpark {bgColor = rgb 0xee 0xee 0xee, step = 5, minMarker = False}) dp+ >>= savePngFile "bar_spark_bg_s5.png"
+ examples/bar.html view
@@ -0,0 +1,10 @@+<p>+Default bar sparkline <img src="bar_spark.png" /> and another version of +the same <img src="bar_spark_s5.png" /> with the step set to 5.+</p>+<p>+Bar sparkline <img src="bar_spark_bg.png" /> with an offwhite background+color and another version of the same <img src="bar_spark_bg_s5.png" /> with+ the step set to 5 and the minMarker turned off.+</p>+
+ examples/dataurl.hs view
@@ -0,0 +1,12 @@++import Graphics.Rendering.HSparklines++dp :: [Float]+dp = [24,21,32.3,24,15,34,43,55,57,72,74,75,73,72,55,44]++main :: IO ()+main = do+ im <- make (barSpark {minMarker = False, maxMarker = False}) dp+ gi <- encodePngAsDataUrl im+ writeFile "dataurl.html" ("<p>This sparkline <img src=\"data:image/png;base64,"+ ++ gi ++ "\" /> is done inline.</p>")
+ examples/smooth.hs view
@@ -0,0 +1,14 @@++import Graphics.Rendering.HSparklines++dp :: [Float]+dp = [24,21,32.3,24,15,34,43,55,57,72,74,75,73,72,55,44]++main :: IO ()+main = do+ make (smoothSpark) dp >>= savePngFile "smooth_spark.png"+ make (smoothSpark {step = 5}) dp >>= savePngFile "smooth_spark_s5.png"+ make (smoothSpark {bgColor = rgb 0xee 0xee 0xee}) dp >>=+ savePngFile "smooth_spark_bg.png"+ make (smoothSpark {bgColor = rgb 0xee 0xee 0xee, step = 5, minMarker = False}) dp+ >>= savePngFile "smooth_spark_bg_s5.png"
+ examples/smooth.html view
@@ -0,0 +1,10 @@+<p>+Default smooth sparkline <img src="smooth_spark.png" /> and another version of +the same <img src="smooth_spark_s5.png" /> with the step set to 5.+</p>+<p>+Smooth sparkline <img src="smooth_spark_bg.png" /> with an offwhite background+color and another version of the same <img src="smooth_spark_bg_s5.png" /> with+ the step set to 5 and the minMarker turned off.+</p>+
+ hsparklines.cabal view
@@ -0,0 +1,21 @@+name: hsparklines+version: 0.1.0+description: Sparklines implementation of smooth and bar graphs+synopsis: Sparklines for Haskell+license: BSD3+license-file: LICENSE+homepage: http://www.jasani.org/search/label/hsparklines+author: Hitesh Jasani+category: Graphics+maintainer: <hitesh.jasani@gmail.com>+Cabal-Version: >= 1.2+Build-Type: Simple+Tested-With: GHC == 6.8.2+extra-source-files: README examples/bar.hs examples/bar.html examples/dataurl.hs+ examples/Makefile examples/smooth.hs examples/smooth.html++library+ build-depends: base >= 3, bytestring, gd, dataenc+ exposed-modules: Graphics.Rendering.HSparklines+ ghc-options: -Wall+