packages feed

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 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+