{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BangPatterns #-}
module Ploterific.Plot.Plot
( plot
) where
import Control.Monad.Reader (ReaderT (..), asks, liftIO)
import Data.Bool (bool)
import Data.Char (ord)
import Data.List (foldl')
import Data.Maybe (fromMaybe)
import qualified Control.Lens as L
import qualified Data.ByteString.Lazy.Char8 as BL
import qualified Data.ByteString.Char8 as B
import qualified Data.Csv.Streaming as CSVStream
import qualified Data.Csv as CSV
import qualified Data.Foldable as F
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import qualified Data.Text.Lazy.IO as TL
import qualified Data.Text.Read as T
import qualified Graphics.Vega.VegaLite as VL
import qualified Graphics.Vega.VegaLite.Theme as VL
import Ploterific.Plot.Types
splitColMeasure :: T.Text -> Either T.Text (T.Text, VL.Measurement)
splitColMeasure :: Text -> Either Text (Text, Measurement)
splitColMeasure Text
feature = (Text, Text) -> Either Text (Text, Measurement)
splitOrNot ((Text, Text) -> Either Text (Text, Measurement))
-> (Text -> (Text, Text))
-> Text
-> Either Text (Text, Measurement)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> (Text, Text)
T.breakOnEnd Text
":" (Text -> Either Text (Text, Measurement))
-> Text -> Either Text (Text, Measurement)
forall a b. (a -> b) -> a -> b
$ Text
feature
where
splitOrNot :: (Text, Text) -> Either Text (Text, Measurement)
splitOrNot (Text
"", Text
_) = Text -> Either Text (Text, Measurement)
forall a b. a -> Either a b
Left Text
feature
splitOrNot (Text, Text)
x = (Text, Measurement) -> Either Text (Text, Measurement)
forall a b. b -> Either a b
Right ((Text, Measurement) -> Either Text (Text, Measurement))
-> (Text, Measurement) -> Either Text (Text, Measurement)
forall a b. (a -> b) -> a -> b
$ (Text, Text) -> (Text, Measurement)
trueSplit (Text, Text)
x
trueSplit :: (Text, Text) -> (Text, Measurement)
trueSplit = ASetter (Text, Measurement) (Text, Measurement) Text Text
-> (Text -> Text) -> (Text, Measurement) -> (Text, Measurement)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
L.over ASetter (Text, Measurement) (Text, Measurement) Text Text
forall s t a b. Field1 s t a b => Lens s t a b
L._1 (Int -> Text -> Text
T.dropEnd Int
1) ((Text, Measurement) -> (Text, Measurement))
-> ((Text, Text) -> (Text, Measurement))
-> (Text, Text)
-> (Text, Measurement)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ASetter (Text, Text) (Text, Measurement) Text Measurement
-> (Text -> Measurement) -> (Text, Text) -> (Text, Measurement)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
L.over ASetter (Text, Text) (Text, Measurement) Text Measurement
forall s t a b. Field2 s t a b => Lens s t a b
L._2 Text -> Measurement
forall a. (Eq a, IsString a) => a -> Measurement
toMeasurement
toMeasurement :: a -> Measurement
toMeasurement a
"N" = Measurement
VL.Nominal
toMeasurement a
"O" = Measurement
VL.Ordinal
toMeasurement a
"Q" = Measurement
VL.Quantitative
toMeasurement a
"T" = Measurement
VL.Temporal
getColName :: T.Text -> T.Text
getColName :: Text -> Text
getColName = (Text -> Text)
-> ((Text, Measurement) -> Text)
-> Either Text (Text, Measurement)
-> Text
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Text
forall a. a -> a
id (Text, Measurement) -> Text
forall a b. (a, b) -> a
fst (Either Text (Text, Measurement) -> Text)
-> (Text -> Either Text (Text, Measurement)) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either Text (Text, Measurement)
splitColMeasure
getColMeasurement :: T.Text -> Maybe VL.Measurement
getColMeasurement :: Text -> Maybe Measurement
getColMeasurement = (Text -> Maybe Measurement)
-> ((Text, Measurement) -> Maybe Measurement)
-> Either Text (Text, Measurement)
-> Maybe Measurement
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe Measurement -> Text -> Maybe Measurement
forall a b. a -> b -> a
const Maybe Measurement
forall a. Maybe a
Nothing) (Measurement -> Maybe Measurement
forall a. a -> Maybe a
Just (Measurement -> Maybe Measurement)
-> ((Text, Measurement) -> Measurement)
-> (Text, Measurement)
-> Maybe Measurement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, Measurement) -> Measurement
forall a b. (a, b) -> b
snd) (Either Text (Text, Measurement) -> Maybe Measurement)
-> (Text -> Either Text (Text, Measurement))
-> Text
-> Maybe Measurement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either Text (Text, Measurement)
splitColMeasure
loadCsv :: Delimiter -> BL.ByteString -> [Map.Map T.Text T.Text]
loadCsv :: Delimiter -> ByteString -> [Map Text Text]
loadCsv (Delimiter Char
d) =
([Char] -> [Map Text Text])
-> ((Header, Records (Map Text Text)) -> [Map Text Text])
-> Either [Char] (Header, Records (Map Text Text))
-> [Map Text Text]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either [Char] -> [Map Text Text]
forall a. HasCallStack => [Char] -> a
error (Records (Map Text Text) -> [Map Text Text]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (Records (Map Text Text) -> [Map Text Text])
-> ((Header, Records (Map Text Text)) -> Records (Map Text Text))
-> (Header, Records (Map Text Text))
-> [Map Text Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Header, Records (Map Text Text)) -> Records (Map Text Text)
forall a b. (a, b) -> b
snd)
(Either [Char] (Header, Records (Map Text Text))
-> [Map Text Text])
-> (ByteString -> Either [Char] (Header, Records (Map Text Text)))
-> ByteString
-> [Map Text Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DecodeOptions
-> ByteString -> Either [Char] (Header, Records (Map Text Text))
forall a.
FromNamedRecord a =>
DecodeOptions -> ByteString -> Either [Char] (Header, Records a)
CSVStream.decodeByNameWith ( DecodeOptions
CSV.defaultDecodeOptions
{ decDelimiter :: Word8
CSV.decDelimiter = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
d) }
)
rowsToDataColumns :: Maybe Color
-> [Feature]
-> [Map.Map T.Text T.Text]
-> [VL.DataColumn]
-> VL.Data
rowsToDataColumns :: Maybe Color -> [Feature] -> [Map Text Text] -> [DataColumn] -> Data
rowsToDataColumns Maybe Color
color [Feature]
fs [Map Text Text]
rows =
[Format] -> [DataColumn] -> Data
VL.dataFromColumns []
([DataColumn] -> Data)
-> ([DataColumn] -> [DataColumn]) -> [DataColumn] -> Data
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([DataColumn] -> [DataColumn])
-> (Color -> [DataColumn] -> [DataColumn])
-> Maybe Color
-> [DataColumn]
-> [DataColumn]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
[DataColumn] -> [DataColumn]
forall a. a -> a
id
(\ (Color Text
c)
-> Text -> DataValues -> [DataColumn] -> [DataColumn]
VL.dataColumn
(Text -> Text
getColName Text
c)
(([Map Text Text] -> DataValues)
-> Text -> [Map Text Text] -> DataValues
numOrString (Text -> [Map Text Text] -> DataValues
textToString Text
c) Text
c [Map Text Text]
rows)
)
Maybe Color
color
([DataColumn] -> [DataColumn])
-> ([DataColumn] -> [DataColumn]) -> [DataColumn] -> [DataColumn]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([DataColumn] -> [DataColumn])
-> Feature -> [DataColumn] -> [DataColumn])
-> ([DataColumn] -> [DataColumn])
-> [Feature]
-> [DataColumn]
-> [DataColumn]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl'
(\ [DataColumn] -> [DataColumn]
acc (Feature Text
x)
-> Text -> DataValues -> [DataColumn] -> [DataColumn]
VL.dataColumn
(Text -> Text
getColName Text
x)
(([Map Text Text] -> DataValues)
-> Text -> [Map Text Text] -> DataValues
numOrString (Text -> [Map Text Text] -> DataValues
textToNumbers Text
x) Text
x [Map Text Text]
rows)
([DataColumn] -> [DataColumn])
-> ([DataColumn] -> [DataColumn]) -> [DataColumn] -> [DataColumn]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [DataColumn] -> [DataColumn]
acc
)
[DataColumn] -> [DataColumn]
forall a. a -> a
id
[Feature]
fs
where
numOrString :: ([Map.Map T.Text T.Text] -> VL.DataValues) -> T.Text -> ([Map.Map T.Text T.Text] -> VL.DataValues)
numOrString :: ([Map Text Text] -> DataValues)
-> Text -> [Map Text Text] -> DataValues
numOrString [Map Text Text] -> DataValues
def Text
x =
([Map Text Text] -> DataValues)
-> (Measurement -> [Map Text Text] -> DataValues)
-> Maybe Measurement
-> [Map Text Text]
-> DataValues
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
[Map Text Text] -> DataValues
def
(([Map Text Text] -> DataValues)
-> ([Map Text Text] -> DataValues)
-> Bool
-> [Map Text Text]
-> DataValues
forall a. a -> a -> Bool -> a
bool (Text -> [Map Text Text] -> DataValues
textToString Text
x) (Text -> [Map Text Text] -> DataValues
textToNumbers Text
x) (Bool -> [Map Text Text] -> DataValues)
-> (Measurement -> Bool)
-> Measurement
-> [Map Text Text]
-> DataValues
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Measurement -> Measurement -> Bool
forall a. Eq a => a -> a -> Bool
== Measurement
VL.Quantitative))
(Maybe Measurement -> [Map Text Text] -> DataValues)
-> (Text -> Maybe Measurement)
-> Text
-> [Map Text Text]
-> DataValues
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Measurement
getColMeasurement
(Text -> [Map Text Text] -> DataValues)
-> Text -> [Map Text Text] -> DataValues
forall a b. (a -> b) -> a -> b
$ Text
x
textToNumbers :: Text -> [Map Text Text] -> DataValues
textToNumbers Text
x = [Double] -> DataValues
VL.Numbers
([Double] -> DataValues)
-> ([Map Text Text] -> [Double]) -> [Map Text Text] -> DataValues
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Text Text -> Double) -> [Map Text Text] -> [Double]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ( Double -> (Text -> Double) -> Maybe Text -> Double
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
([Char] -> Double
forall a. HasCallStack => [Char] -> a
error [Char]
"Can not parse number in column")
(([Char] -> Double)
-> ((Double, Text) -> Double)
-> Either [Char] (Double, Text)
-> Double
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either [Char] -> Double
forall a. HasCallStack => [Char] -> a
error (Double, Text) -> Double
forall a b. (a, b) -> a
fst (Either [Char] (Double, Text) -> Double)
-> (Text -> Either [Char] (Double, Text)) -> Text -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either [Char] (Double, Text)
T.double)
(Maybe Text -> Double)
-> (Map Text Text -> Maybe Text) -> Map Text Text -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Text -> Text
getColName Text
x)
)
textToString :: Text -> [Map Text Text] -> DataValues
textToString Text
x = [Text] -> DataValues
VL.Strings ([Text] -> DataValues)
-> ([Map Text Text] -> [Text]) -> [Map Text Text] -> DataValues
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Text Text -> Text) -> [Map Text Text] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" (Maybe Text -> Text)
-> (Map Text Text -> Maybe Text) -> Map Text Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Text -> Text
getColName Text
x))
enc :: Maybe Color -> [Feature] -> [VL.EncodingSpec] -> VL.PropertySpec
enc :: Maybe Color -> [Feature] -> [EncodingSpec] -> Data
enc Maybe Color
color [Feature]
fs =
[EncodingSpec] -> Data
VL.encoding
([EncodingSpec] -> Data)
-> ([EncodingSpec] -> [EncodingSpec]) -> [EncodingSpec] -> Data
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([EncodingSpec] -> [EncodingSpec])
-> (Color -> [EncodingSpec] -> [EncodingSpec])
-> Maybe Color
-> [EncodingSpec]
-> [EncodingSpec]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
[EncodingSpec] -> [EncodingSpec]
forall a. a -> a
id
(\ (Color Text
c)
-> [MarkChannel] -> [EncodingSpec] -> [EncodingSpec]
VL.color ( [Text -> MarkChannel
VL.MName (Text -> MarkChannel) -> (Text -> Text) -> Text -> MarkChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
getColName (Text -> MarkChannel) -> Text -> MarkChannel
forall a b. (a -> b) -> a -> b
$ Text
c]
[MarkChannel] -> [MarkChannel] -> [MarkChannel]
forall a. Semigroup a => a -> a -> a
<> [MarkChannel]
-> (Measurement -> [MarkChannel])
-> Maybe Measurement
-> [MarkChannel]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\Measurement
x -> [Measurement -> MarkChannel
VL.MmType Measurement
x]) (Text -> Maybe Measurement
getColMeasurement Text
c)
)
)
Maybe Color
color
([EncodingSpec] -> [EncodingSpec])
-> ([EncodingSpec] -> [EncodingSpec])
-> [EncodingSpec]
-> [EncodingSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[TextChannel]] -> [EncodingSpec] -> [EncodingSpec]
VL.tooltips
( (Feature -> [TextChannel]) -> [Feature] -> [[TextChannel]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ (Feature !Text
f)
-> [ Text -> TextChannel
VL.TName (Text -> TextChannel) -> (Text -> Text) -> Text -> TextChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
getColName (Text -> TextChannel) -> Text -> TextChannel
forall a b. (a -> b) -> a -> b
$ Text
f ]
[TextChannel] -> [TextChannel] -> [TextChannel]
forall a. Semigroup a => a -> a -> a
<> [TextChannel]
-> (Measurement -> [TextChannel])
-> Maybe Measurement
-> [TextChannel]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\Measurement
x -> [Measurement -> TextChannel
VL.TmType Measurement
x]) (Text -> Maybe Measurement
getColMeasurement Text
f)
)
[Feature]
fs
[[TextChannel]] -> [[TextChannel]] -> [[TextChannel]]
forall a. Semigroup a => a -> a -> a
<> [ [TextChannel]
-> (Color -> [TextChannel]) -> Maybe Color -> [TextChannel]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
[]
(\ (Color Text
c)
-> [Text -> TextChannel
VL.TName (Text -> TextChannel) -> (Text -> Text) -> Text -> TextChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
getColName (Text -> TextChannel) -> Text -> TextChannel
forall a b. (a -> b) -> a -> b
$ Text
c]
[TextChannel] -> [TextChannel] -> [TextChannel]
forall a. Semigroup a => a -> a -> a
<> [TextChannel]
-> (Measurement -> [TextChannel])
-> Maybe Measurement
-> [TextChannel]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\Measurement
x -> [Measurement -> TextChannel
VL.TmType Measurement
x]) (Text -> Maybe Measurement
getColMeasurement Text
c)
)
Maybe Color
color
]
)
([EncodingSpec] -> [EncodingSpec])
-> ([EncodingSpec] -> [EncodingSpec])
-> [EncodingSpec]
-> [EncodingSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([EncodingSpec] -> [EncodingSpec])
-> (Position, Feature) -> [EncodingSpec] -> [EncodingSpec])
-> ([EncodingSpec] -> [EncodingSpec])
-> [(Position, Feature)]
-> [EncodingSpec]
-> [EncodingSpec]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl'
(\ [EncodingSpec] -> [EncodingSpec]
acc (!Position
p, Feature !Text
f)
-> Position -> [PositionChannel] -> [EncodingSpec] -> [EncodingSpec]
VL.position
Position
p
( [Text -> PositionChannel
VL.PName (Text -> PositionChannel)
-> (Text -> Text) -> Text -> PositionChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
getColName (Text -> PositionChannel) -> Text -> PositionChannel
forall a b. (a -> b) -> a -> b
$ Text
f]
[PositionChannel] -> [PositionChannel] -> [PositionChannel]
forall a. Semigroup a => a -> a -> a
<> [PositionChannel]
-> (Measurement -> [PositionChannel])
-> Maybe Measurement
-> [PositionChannel]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\Measurement
x -> [Measurement -> PositionChannel
VL.PmType Measurement
x]) (Text -> Maybe Measurement
getColMeasurement Text
f)
)
([EncodingSpec] -> [EncodingSpec])
-> ([EncodingSpec] -> [EncodingSpec])
-> [EncodingSpec]
-> [EncodingSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [EncodingSpec] -> [EncodingSpec]
acc
)
[EncodingSpec] -> [EncodingSpec]
forall a. a -> a
id
([Position] -> [Feature] -> [(Position, Feature)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Position]
pos [Feature]
fs)
where
pos :: [Position]
pos = [Position
VL.X, Position
VL.Y]
plot :: ReaderT Opts IO ()
plot :: ReaderT Opts IO ()
plot = do
IO ByteString
input' <- (Opts -> IO ByteString) -> ReaderT Opts IO (IO ByteString)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (IO ByteString
-> (Input -> IO ByteString) -> Maybe Input -> IO ByteString
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ByteString
BL.getContents ([Char] -> IO ByteString
BL.readFile ([Char] -> IO ByteString)
-> (Input -> [Char]) -> Input -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Input -> [Char]
unInput) (Maybe Input -> IO ByteString)
-> (Opts -> Maybe Input) -> Opts -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Opts -> Maybe Input
_input)
Text -> IO ()
output' <- (Opts -> Text -> IO ()) -> ReaderT Opts IO (Text -> IO ())
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ((Text -> IO ())
-> (Output -> Text -> IO ()) -> Maybe Output -> Text -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text -> IO ()
TL.putStrLn ([Char] -> Text -> IO ()
TL.writeFile ([Char] -> Text -> IO ())
-> (Output -> [Char]) -> Output -> Text -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Output -> [Char]
unOutput) (Maybe Output -> Text -> IO ())
-> (Opts -> Maybe Output) -> Opts -> Text -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Opts -> Maybe Output
_output)
Maybe Height
height' <- (Opts -> Maybe Height) -> ReaderT Opts IO (Maybe Height)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Opts -> Maybe Height
_height
Maybe Width
width' <- (Opts -> Maybe Width) -> ReaderT Opts IO (Maybe Width)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Opts -> Maybe Width
_width
Mark
mark' <- (Opts -> Mark) -> ReaderT Opts IO Mark
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Opts -> Mark
_mark
Maybe Color
color' <- (Opts -> Maybe Color) -> ReaderT Opts IO (Maybe Color)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Opts -> Maybe Color
_color
[Feature]
features' <- (Opts -> [Feature]) -> ReaderT Opts IO [Feature]
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Opts -> [Feature]
_features
Delimiter
delimiter' <- (Opts -> Delimiter) -> ReaderT Opts IO Delimiter
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Opts -> Delimiter
_delimiter
ByteString
contents <- IO ByteString -> ReaderT Opts IO ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ByteString
input'
let dataSet :: [DataColumn] -> Data
dataSet =
Maybe Color -> [Feature] -> [Map Text Text] -> [DataColumn] -> Data
rowsToDataColumns Maybe Color
color' [Feature]
features' ([Map Text Text] -> [DataColumn] -> Data)
-> (ByteString -> [Map Text Text])
-> ByteString
-> [DataColumn]
-> Data
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Delimiter -> ByteString -> [Map Text Text]
loadCsv Delimiter
delimiter' (ByteString -> [DataColumn] -> Data)
-> ByteString -> [DataColumn] -> Data
forall a b. (a -> b) -> a -> b
$ ByteString
contents
p :: VegaLite
p = [Data] -> VegaLite
VL.toVegaLite
([Data] -> VegaLite) -> [Data] -> VegaLite
forall a b. (a -> b) -> a -> b
$ [ [DataColumn] -> Data
dataSet []
, Maybe Color -> [Feature] -> [EncodingSpec] -> Data
enc Maybe Color
color' [Feature]
features' []
, Mark -> [MarkProperty] -> Data
VL.mark Mark
mark' []
, Config -> [ConfigureSpec] -> Data
VL.theme Config
VL.defaultConfig []
, [SelectSpec] -> Data
VL.selection ([SelectSpec] -> Data)
-> ([SelectSpec] -> [SelectSpec]) -> [SelectSpec] -> Data
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text
-> Selection -> [SelectionProperty] -> [SelectSpec] -> [SelectSpec]
VL.select Text
"view" Selection
VL.Interval [SelectionProperty
VL.BindScales]
([SelectSpec] -> Data) -> [SelectSpec] -> Data
forall a b. (a -> b) -> a -> b
$ []
]
[Data] -> [Data] -> [Data]
forall a. Semigroup a => a -> a -> a
<> [Data] -> (Height -> [Data]) -> Maybe Height -> [Data]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(Height Double
x) -> [Double -> Data
VL.height Double
x]) Maybe Height
height'
[Data] -> [Data] -> [Data]
forall a. Semigroup a => a -> a -> a
<> [Data] -> (Width -> [Data]) -> Maybe Width -> [Data]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(Width Double
x) -> [Double -> Data
VL.width Double
x]) Maybe Width
width'
IO () -> ReaderT Opts IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Opts IO ())
-> (Text -> IO ()) -> Text -> ReaderT Opts IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> IO ()
output' (Text -> ReaderT Opts IO ()) -> Text -> ReaderT Opts IO ()
forall a b. (a -> b) -> a -> b
$ VegaLite -> Text
VL.toHtml VegaLite
p
() -> ReaderT Opts IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()