plot-light 0.1.0.9 → 0.1.1
raw patch · 7 files changed
+275/−59 lines, 7 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Graphics.Rendering.Plot.Light: axis :: (Functor t, Foldable t, Show a, RealFrac a) => Point a -> Axis -> a -> a -> Colour Double -> a -> LineStroke_ a -> Int -> a -> TextAnchor_ -> (l -> Text) -> V2 a -> t (LabeledPoint l a) -> Svg
+ Graphics.Rendering.Plot.Light: FigureData :: a -> a -> a -> a -> a -> a -> Int -> FigureData a
+ Graphics.Rendering.Plot.Light: [figBottomMFrac] :: FigureData a -> a
+ Graphics.Rendering.Plot.Light: [figHeight] :: FigureData a -> a
+ Graphics.Rendering.Plot.Light: [figLabelFontSize] :: FigureData a -> Int
+ Graphics.Rendering.Plot.Light: [figLeftMFrac] :: FigureData a -> a
+ Graphics.Rendering.Plot.Light: [figRightMFrac] :: FigureData a -> a
+ Graphics.Rendering.Plot.Light: [figTopMFrac] :: FigureData a -> a
+ Graphics.Rendering.Plot.Light: [figWidth] :: FigureData a -> a
+ Graphics.Rendering.Plot.Light: candlestick :: (Show a, RealFrac a) => (LabeledPoint l a -> Bool) -> (LabeledPoint l a -> a) -> (LabeledPoint l a -> a) -> (LabeledPoint l a -> a) -> (LabeledPoint l a -> a) -> a -> a -> Colour Double -> Colour Double -> Colour Double -> LabeledPoint l a -> Svg
+ Graphics.Rendering.Plot.Light: data FigureData a
+ Graphics.Rendering.Plot.Light: filledBand :: (Foldable t, Real o, Show a) => Colour Double -> o -> (LabeledPoint l a -> a) -> (LabeledPoint l a -> a) -> t (LabeledPoint l a) -> Svg
+ Graphics.Rendering.Plot.Light: filledPolyline :: (Foldable t, Show a, Real o) => Colour Double -> o -> t (Point a) -> Svg
+ Graphics.Rendering.Plot.Light: frameFromPoints :: (Ord a, Foldable t, Functor t) => t (Point a) -> Frame a
+ Graphics.Rendering.Plot.Light: height :: Num a => Frame a -> a
+ Graphics.Rendering.Plot.Light: mkFrame :: Point a -> Point a -> Frame a
+ Graphics.Rendering.Plot.Light: mkFrameOrigin :: Num a => a -> a -> Frame a
+ Graphics.Rendering.Plot.Light: pointRange :: (Fractional a, Integral n) => n -> Point a -> Point a -> [Point a]
+ Graphics.Rendering.Plot.Light: toPlot :: (Functor t, Foldable t, Show a, RealFrac a) => FigureData a -> (l -> Text) -> (l -> Text) -> a -> a -> a -> Colour Double -> (t (LabeledPoint l a) -> t (LabeledPoint l a)) -> (t (LabeledPoint l a) -> t (LabeledPoint l a)) -> (t (LabeledPoint l a) -> Svg) -> t (LabeledPoint l a) -> Svg
+ Graphics.Rendering.Plot.Light: toSvgFrame :: Fractional a => Frame a -> Frame a -> Bool -> Point a -> Point a
+ Graphics.Rendering.Plot.Light: toSvgFrameLP :: Fractional a => Frame a -> Frame a -> Bool -> LabeledPoint l a -> LabeledPoint l a
+ Graphics.Rendering.Plot.Light: width :: Num a => Frame a -> a
- Graphics.Rendering.Plot.Light: circle :: (Real a1, Real a) => Point a1 -> a -> Maybe (Colour Double) -> Maybe (Colour Double) -> Svg
+ Graphics.Rendering.Plot.Light: circle :: (Real a1, Real a) => Point a1 -> a -> a -> Maybe (Colour Double) -> Maybe (Colour Double) -> Svg
- Graphics.Rendering.Plot.Light: frameToFrame :: (Fractional a, LinearMap m (V2 a)) => Frame a -> Frame a -> m -> V2 a -> V2 a -> V2 a
+ Graphics.Rendering.Plot.Light: frameToFrame :: Fractional a => Frame a -> Frame a -> Bool -> Bool -> V2 a -> V2 a
- Graphics.Rendering.Plot.Light: rectCentered :: (Show a, RealFrac a) => Point a -> a -> a -> Maybe (Colour Double) -> Maybe (Colour Double) -> Svg
+ Graphics.Rendering.Plot.Light: rectCentered :: (Show a, RealFrac a) => Point a -> a -> a -> a -> Maybe (Colour Double) -> Maybe (Colour Double) -> Svg
Files
- README.md +1/−3
- plot-light.cabal +1/−1
- src/Graphics/Rendering/Plot/Light.hs +11/−4
- src/Graphics/Rendering/Plot/Light/Internal.hs +151/−5
- src/Graphics/Rendering/Plot/Light/Internal/Geometry.hs +59/−23
- src/Graphics/Rendering/Plot/Light/PlotTypes/TimeSeries.hs +44/−20
- test/LibSpec.hs +8/−3
README.md view
@@ -23,11 +23,9 @@ Available on Hackage : https://hackage.haskell.org/package/plot-light in the `Graphics.Rendering.Plot.Light` module -Please let me know if documentation is lacking or confusing. - ## Contributing -You can use `plot-light` in your own projects (either personal, academic or commercial), and all feedback such as comments, bug reports, feature requests and patches is welcome.+You can use `plot-light` in your own projects (either personal, academic or commercial). All feedback such as comments, bug reports, new documentation, feature requests and patches is welcome. ## License
plot-light.cabal view
@@ -1,5 +1,5 @@ name: plot-light-version: 0.1.0.9+version: 0.1.1 synopsis: A lightweight plotting library, exporting to SVG description: A lightweight plotting library, exporting to SVG homepage: https://github.com/ocramz/plot-light
src/Graphics/Rendering/Plot/Light.hs view
@@ -20,8 +20,13 @@ -- @import qualified Data.Colour.Names as C@ module Graphics.Rendering.Plot.Light (- -- * Graphical elements- rectCentered, circle, line, axis, text, polyline,+ -- * Plot elements+ -- ** Geometrical primitives+ rectCentered, circle, line, text, polyline, filledPolyline,+ -- ** Composite plot elements+ filledBand, candlestick,+ -- ** Plot utilities+ toPlot, FigureData(..), -- ** Element attributes LineStroke_(..), StrokeLineJoin_(..), TextAnchor_(..), -- ** SVG utilities@@ -40,9 +45,11 @@ -- ** Vector construction v2fromEndpoints, v2fromPoint, -- ** Operations on points- movePoint, moveLabeledPointV2, (-.),+ movePoint, moveLabeledPointV2, (-.), toSvgFrame, toSvgFrameLP, pointRange, -- ** Operations on vectors- frameToFrame,+ frameToFrame, + -- ** Operations on frames+ frameFromPoints, mkFrame, mkFrameOrigin, width, height, -- ** Typeclasses AdditiveGroup(..), VectorSpace(..), Hermitian(..), LinearMap(..), MultiplicativeSemigroup(..), MatrixGroup(..), Eps(..) ) where
src/Graphics/Rendering/Plot/Light/Internal.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}-module Graphics.Rendering.Plot.Light.Internal (Frame(..), mkFrame, mkFrameOrigin, frameToFrame, frameFromDataset, Point(..), mkPoint, LabeledPoint(..), mkLabeledPoint, Axis(..), svgHeader, rectCentered, circle, line, tick, ticks, axis, text, polyline, strokeLineJoin, LineStroke_(..), StrokeLineJoin_(..), TextAnchor_(..), V2(..), Mat2(..), DiagMat2(..), diagMat2, AdditiveGroup(..), VectorSpace(..), Hermitian(..), LinearMap(..), MultiplicativeSemigroup(..), MatrixGroup(..), Eps(..), norm2, normalize2, v2fromEndpoints, v2fromPoint, origin, (-.), movePoint, moveLabeledPointV2, moveLabeledPointV2Frames, e1, e2) where+module Graphics.Rendering.Plot.Light.Internal (FigureData(..), Frame(..), mkFrame, mkFrameOrigin, frameToFrame, frameFromPoints, width, height, Point(..), mkPoint, LabeledPoint(..), mkLabeledPoint, Axis(..), svgHeader, rectCentered, circle, line, tick, ticks, axis, toPlot, text, polyline, filledPolyline, filledBand, candlestick, strokeLineJoin, LineStroke_(..), StrokeLineJoin_(..), TextAnchor_(..), V2(..), Mat2(..), DiagMat2(..), diagMat2, AdditiveGroup(..), VectorSpace(..), Hermitian(..), LinearMap(..), MultiplicativeSemigroup(..), MatrixGroup(..), Eps(..), norm2, normalize2, v2fromEndpoints, v2fromPoint, origin, (-.), pointRange, movePoint, moveLabeledPointV2, moveLabeledPointV2Frames, toSvgFrame, toSvgFrameLP, e1, e2) where import Data.Monoid ((<>)) import qualified Data.Foldable as F (toList)@@ -28,7 +28,26 @@ import Graphics.Rendering.Plot.Light.Internal.Geometry +-- | Figure data+data FigureData a = FigureData {+ -- | Figure width+ figWidth :: a+ -- | Figure height+ , figHeight :: a+ -- | Left margin fraction (w.r.t figure width)+ , figLeftMFrac :: a+ -- | Right margin fraction (w.r.t figure width) + , figRightMFrac :: a+ -- | Top margin fraction (w.r.t figure height)+ , figTopMFrac :: a+ -- | Bottom margin fraction (w.r.t figure height) + , figBottomMFrac :: a+ -- | Tick label font size+ , figLabelFontSize :: Int+ } deriving (Eq, Show) ++ -- | Create the SVG header from a `Frame` svgHeader :: Real a => Frame a -> Svg -> Svg svgHeader fd =@@ -48,11 +67,12 @@ Point a -- ^ Center coordinates -> a -- ^ Width -> a -- ^ Height+ -> a -- ^ Stroke width -> Maybe (C.Colour Double) -- ^ Stroke colour -> Maybe (C.Colour Double) -- ^ Fill colour -> Svg-rectCentered (Point x0 y0) wid hei scol fcol = S.g ! SA.transform (S.translate x0c y0c) $ - S.rect ! SA.width (vd wid) ! SA.height (vd hei) ! colourFillOpt fcol ! colourStrokeOpt scol where+rectCentered (Point x0 y0) wid hei sw scol fcol = S.g ! SA.transform (S.translate x0c y0c) $ + S.rect ! SA.width (vd wid) ! SA.height (vd hei) ! colourFillOpt fcol ! colourStrokeOpt scol ! SA.strokeWidth (vd sw) where x0c = x0 - (wid / 2) y0c = y0 - (hei / 2) @@ -152,6 +172,49 @@ | otherwise = setPointX ox ++-- | `toPlot` performs a number of related operations:+--+-- * Maps the dataset to the figure frame+-- +-- * Renders the X, Y axes+--+-- * Renders the transformed dataset onto the newly created plot canvas+toPlot+ :: (Functor t, Foldable t, Show a, RealFrac a) =>+ FigureData a + -> (l -> T.Text) -- ^ X tick label+ -> (l -> T.Text) -- ^ Y tick label+ -> a -- ^ X label rotation angle+ -> a -- ^ Y label rotation angle+ -> a -- ^ Stroke width+ -> C.Colour Double -- ^ Stroke colour+ -> (t (LabeledPoint l a) -> t (LabeledPoint l a)) -- ^ X axis labels+ -> (t (LabeledPoint l a) -> t (LabeledPoint l a)) -- ^ Y axis labels+ -> (t (LabeledPoint l a) -> Svg) -- ^ Data rendering function+ -> t (LabeledPoint l a) -- ^ Data+ -> Svg +toPlot fd flabelx flabely rotx roty sw col1 tickXf tickYf plotf dat = do+ axis oSvg X (right - left) sw col1 0.05 Continuous fontsize rotx TAEnd flabelx (V2 (-10) 0) (tickXf dat')+ axis oSvg Y (top - bot) sw col1 0.05 Continuous fontsize roty TAEnd flabely (V2 (-10) 0) (tickYf dat')+ plotf dat'+ where+ fontsize = figLabelFontSize fd+ wfig = figWidth fd+ hfig = figHeight fd+ (left, right) = (figLeftMFrac fd * wfig, figRightMFrac fd * wfig)+ (top, bot) = (figTopMFrac fd * hfig, figBottomMFrac fd * hfig)+ oTo = Point left top+ p2To = Point right bot+ from = frameFromPoints $ _lp <$> dat+ to = mkFrame oTo p2To+ dat' = toSvgFrameLP from to False <$> dat+ oSvg = Point left bot+++++ -- * text -- | `text` renders text onto the SVG canvas@@ -196,11 +259,12 @@ :: (Real a1, Real a) => Point a1 -- ^ Center -> a -- ^ Radius+ -> a -- ^ Stroke width -> Maybe (C.Colour Double) -- ^ Stroke colour -> Maybe (C.Colour Double) -- ^ Fill colour -> Svg-circle (Point x y) r scol fcol =- S.circle ! SA.cx (vd x) ! SA.cy (vd y) ! SA.r (vd r) ! colourFillOpt fcol ! colourStrokeOpt scol+circle (Point x y) r sw scol fcol =+ S.circle ! SA.cx (vd x) ! SA.cy (vd y) ! SA.r (vd r) ! colourFillOpt fcol ! colourStrokeOpt scol ! SA.strokeWidth (vd sw) @@ -232,6 +296,70 @@ colourStrokeOpt (Just c) = SA.stroke (colourAttr c) +-- | A filled polyline+--+-- > > putStrLn $ renderSvg $ filledPolyline C.coral 0.3 [(Point 0 1), (Point 10 40), Point 34 50, Point 30 5]+-- > <polyline points="0,1 10,40 34,50 30,5" fill="#ff7f50" fill-opacity="0.3" />+filledPolyline :: (Foldable t, Show a, Real o) =>+ C.Colour Double -- ^ Fill colour+ -> o -- ^ Fill opacity+ -> t (Point a) -- ^ Contour point coordinates+ -> Svg+filledPolyline col opac lis = S.polyline ! SA.points (S.toValue $ unwords $ map show $ F.toList lis) ! SA.fill (colourAttr col) ! SA.fillOpacity (vd opac)+++-- | A filled band of colour, given the coordinates of its center line+--+-- This element can be used to overlay uncertainty ranges (e.g. the first standard deviation) associated with a given data series.+filledBand :: (Foldable t, Real o, Show a) =>+ C.Colour Double -- ^ Fill colour+ -> o -- ^ Fill opacity+ -> (LabeledPoint l a -> a) -- ^ Band maximum value+ -> (LabeledPoint l a -> a) -- ^ Band minimum value+ -> t (LabeledPoint l a) -- ^ Centerline points+ -> Svg+filledBand col opac ftop fbot lis0 = filledPolyline col opac (lis1 <> lis2) where+ lis = F.toList lis0+ f1 lp = setPointY (ftop lp) $ _lp lp+ f2 lp = setPointY (fbot lp) $ _lp lp+ lis1 = f1 <$> lis+ lis2 = f2 <$> reverse lis+++-- | A `candlestick` glyph for time series plots. This is a type of box glyph, commonly used in plotting financial time series.+--+-- Some financial market quantities such as currency exchange rates are aggregated over some time period (e.g. a day) and summarized by various quantities, for example opening and closing rates, as well as maximum and minimum over the period.+--+-- By convention, the `candlestick` colour depends on the derivative sign of one such quantity (e.g. it is green if the market closes higher than it opened, and red otherwise).+candlestick+ :: (Show a, RealFrac a) =>+ (LabeledPoint l a -> Bool) -- ^ If True, fill the box with the first colour, otherwise with the second+ -> (LabeledPoint l a -> a) -- ^ Box maximum value+ -> (LabeledPoint l a -> a) -- ^ Box minimum value+ -> (LabeledPoint l a -> a) -- ^ Line maximum value + -> (LabeledPoint l a -> a) -- ^ Line minimum value+ -> a -- ^ Box width+ -> a -- ^ Stroke width+ -> C.Colour Double -- ^ First box colour+ -> C.Colour Double -- ^ Second box colour+ -> C.Colour Double -- ^ Line stroke colour+ -> LabeledPoint l a -- ^ Data point+ -> Svg+candlestick fdec fboxmin fboxmax fmin fmax wid sw col1 col2 colstroke lp = do+ line pmin pmax sw Continuous colstroke+ rectCentered p wid hei sw (Just colstroke) (Just col)+ where+ p = _lp lp+ pmin = setPointY (fmin lp) p+ pmax = setPointY (fmax lp) p+ hei = fboxmax lp - fboxmin lp+ col | fdec lp = col1+ | otherwise = col2+++++ -- | Specify the type of connection between line segments data StrokeLineJoin_ = Miter | Round | Bevel | Inherit deriving (Eq, Show) @@ -241,6 +369,24 @@ | slj == Round = "round" | slj == Bevel = "bevel" | otherwise = "inherit"+++-- | Move point to the SVG frame of reference (for which the origing is a the top-left corner of the screen)+toSvgFrame ::+ Fractional a =>+ Frame a -- ^ Initial frame+ -> Frame a -- ^ Final frame+ -> Bool -- ^ Flip L-R in [0,1] x [0,1]+ -> Point a -- ^ Point in the initial frame+ -> Point a+toSvgFrame from to fliplr p = pointFromV2 v' where+ v' = frameToFrame from to fliplr True (v2fromPoint p)+++-- | Move LabeledPoint to the SVG frame of reference (uses `toSvgFrame` ) +toSvgFrameLP ::+ Fractional a => Frame a -> Frame a -> Bool -> LabeledPoint l a -> LabeledPoint l a+toSvgFrameLP from to fliplr (LabeledPoint p lab) = LabeledPoint (toSvgFrame from to fliplr p) lab
src/Graphics/Rendering/Plot/Light/Internal/Geometry.hs view
@@ -56,22 +56,24 @@ mkFrameOrigin w h = Frame origin (Point w h) --- | Create a `Frame` from a container of `LabeledPoint`s `P`, i.e. construct two points `p1` and `p2` such that :+-- | Create a `Frame` from a container of `Point`s `P`, i.e. construct two points `p1` and `p2` such that : -- -- p1 := inf(x,y) P -- p2 := sup(x,y) P-frameFromDataset ::- (Functor t, Ord a, Foldable t) => t (LabeledPoint l a) -> Frame a-frameFromDataset ds = mkFrame (Point mx my) (Point mmx mmy)+frameFromPoints :: (Ord a, Foldable t, Functor t) =>+ t (Point a) -> Frame a+frameFromPoints ds = mkFrame (Point mx my) (Point mmx mmy) where- xcoord = _px . _lp <$> ds- ycoord = _py . _lp <$> ds+ xcoord = _px <$> ds+ ycoord = _py <$> ds mmx = maximum xcoord mmy = maximum ycoord mx = minimum xcoord my = minimum ycoord- ++ + -- | Frame corner coordinates xmin, xmax, ymin, ymax :: Frame a -> a xmin = _px . _fpmin@@ -209,6 +211,12 @@ diagMat2 :: Num a => a -> a -> DiagMat2 a diagMat2 = DMat2 ++-- | Rotation matrix+rotMtx :: Floating a => a -> Mat2 a+rotMtx r = Mat2 (cos r) (- (sin r)) (sin r) (cos r)++ -- | The class of invertible linear transformations class LinearMap m v => MatrixGroup m v where -- | Inverse matrix action on a vector@@ -224,10 +232,14 @@ instance Fractional a => MatrixGroup (DiagMat2 a) (V2 a) where DMat2 d1 d2 <\> V2 vx vy = V2 (vx / d1) (vy / d2) --- | Build a V2 from a `Point` p (i.e. assuming the V2 points from the origin (0,0) to p)+-- | Build a `V2` v from a `Point` p (i.e. assuming v points from the origin (0,0) to p) v2fromPoint :: Num a => Point a -> V2 a v2fromPoint p = origin -. p +-- | Build a `Point` p from a `V2` v (i.e. assuming v points from the origin (0,0) to p)+pointFromV2 :: V2 a -> Point a+pointFromV2 (V2 x y) = Point x y+ -- | Move a point along a vector movePoint :: Num a => V2 a -> Point a -> Point a movePoint (V2 vx vy) (Point px py) = Point (px + vx) (py + vy)@@ -237,8 +249,18 @@ moveLabeledPointV2 = moveLabeledPoint . movePoint +-- | `pointRange n p q` returns a list of `n+1` equi-spaced `Point`s between `p` and `q` (i.e. the input points are included as the first and last points in the list)+pointRange :: (Fractional a, Integral n) =>+ n -> Point a -> Point a -> [Point a]+pointRange n p q = [ movePoint (fromIntegral x .* vnth) p | x <- [0 .. n]]+ where+ v = p -. q+ vnth = (1/fromIntegral n) .* v +++ fromFrame :: Fractional a => Frame a -> V2 a -> V2 a fromFrame from v = mfrom <\> (v ^-^ vfrom) where vfrom = v2fromPoint (_fpmin from) -- min.point vector of `from`@@ -252,39 +274,53 @@ --- | Given two frames `F1` and `F2`, returns a function `f` that maps an arbitrary vector `v` that points within `F1` to one contained within `F2`.+-- | Given two frames `F1` and `F2`, returns a function `f` that maps an arbitrary vector `v` contained within `F1` onto one contained within `F2`. ----- 1. map `v` into a unit square vector `v01` with an affine transformation+-- This function is composed of three affine maps : ----- 2. (optional) map `v01` into another point in the unit square via a linear rescaling+-- 1. map `v` into a vector `v01` that points within the unit square, ----- 3. map `v01'` onto `F2` with a second affine transformation+-- 2. map `v01` onto `v01'`. This transformation serves to e.g. flip the dataset along the y axis (since the origin of the SVG canvas is the top-left corner of the screen). If this is not needed one can just supply the identity matrix and the zero vector, ----- NB: we do not check that `v` is actually contained within the `F1`. This has to be supplied correctly by the user.-frameToFrame :: (Fractional a, LinearMap m (V2 a)) =>+-- 3. map `v01'` onto the target frame `F2`. +--+-- NB: we do not check that `v` is actually contained within the `F1`, nor that `v01'` is still contained within [0,1] x [0, 1]. This has to be supplied correctly by the user.+frameToFrame :: Fractional a => Frame a -- ^ Initial frame -> Frame a -- ^ Final frame- -> m -- ^ Optional rescaling in [0,1] x [0,1]- -> V2 a -- ^ Optional shift + -> Bool -- ^ Flip L-R in [0,1] x [0,1]+ -> Bool -- ^ Flip U-D in [0,1] x [0,1] -> V2 a -- ^ Initial vector -> V2 a-frameToFrame from to mopt vopt v = toFrame to v01'+frameToFrame from to fliplr flipud v = toFrame to v01' where v01 = fromFrame from v- v01' = (mopt #> v01) ^+^ vopt+ v01' | fliplr && flipud = flipLR01 (flipUD01 v01)+ | fliplr = flipLR01 v01+ | flipud = flipUD01 v01+ | otherwise = v01 ++flipLR01, flipUD01 :: Num a => V2 a -> V2 a+flipLR01 (V2 a b) = V2 (1 - a) b+flipUD01 (V2 a b) = V2 a (1 - b)++++ moveLabeledPointV2Frames ::- (LinearMap m (V2 a), Fractional a) =>+ Fractional a => Frame a -- ^ Initial frame -> Frame a -- ^ Final frame- -> m -- ^ Optional rescaling in [0,1] x [0,1]- -> V2 a -- ^ Optional shift+ -> Bool -- ^ Flip L-R in [0,1] x [0,1]+ -> Bool -- ^ Flip U-D in [0,1] x [0,1] -> LabeledPoint l a -- ^ Initial `LabeledPoint` -> LabeledPoint l a-moveLabeledPointV2Frames from to mopt vopt lp = moveLabeledPointV2 vmove lp+moveLabeledPointV2Frames from to fliplr flipud lp = LabeledPoint p' (_lplabel lp) where vlp = v2fromPoint $ _lp lp -- vector associated with starting point- vmove = frameToFrame from to mopt vopt vlp -- frame translation vector+ vlp' = frameToFrame from to fliplr flipud vlp -- vector associated w new point+ p' = pointFromV2 vlp'
src/Graphics/Rendering/Plot/Light/PlotTypes/TimeSeries.hs view
@@ -11,6 +11,7 @@ import Graphics.Rendering.Plot.Light.Internal import Data.TimeSeries+import Data.TimeSeries.Forex -- For debugging import Text.Blaze.Svg@@ -25,33 +26,52 @@ -- 1. Remap the figure data to fit within the FigData ranges, expressed in pixels -- 2. Flip the data along the y axis since the origin in SVG is the top-left corner of the screen --- tsAxis :: (Num a, LinearMap (DiagMat2 a) (V2 a), RealFrac a, Show a,--- Foldable t, Functor t) =>--- (a -> a)--- -> a--- -> a--- -> a--- -> C.Colour Double--- -> a--- -> t (TsPoint a)--- -> Svg-tsAxis fval wFig hFig sw col rot ps = dat' -- axis origin X wFig sw col 0.01 Continuous rot TAEnd T.pack (V2 (-10) 0) dat'+tsAxis fval wfig hfig sw col1 col2 rot ps = do + axis oSvg X (right - left) sw col1 0.01 Continuous 10 rot TAEnd (T.pack . fst) (V2 (-10) 0) dat'+ axis oSvg Y (top - bot) sw col1 0.01 Continuous 10 0 TAEnd (T.pack . snd) (V2 (-10) 0) dat'+ polyline (_lp <$> dat') sw Continuous Round col2 where- lpFun = tspToLP fval (\t _ -> show t)- dat = lpFun <$> ps- frameFrom = frameFromDataset dat- frameTo = mkFrameOrigin wFig hFig- dat' = moveLabeledPointV2Frames frameFrom frameTo (mempty :: DiagMat2 Scientific) (V2 0 0) <$> dat+ dat = tspToLP fval (\(Tick d t) v -> (show (d, t), show (fval v))) <$> ps+ dat' = toSvgFrameLP from to False <$> dat + (left, right) = (0.1 * wfig, 0.9 * wfig)+ (top, bot) = (0.1 * hfig, 0.9 * hfig)+ oTo = Point left top+ p2To = Point right bot+ from = frameFromPoints $ _lp <$> dat+ to = mkFrame oTo p2To+ oSvg = Point left bot+ + +tsAxis' fval ftickx fticky fd sw col rot ps =+ toPlot fd (T.pack . ftickx) (T.pack . fticky) rot 0 sw col + -nth xss n = reverse $ go xss n [] where- go (_:xs) i l | i>0 = go xs (i-1) l- go (x:xs) i l | i==0 = go xs n (x : l)- go [] _ l = l +-- nth xss n = reverse $ go xss n [] where+-- go (_:xs) i l | i>0 = go xs (i-1) l+-- go (x:xs) i l | i==0 = go xs n (x : l)+-- go [] _ l = l++-- tsp1 :: Maybe (TsPoint (FxRow Double))+-- tsp1 = Tsp <$> mkTick 2017 16 3 20 30 01 <*> Just (FxRow pi 20 10 5.4)++dat1 :: [ LabeledPoint String Double ]+dat1 = [LabeledPoint (Point 0 1) "blah",+ LabeledPoint (Point 2 0) "asdf",+ LabeledPoint (Point 3 1) "yo"]++to, from :: Frame Double+from = frameFromPoints $ _lp <$> dat1+to = mkFrameOrigin 400 300+++++ -- * Helpers@@ -76,6 +96,10 @@ fromTick :: Tick -> Rational fromTick (Tick d t) = fromIntegral (toModifiedJulianDay d) + timeOfDayToDayFraction t ++-- fromTickI (Tick d t) = toModifiedJulianDay d + timeOfDayToDayFraction t++
test/LibSpec.hs view
@@ -27,9 +27,7 @@ let from = Frame (Point 5 1) (Point 8 3) :: Frame Double to = Frame (Point 1 2) (Point 4 4) v1 = v2fromPoint $ Point 7 2- mopt = diagMat2 1 1 :: DiagMat2 Double- vopt = V2 0 0 - v2 = frameToFrame from to mopt vopt v1+ v2 = frameToFrame from to False False v1 p2 = movePoint v2 origin -- p2 `shouldBe` Point 3 3 norm2 (p2 -. Point 3 3) ~= 0 `shouldBe` True@@ -38,7 +36,14 @@ +ps = [Point 12312 0.2, Point 13420.2 0.3, Point 14567 0.14] +fin = frameFromPoints ps+fout = mkFrame (Point 0 0) (Point 1 1)++vf = frameToFrame fin fout False False++v1 = V2 13555.2 0.25