barchart-0.1: src/Graphics/BarChart/Parser.hs
module Graphics.BarChart.Parser where
import Text.CSV
import Data.List ( nub )
import Data.Maybe ( fromJust, fromMaybe )
import System.FilePath
import Graphics.BarChart.Types
import Graphics.BarChart.Rendering
-- | Converts a CSV file to be drawn as a chart where each bar may
-- consist of multiple blocks.
--
parseMultiBars :: Read a => [Label] -> CSV -> MultiBars a
parseMultiBars block_labels = MultiBars block_labels . map parseRecord
where parseRecord (label:values) = (label,map read values)
-- | Converts a CSV file to be drawn as a chart where each bar has an
-- attached deviation depicted as an interval next to the bar.
--
parseIntervals :: Read a => CSV -> Intervals a
parseIntervals = Intervals . map parseRecord
where parseRecord [label,m,l,u] = (label,(read m, read l, read u))
-- | Converts a CSV file to be drawn as a chart where each bar may
-- consist of multiple blocks which have an attached deviation
-- depicted as an interval next to them.
--
parseMultiBarIntervals :: Read a => [Label] -> CSV -> MultiBarIntervals a
parseMultiBarIntervals block_labels =
MBIntervals block_labels . map parseRecord
where parseRecord (label:fields) = (label, triples fields)
triples (x:y:z:xs) = (read x,read y,read z) : triples xs
triples _ = []
-- | Used by 'writeMultiBarChart' to create a 'BarChart' from a CSV file.
--
multiBarChart :: (Measurable a, Read a)
=> [Label] -- ^ legend for blocks
-> CSV -- ^ comma separated values to depict
-> BarChart a
multiBarChart block_labels = drawMultiBars . parseMultiBars block_labels
-- | Used by 'writeIntervalChart' to create a 'BarChart' from a CSV file.
--
intervalChart :: (Measurable a, Read a)
=> CSV -- ^ comma separated values to depict
-> BarChart a
intervalChart = drawIntervals . parseIntervals
-- | Used by 'writeMultiBarIntervalChart' to create a 'BarChart' from
-- | a CSV file.
--
multiBarIntervalChart :: (Measurable a, Read a)
=> [Label] -- ^ legend for blocks
-> CSV -- ^ comma separated values to depict
-> BarChart a
multiBarIntervalChart block_labels =
drawMultiBarIntervals . parseMultiBarIntervals block_labels
-- | The first column of the CSV file is parsed as names of the
-- bars. The height of each bar corresponds to the sum of all
-- subsequent entries. If there is more than one entry, the bars are
-- split into blocks.
--
writeMultiBarChart :: Config -- ^ where and how to draw the bar chart
-> FilePath -- ^ CSV file to read
-> [Label] -- ^ if non-empty, used as legend for blocks
-> IO ()
writeMultiBarChart config file block_labels =
do csv <- readCSV file
let chart = multiBarChart block_labels csv :: BarChart Double
renderWith config chart
-- | The first column of the CSV file is parsed as names of the
-- bars. Three entries following each bar name are parsed as mean,
-- minimum, and maximum value and depicted using an interval next to
-- the bar.
--
writeIntervalChart :: Config -- ^ where and how to draw the bar chart
-> FilePath -- ^ CSV file to read
-> IO ()
writeIntervalChart config file =
do csv <- readCSV file
let chart = intervalChart csv :: BarChart Double
renderWith config chart
-- | The first column of the CSV file is parsed as names of the
-- bars. The entries following each bar name are parsed as triples
-- of mean, minimum, and maximum value and depicted using an
-- interval next to the bar. The number of subsequent entries must
-- be a multiple of three and each bar is divided into a
-- corresponding number of blocks.
--
writeMultiBarIntervalChart :: Config -- ^ where and how to draw the bar chart
-> FilePath -- ^ CSV file to read
-> [Label] -- ^ legend for blocks
-> IO ()
writeMultiBarIntervalChart config file block_labels =
do csv <- readCSV file
let chart = multiBarIntervalChart block_labels csv :: BarChart Double
renderWith config chart
readCSV :: FilePath -> IO CSV
readCSV file = either (fail . show) (return . clean) =<< parseCSVFromFile file
where clean = filter (not . all null)