Skip to content

Commit

Permalink
it works kinda
Browse files Browse the repository at this point in the history
  • Loading branch information
mstksg committed Sep 3, 2019
1 parent d8170e7 commit 07e2f48
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 65 deletions.
4 changes: 2 additions & 2 deletions app/demo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import Data.Default
import Interactive.Plot

cosTest, lineTest :: AutoSeries
cosTest = funcSeries cos (enumRange 100 (R (-5) 5)) def
lineTest = funcSeries id (enumRange 20 (R (-4) 4)) def
cosTest = funcSeries cos (enumRange 100 (R (-5) 5)) mempty
lineTest = funcSeries id (enumRange 20 (R (-4) 4)) mempty

main :: IO ()
main = runPlotAuto def [cosTest, lineTest]
Expand Down
91 changes: 66 additions & 25 deletions src/Interactive/Plot/Core.hs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}

-- |
-- Module : Interative.Plot.Core
Expand All @@ -22,8 +28,8 @@
module Interactive.Plot.Core (
Coord(..), cX, cY
, Range(.., RAbout), rMin, rMax, rSize, rMid, _rSize
, PointStyle(..), psMarker, psColor
, Series(..), sItems, sStyle, toCoordMap, fromCoordMap
, PointStyleF(.., PointStyle), PointStyle, AutoPointStyle, psMarker, psColor
, SeriesF(..), Series, AutoSeries, sItems, sStyle, toCoordMap, fromCoordMap
, Alignment(..)
, PlotOpts(..), poTermRatio, poAspectRatio, poXRange, poYRange, poRange
, renderPlot
Expand All @@ -39,14 +45,16 @@ import Data.Coerce
import Data.Default
import Data.Foldable
import Data.Functor.Compose
import Data.Functor.Identity
import Data.Maybe
import Data.Ord
import Graphics.Vty
import GHC.Generics (Generic)
import Graphics.Vty hiding ((<|>))
import Lens.Micro
import Lens.Micro.TH
import Text.Printf
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Map as M
import qualified Data.Set as S

-- | Newtype wrapper providing an 'Ord' instance for 'Color'.
newtype OrdColor = OC { getOC :: Color }
Expand Down Expand Up @@ -105,24 +113,57 @@ instance Monad Range where
R x y >>= f = R (_rMin (f x)) (_rMax (f y))

-- | Specification of a style for a point.
data PointStyle = PointStyle
{ _psMarker :: Char -- ^ Marker cahracter. For getter/setter lens, see 'psMarker'.
, _psColor :: Color -- ^ Marker color. For getter/setter lens, see 'psColor'.
data PointStyleF f = PointStyleF
{ _psMarkerF :: f Char -- ^ Marker cahracter. For getter/setter lens, see 'psMarker'.
, _psColorF :: f Color -- ^ Marker color. For getter/setter lens, see 'psColor'.
}
deriving (Eq)
deriving (Generic)

makeLenses ''PointStyle
makeLenses ''PointStyleF

instance Ord PointStyle where
compare = comparing $ \case PointStyle m1 c1 -> (m1, OC c1)
type PointStyle = PointStyleF Identity

-- | A version of 'PointStyle' where you can leave the marker or color
-- blank, to be automatically inferred.
type AutoPointStyle = PointStyleF Maybe

pattern PointStyle :: Char -> Color -> PointStyle
pattern PointStyle { _psMarker, _psColor } = PointStyleF (Identity _psMarker) (Identity _psColor)
{-# COMPLETE PointStyle #-}

instance Semigroup AutoPointStyle where
PointStyleF m1 c1 <> PointStyleF m2 c2 = PointStyleF (m1 <|> m2) (c1 <|> c2)
instance Monoid AutoPointStyle where
mempty = PointStyleF Nothing Nothing

deriving instance (Eq (f Char), Eq (f Color)) => Eq (PointStyleF f)
instance (Ord (f Char), Ord (f OrdColor), Functor f, Eq (f Color)) => Ord (PointStyleF f) where
compare = comparing $ \case PointStyleF m1 c1 -> (m1, OC <$> c1)

_Identity :: Lens (Identity a) (Identity b) a b
_Identity f (Identity x) = Identity <$> f x

psMarker :: Lens' PointStyle Char
psMarker = psMarkerF . _Identity

psColor :: Lens' PointStyle Color
psColor = psColorF . _Identity

-- | Data for a single series: contains the coordinate map with the point
-- style for the series.
data Series = Series { _sItems :: M.Map Double (S.Set Double)
, _sStyle :: PointStyle
}
data SeriesF f = Series { _sItems :: M.Map Double (S.Set Double)
, _sStyle :: PointStyleF f
}


type Series = SeriesF Identity

-- | A version of 'Series' where you can leave the marker or color blank,
-- to be automatically inferred.
type AutoSeries = SeriesF Maybe


makeLenses ''Series
makeLenses ''SeriesF

-- | Alignment specification.
data Alignment = ALeft
Expand Down
49 changes: 11 additions & 38 deletions src/Interactive/Plot/Series.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
--
-- Create common serieses.
module Interactive.Plot.Series (
AutoPointStyle(..), apsMarker, apsColor
, AutoSeries(..), asItems, asStyle
, defaultStyles
defaultStyles
-- * Create a 'Series' from an 'AutoSeries'.
, fromAutoSeries
, fromAutoSeriesIO
Expand All @@ -30,51 +28,26 @@ module Interactive.Plot.Series (

import Control.Monad.Random
import Control.Monad.State
import Data.Default
import Data.Foldable
import Data.Maybe
import Graphics.Vty
import Interactive.Plot.Core
import Lens.Micro
import Lens.Micro.TH
import qualified Data.Map as M
import qualified Data.Set as S

-- | A version of 'PointStyle' where you can leave the marker or color
-- blank, to be automatically inferred.
data AutoPointStyle = APS
{ _apsMarker :: Maybe Char
, _apsColor :: Maybe Color
}
deriving Show

makeLenses ''AutoPointStyle

instance Default AutoPointStyle where
def = APS Nothing Nothing

-- | A version of 'Series' where you can leave the marker or color blank,
-- to be automatically inferred.
data AutoSeries = AS { _asItems :: M.Map Double (S.Set Double)
, _asStyle :: AutoPointStyle
}
deriving Show

makeLenses ''AutoSeries

-- | Construct a series from any foldable container of y-values.
listSeries :: Foldable t => t Double -> AutoPointStyle -> AutoSeries
listSeries xs = AS (toCoordMap . S.fromList . zipWith C [0..] . toList $ xs)
listSeries xs = Series (toCoordMap . S.fromList . zipWith C [0..] . toList $ xs)

-- | Construct a series from any foldable container of x-y tuples.
tupleSeries :: Foldable t => t (Double, Double) -> AutoPointStyle -> AutoSeries
tupleSeries xs = AS (toCoordMap . S.fromList . foldMap ((:[]) . uncurry C) $ xs)
tupleSeries xs = Series (toCoordMap . S.fromList . foldMap ((:[]) . uncurry C) $ xs)

-- | Convert from a 'Series' back into an 'AutoSeries' with settings given.
autoSeries :: Series -> AutoSeries
autoSeries s = AS (s ^. sItems)
$ APS (Just (s ^. sStyle . psMarker))
(Just (s ^. sStyle . psColor))
autoSeries s = Series (s ^. sItems)
$ PointStyleF (Just (s ^. sStyle . psMarker))
(Just (s ^. sStyle . psColor))

-- | @'enumRange' n ('R' a b)@ generates a list of @n@ equally spaced values
-- between @a@ and @b@.
Expand Down Expand Up @@ -132,30 +105,30 @@ fromAutoSeries_ :: StdGen -> [AutoSeries] -> [Series]
fromAutoSeries_ seed = flip evalRand seed . flip evalStateT S.empty . mapM go
where
go :: AutoSeries -> StateT (S.Set PointStyle) (Rand StdGen) Series
go (AS is ps) = Series is <$> pickPs
go (Series is ps) = Series is <$> pickPs
where
pickPs = case ps of
APS Nothing Nothing -> do
PointStyleF Nothing Nothing -> do
picked <- get
samp <- sampleSet $ defaultStyles S.\\ picked
case samp of
Nothing -> fromJust <$> sampleSet defaultStyles
Just s -> s <$ put (s `S.insert` picked)
APS (Just m) Nothing -> do
PointStyleF (Just m) Nothing -> do
picked <- get
let allDefaults = combinePointStyles (S.singleton m) defaultColors
samp <- sampleSet $ allDefaults S.\\ picked
case samp of
Nothing -> fromJust <$> sampleSet allDefaults
Just s -> s <$ put (s `S.insert` picked)
APS Nothing (Just c) -> do
PointStyleF Nothing (Just c) -> do
picked <- get
let allDefaults = combinePointStyles defaultMarkers (S.singleton (OC c))
samp <- sampleSet $ allDefaults S.\\ picked
case samp of
Nothing -> fromJust <$> sampleSet allDefaults
Just s -> s <$ put (s `S.insert` picked)
APS (Just m) (Just c) -> pure $ PointStyle m c
PointStyleF (Just m) (Just c) -> pure $ PointStyle m c

sampleSet
:: (MonadRandom m)
Expand Down

0 comments on commit 07e2f48

Please sign in to comment.