plot-light 0.1.0.0 → 0.1.0.1
raw patch · 10 files changed
+323/−59 lines, 10 filesdep +attoparsec-timedep −vectordep ~basenew-component:exe:plot-light
Dependencies added: attoparsec-time
Dependencies removed: vector
Dependency ranges changed: base
Files
- app/timeseries/Main.hs +15/−0
- data/forex +174/−0
- data/heatmap-bw +6/−0
- plot-light.cabal +17/−9
- src/Data/TimeSeries/Forex.hs +22/−0
- src/Graphics/Rendering/Plot/Light.hs +0/−1
- src/Graphics/Rendering/Plot/Light/IO/Text.hs +41/−6
- src/Graphics/Rendering/Plot/Light/Internal.hs +24/−34
- src/Graphics/Rendering/Plot/Light/Internal/Types.hs +20/−0
- src/Graphics/Rendering/Plot/Light/PlotTypes/TimeSeries.hs +4/−9
+ app/timeseries/Main.hs view
@@ -0,0 +1,15 @@+module Main where++import Graphics.Rendering.Plot.Light.IO.Text++import qualified Data.Attoparsec.Text as A+import qualified Data.Text.IO as T+++fname = "data/forex"++main = do+ d <- T.readFile fname+ let pd = A.parseOnly parseFxDataset d+ case pd of Left e -> error e+ Right datarows -> pure datarows
+ data/forex view
@@ -0,0 +1,174 @@+2017-06-26 21:00:00,1.0876,1.0880,1.0872,1.0874+2017-06-26 20:00:00,1.0873,1.0875,1.0872,1.0875+2017-06-26 19:00:00,1.0874,1.0875,1.0873,1.0874+2017-06-26 18:00:00,1.0870,1.0875,1.0870,1.0875+2017-06-26 17:00:00,1.0873,1.0873,1.0870,1.0870+2017-06-26 16:00:00,1.0869,1.0873,1.0867,1.0873+2017-06-26 15:00:00,1.0873,1.0876,1.0869,1.0870+2017-06-26 14:00:00,1.0875,1.0877,1.0871,1.0873+2017-06-26 13:00:00,1.0882,1.0883,1.0875,1.0875+2017-06-26 12:00:00,1.0882,1.0888,1.0880,1.0885+2017-06-26 11:00:00,1.0881,1.0882,1.0879,1.0881+2017-06-26 10:00:00,1.0881,1.0883,1.0879,1.0881+2017-06-26 09:00:00,1.0864,1.0879,1.0862,1.0879+2017-06-26 08:00:00,1.0858,1.0866,1.0858,1.0862+2017-06-26 07:00:00,1.0860,1.0862,1.0857,1.0860+2017-06-26 06:00:00,1.0855,1.0859,1.0854,1.0859+2017-06-26 05:00:00,1.0857,1.0859,1.0856,1.0856+2017-06-26 04:00:00,1.0858,1.0859,1.0857,1.0857+2017-06-26 03:00:00,1.0855,1.0859,1.0855,1.0858+2017-06-26 02:00:00,1.0856,1.0857,1.0855,1.0855+2017-06-26 01:00:00,1.0855,1.0858,1.0855,1.0856+2017-06-26 00:00:00,1.0856,1.0856,1.0855,1.0856+2017-06-25 23:00:00,1.0855,1.0856,1.0854,1.0855+2017-06-25 22:00:00,1.0855,1.0857,1.0851,1.0855+2017-06-25 21:00:00,1.0859,1.0863,1.0851,1.0855+2017-06-23 20:00:00,1.0855,1.0858,1.0852,1.0852+2017-06-23 19:00:00,1.0852,1.0855,1.0851,1.0855+2017-06-23 18:00:00,1.0854,1.0856,1.0852,1.0852+2017-06-23 17:00:00,1.0856,1.0856,1.0852,1.0854+2017-06-23 16:00:00,1.0853,1.0854,1.0851,1.0854+2017-06-23 15:00:00,1.0850,1.0853,1.0849,1.0853+2017-06-23 14:00:00,1.0852,1.0853,1.0847,1.0848+2017-06-23 13:00:00,1.0856,1.0859,1.0849,1.0849+2017-06-23 12:00:00,1.0856,1.0856,1.0851,1.0854+2017-06-23 11:00:00,1.0848,1.0856,1.0848,1.0856+2017-06-23 10:00:00,1.0854,1.0855,1.0845,1.0848+2017-06-23 09:00:00,1.0842,1.0852,1.0841,1.0852+2017-06-23 08:00:00,1.0844,1.0844,1.0837,1.0843+2017-06-23 07:00:00,1.0842,1.0848,1.0840,1.0845+2017-06-23 06:00:00,1.0838,1.0845,1.0838,1.0842+2017-06-23 05:00:00,1.0837,1.0839,1.0837,1.0838+2017-06-23 04:00:00,1.0837,1.0838,1.0836,1.0837+2017-06-23 03:00:00,1.0837,1.0837,1.0836,1.0836+2017-06-23 02:00:00,1.0838,1.0838,1.0835,1.0836+2017-06-23 01:00:00,1.0837,1.0839,1.0836,1.0837+2017-06-23 00:00:00,1.0837,1.0838,1.0835,1.0837+2017-06-22 23:00:00,1.0838,1.0838,1.0836,1.0837+2017-06-22 22:00:00,1.0839,1.0843,1.0837,1.0838+2017-06-22 21:00:00,1.0838,1.0856,1.0837,1.0838+2017-06-22 20:00:00,1.0838,1.0839,1.0837,1.0838+2017-06-22 19:00:00,1.0842,1.0842,1.0836,1.0837+2017-06-22 18:00:00,1.0841,1.0843,1.0840,1.0841+2017-06-22 17:00:00,1.0845,1.0847,1.0840,1.0841+2017-06-22 16:00:00,1.0847,1.0848,1.0843,1.0845+2017-06-22 15:00:00,1.0848,1.0851,1.0843,1.0845+2017-06-22 14:00:00,1.0852,1.0858,1.0844,1.0850+2017-06-22 13:00:00,1.0860,1.0864,1.0851,1.0851+2017-06-22 12:00:00,1.0873,1.0873,1.0862,1.0862+2017-06-22 11:00:00,1.0869,1.0873,1.0868,1.0871+2017-06-22 10:00:00,1.0871,1.0874,1.0869,1.0870+2017-06-22 09:00:00,1.0870,1.0871,1.0866,1.0870+2017-06-22 08:00:00,1.0861,1.0870,1.0860,1.0869+2017-06-22 07:00:00,1.0857,1.0862,1.0855,1.0861+2017-06-22 06:00:00,1.0863,1.0864,1.0857,1.0857+2017-06-22 05:00:00,1.0863,1.0864,1.0862,1.0863+2017-06-22 04:00:00,1.0863,1.0864,1.0861,1.0863+2017-06-22 03:00:00,1.0860,1.0863,1.0860,1.0863+2017-06-22 02:00:00,1.0862,1.0862,1.0859,1.0860+2017-06-22 01:00:00,1.0859,1.0863,1.0859,1.0863+2017-06-22 00:00:00,1.0861,1.0863,1.0860,1.0860+2017-06-21 23:00:00,1.0861,1.0862,1.0860,1.0861+2017-06-21 22:00:00,1.0861,1.0862,1.0860,1.0861+2017-06-21 21:00:00,1.0862,1.0866,1.0860,1.0861+2017-06-21 20:00:00,1.0861,1.0862,1.0859,1.0861+2017-06-21 19:00:00,1.0862,1.0862,1.0860,1.0860+2017-06-21 18:00:00,1.0860,1.0862,1.0860,1.0861+2017-06-21 17:00:00,1.0858,1.0861,1.0855,1.0859+2017-06-21 16:00:00,1.0860,1.0862,1.0858,1.0858+2017-06-21 15:00:00,1.0864,1.0864,1.0858,1.0858+2017-06-21 14:00:00,1.0859,1.0866,1.0858,1.0865+2017-06-21 13:00:00,1.0859,1.0861,1.0854,1.0856+2017-06-21 12:00:00,1.0860,1.0862,1.0858,1.0860+2017-06-21 11:00:00,1.0864,1.0865,1.0856,1.0860+2017-06-21 10:00:00,1.0855,1.0863,1.0855,1.0863+2017-06-21 09:00:00,1.0855,1.0858,1.0854,1.0854+2017-06-21 08:00:00,1.0848,1.0854,1.0846,1.0854+2017-06-21 07:00:00,1.0852,1.0853,1.0848,1.0850+2017-06-21 06:00:00,1.0852,1.0853,1.0849,1.0851+2017-06-21 05:00:00,1.0851,1.0852,1.0851,1.0851+2017-06-21 04:00:00,1.0851,1.0852,1.0850,1.0851+2017-06-21 03:00:00,1.0851,1.0853,1.0851,1.0852+2017-06-21 02:00:00,1.0855,1.0855,1.0849,1.0851+2017-06-21 01:00:00,1.0854,1.0855,1.0853,1.0855+2017-06-21 00:00:00,1.0856,1.0856,1.0850,1.0852+2017-06-20 23:00:00,1.0856,1.0857,1.0855,1.0856+2017-06-20 22:00:00,1.0866,1.0871,1.0856,1.0856+2017-06-20 21:00:00,1.0858,1.0870,1.0856,1.0861+2017-06-20 20:00:00,1.0855,1.0858,1.0855,1.0858+2017-06-20 19:00:00,1.0855,1.0857,1.0854,1.0855+2017-06-20 18:00:00,1.0857,1.0858,1.0855,1.0855+2017-06-20 17:00:00,1.0857,1.0859,1.0856,1.0858+2017-06-20 16:00:00,1.0858,1.0861,1.0857,1.0858+2017-06-20 15:00:00,1.0860,1.0862,1.0858,1.0860+2017-06-20 14:00:00,1.0859,1.0861,1.0857,1.0859+2017-06-20 13:00:00,1.0864,1.0865,1.0858,1.0859+2017-06-20 12:00:00,1.0854,1.0867,1.0854,1.0865+2017-06-20 11:00:00,1.0864,1.0864,1.0854,1.0855+2017-06-20 10:00:00,1.0861,1.0865,1.0860,1.0865+2017-06-20 09:00:00,1.0871,1.0875,1.0857,1.0864+2017-06-20 08:00:00,1.0874,1.0877,1.0868,1.0870+2017-06-20 07:00:00,1.0879,1.0880,1.0864,1.0872+2017-06-20 06:00:00,1.0878,1.0881,1.0877,1.0880+2017-06-20 05:00:00,1.0881,1.0882,1.0877,1.0877+2017-06-20 04:00:00,1.0879,1.0882,1.0878,1.0880+2017-06-20 03:00:00,1.0880,1.0881,1.0879,1.0879+2017-06-20 02:00:00,1.0880,1.0881,1.0878,1.0880+2017-06-20 01:00:00,1.0879,1.0880,1.0878,1.0880+2017-06-20 00:00:00,1.0880,1.0881,1.0878,1.0878+2017-06-19 23:00:00,1.0880,1.0880,1.0877,1.0880+2017-06-19 22:00:00,1.0882,1.0883,1.0879,1.0879+2017-06-19 21:00:00,1.0878,1.0890,1.0875,1.0882+2017-06-19 20:00:00,1.0878,1.0879,1.0877,1.0878+2017-06-19 19:00:00,1.0879,1.0879,1.0877,1.0879+2017-06-19 18:00:00,1.0879,1.0879,1.0876,1.0877+2017-06-19 17:00:00,1.0875,1.0879,1.0875,1.0878+2017-06-19 16:00:00,1.0877,1.0879,1.0875,1.0876+2017-06-19 15:00:00,1.0877,1.0879,1.0873,1.0877+2017-06-19 14:00:00,1.0883,1.0883,1.0877,1.0881+2017-06-19 13:00:00,1.0877,1.0885,1.0875,1.0885+2017-06-19 12:00:00,1.0869,1.0882,1.0868,1.0882+2017-06-19 11:00:00,1.0879,1.0880,1.0869,1.0870+2017-06-19 10:00:00,1.0876,1.0880,1.0873,1.0878+2017-06-19 09:00:00,1.0880,1.0881,1.0875,1.0876+2017-06-19 08:00:00,1.0883,1.0885,1.0877,1.0881+2017-06-19 07:00:00,1.0903,1.0903,1.0889,1.0890+2017-06-19 06:00:00,1.0905,1.0910,1.0904,1.0905+2017-06-19 05:00:00,1.0905,1.0905,1.0903,1.0904+2017-06-19 04:00:00,1.0902,1.0906,1.0902,1.0905+2017-06-19 03:00:00,1.0903,1.0903,1.0901,1.0902+2017-06-19 02:00:00,1.0904,1.0905,1.0902,1.0903+2017-06-19 01:00:00,1.0903,1.0905,1.0903,1.0904+2017-06-19 00:00:00,1.0906,1.0906,1.0902,1.0902+2017-06-18 23:00:00,1.0905,1.0905,1.0902,1.0905+2017-06-18 22:00:00,1.0903,1.0905,1.0901,1.0905+2017-06-18 21:00:00,1.0911,1.0911,1.0902,1.0907+2017-06-16 20:00:00,1.0900,1.0907,1.0898,1.0906+2017-06-16 19:00:00,1.0901,1.0902,1.0898,1.0900+2017-06-16 18:00:00,1.0904,1.0904,1.0900,1.0902+2017-06-16 17:00:00,1.0901,1.0902,1.0899,1.0901+2017-06-16 16:00:00,1.0902,1.0902,1.0898,1.0901+2017-06-16 15:00:00,1.0898,1.0902,1.0893,1.0901+2017-06-16 14:00:00,1.0890,1.0898,1.0886,1.0898+2017-06-16 13:00:00,1.0886,1.0888,1.0883,1.0884+2017-06-16 12:00:00,1.0885,1.0891,1.0884,1.0886+2017-06-16 11:00:00,1.0889,1.0890,1.0885,1.0885+2017-06-16 10:00:00,1.0881,1.0893,1.0881,1.0890+2017-06-16 09:00:00,1.0882,1.0883,1.0877,1.0882+2017-06-16 08:00:00,1.0876,1.0882,1.0876,1.0882+2017-06-16 07:00:00,1.0871,1.0876,1.0869,1.0875+2017-06-16 06:00:00,1.0870,1.0874,1.0867,1.0874+2017-06-16 05:00:00,1.0871,1.0872,1.0869,1.0870+2017-06-16 04:00:00,1.0871,1.0872,1.0870,1.0870+2017-06-16 03:00:00,1.0871,1.0872,1.0870,1.0871+2017-06-16 02:00:00,1.0872,1.0872,1.0869,1.0871+2017-06-16 01:00:00,1.0872,1.0873,1.0870,1.0872+2017-06-16 00:00:00,1.0874,1.0874,1.0871,1.0872+2017-06-15 23:00:00,1.0872,1.0873,1.0871,1.0872+2017-06-15 22:00:00,1.0875,1.0875,1.0871,1.0872+2017-06-15 21:00:00,1.0873,1.0876,1.0871,1.0875+2017-06-15 20:00:00,1.0874,1.0875,1.0871,1.0873+2017-06-15 19:00:00,1.0875,1.0875,1.0873,1.0873+2017-06-15 18:00:00,1.0874,1.0875,1.0873,1.0874+2017-06-15 17:00:00,1.0872,1.0874,1.0871,1.0872+2017-06-15 16:00:00,1.0873,1.0874,1.0871,1.0871
+ data/heatmap-bw view
@@ -0,0 +1,6 @@+6 5 4 3 1 0+3 2 2 0 0 1+0 0 0 0 1 0+0 0 0 0 2 3+0 0 1 2 4 3+0 1 2 3 4 5
plot-light.cabal view
@@ -1,5 +1,5 @@ name: plot-light-version: 0.1.0.0+version: 0.1.0.1 synopsis: A lightweight plotting library, exporting to SVG -- description: homepage: https://github.com/ocramz/plot-light@@ -13,6 +13,9 @@ extra-source-files: README.md cabal-version: >=1.10 tested-with: GHC == 8.0.2+data-dir: data+data-files: forex+ heatmap-bw library default-language: Haskell2010@@ -24,9 +27,12 @@ Graphics.Rendering.Plot.Light.IO.Text Graphics.Rendering.Plot.Light.PlotTypes.Heatmap Graphics.Rendering.Plot.Light.PlotTypes.TimeSeries+ other-modules: Data.TimeSeries.Forex+ Graphics.Rendering.Plot.Light.Internal.Types build-depends: base >= 4.7 && < 5 , time- , vector+ , attoparsec-time + -- , vector , attoparsec , scientific , text@@ -34,13 +40,15 @@ , palette , blaze-svg --- executable plot-light--- default-language: Haskell2010--- ghc-options: -threaded -rtsopts -with-rtsopts=-N--- hs-source-dirs: app--- main-is: Main.hs--- build-depends: base--- , plot-light+executable plot-light+ default-language: Haskell2010+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ hs-source-dirs: app/timeseries+ main-is: Main.hs+ build-depends: base+ , plot-light+ , attoparsec+ , text test-suite spec default-language: Haskell2010
+ src/Data/TimeSeries/Forex.hs view
@@ -0,0 +1,22 @@+module Data.TimeSeries.Forex where++import Data.Time++data FxRow a = FxRow {+ rateOpen :: a+ , rateHigh :: a+ , rateLow :: a+ , rateClose :: a+ } deriving (Eq, Show)+++-- | An instant, defined by date (Day) and TimeOfDay+data Tick = Tick Day TimeOfDay+ deriving (Eq, Show, Ord)++-- | A point in a time series+data TsPoint a =+ Tsp {+ _tick :: Tick,+ _val :: a+ } deriving (Eq, Show)
src/Graphics/Rendering/Plot/Light.hs view
@@ -3,7 +3,6 @@ -- import Data.Foldable import qualified Data.Text as T-import qualified Data.Vector as V import Text.Blaze.Svg import Text.Blaze.Svg11 ((!), mkPath, rotate, translate, l, m)
src/Graphics/Rendering/Plot/Light/IO/Text.hs view
@@ -1,29 +1,64 @@ module Graphics.Rendering.Plot.Light.IO.Text where - import Data.Text import qualified Data.Attoparsec.Text as A import qualified Data.Attoparsec.Internal.Types as AP (Parser) import Data.Scientific +import Control.Applicative ((<|>))+import Data.Time (Day, TimeOfDay)+import qualified Attoparsec.Time as AT +import Data.TimeSeries.Forex --- row = many' decimal space, comma :: A.Parser Char space = A.char ' ' comma = A.char ',' --- rowNums :: A.Parser Scientific+-- | Parse a row of numbers, separated by `sep` rowNums :: AP.Parser Text s -> AP.Parser Text [Scientific]-rowNums = A.sepBy A.scientific+rowNums sep = A.sepBy A.scientific sep rowNumSpace :: AP.Parser Text [Scientific] rowNumSpace = rowNums space -- -- | parse a grid of numbers, separated by `sep` gridNum :: AP.Parser Text s -> AP.Parser Text [[Scientific]] gridNum sep = A.sepBy (rowNums sep) A.endOfLine++++++++++-- * Forex dataset++parseFxDataset :: AP.Parser Text [TsPoint (FxRow Scientific)]+parseFxDataset = A.sepBy parseFxRow A.endOfLine++parseFxRow :: AP.Parser Text (TsPoint (FxRow Scientific))+parseFxRow = do+ (d, t) <- parseDateTime+ _ <- comma+ open <- A.scientific+ _ <- comma+ hi <- A.scientific+ _ <- comma+ lo <- A.scientific+ _ <- comma+ close <- A.scientific+ pure $ Tsp (Tick d t) (FxRow open hi lo close)++parseDateTime :: AP.Parser Text (Day, TimeOfDay)+parseDateTime = do+ d <- AT.dayInISO8601+ _ <- space+ t <- AT.timeOfDayInISO8601+ return (d, t)++
src/Graphics/Rendering/Plot/Light/Internal.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} module Graphics.Rendering.Plot.Light.Internal where - import Control.Arrow ((&&&), (***)) -- import Data.Foldable@@ -11,34 +10,16 @@ import Text.Blaze.Svg import Text.Blaze.Svg11 -- ((!), mkPath, rotate, translate, l, m) import qualified Text.Blaze.Svg11 as S-import qualified Text.Blaze.Svg11.Attributes as A+import qualified Text.Blaze.Svg11.Attributes as S import Text.Blaze.Svg.Renderer.String (renderSvg) import qualified Data.Colour as C import qualified Data.Colour.Names as C import qualified Data.Colour.SRGB as C ---data FigureData a d =- FigData {- _width :: a- , _height :: a- , _xmin :: a- , _xmax :: a- , _ymin :: a- , _ymax :: a- , _figData :: d- }----- | A LabeledPoint carries the information of where a point should be plotted, what label should it carry (e.g. for labelling the axes) and its function value -data LabeledPoint c l a =- LabeledPoint { _coord :: c, _label :: l, _value :: a }--data P1 a = P1 a-data P2 a = P2 a a+import GHC.Real +import Graphics.Rendering.Plot.Light.Internal.Types -- axis f1 figd = undefined@@ -49,38 +30,46 @@ -- m = minimum d --- | Given a point `x` in a range [x1min, x1max], map it by affine transformation onto the interval [x2min, x2max]-affine :: Fractional t => t -> t -> t -> t -> t -> t-affine x2min x2max x1min x1max x = (x - x1min)*d2/d1 + x2min where- d1 = x1max - x1min- d2 = x2max - x2min + -- | Header for a Figure figure :: FigureData Int d -> Svg -> Svg figure fd = S.docTypeSvg- ! A.version "1.1"- ! A.width (vi $ _width fd)- ! A.height (vi $ _height fd)- ! A.viewbox (vis [_xmin fd, _ymin fd, _xmax fd, _ymax fd])+ ! S.version "1.1"+ ! S.width (vi $ _width fd)+ ! S.height (vi $ _height fd)+ ! S.viewbox (vis [_xmin fd, _ymin fd, _xmax fd, _ymax fd]) -- | A filled rectangle, centered at (x0, y0) rectCentered :: Double -> Double -> Double -> Double -> C.Colour Double -> Svg-rectCentered x0 y0 wid hei col = S.g ! A.transform (translate x0c y0c) $ - S.rect ! A.width (vd wid) ! A.height (vd hei) ! A.fill (colourAttr col) where+rectCentered x0 y0 wid hei col = S.g ! S.transform (translate x0c y0c) $ + S.rect ! S.width (vd wid) ! S.height (vd hei) ! S.fill (colourAttr col) where x0c = x0 - (wid / 2) y0c = y0 - (hei / 2) -- centeredAt x0 y0 = S.g ! A.transform (translate x0 y0) +line x1 x2 y1 y2 = S.line ! S.x1 (vd x1) ! S.x2 (vd x2) ! S.y1 (vd y1) ! S.y2 (vd y2) --- * Helpers +-- * Helpers+++-- | Given a point `x` in a range [x1min, x1max], map it by affine transformation onto the interval [x2min, x2max]+affine :: Fractional t => t -> t -> t -> t -> t -> t+affine x2min x2max x1min x1max x = (x - x1min)*d2/d1 + x2min where+ d1 = x1max - x1min+ d2 = x2max - x2min++ ++ -- Render a Colour from `colour` into a `blaze` Attribute colourAttr :: C.Colour Double -> S.AttributeValue colourAttr = S.toValue . C.sRGB24show @@ -88,6 +77,7 @@ -- ** Conversion from primitive numerical types to AttributeValue vi :: Int -> S.AttributeValue vi = S.toValue+ -- | For use e.g. in `viewbox` vis :: [Int] -> S.AttributeValue
+ src/Graphics/Rendering/Plot/Light/Internal/Types.hs view
@@ -0,0 +1,20 @@+module Graphics.Rendering.Plot.Light.Internal.Types where+++data FigureData a d =+ FigData {+ _width :: a+ , _height :: a+ , _xmin :: a+ , _xmax :: a+ , _ymin :: a+ , _ymax :: a+ , _figData :: d+ }++-- | A LabeledPoint carries the information of where a point should be plotted, what label should it carry (e.g. for labelling the axes) and its function value +data LabeledPoint c l a =+ LabeledPoint { _coord :: c, _label :: l, _value :: a }++data P1 a = P1 a+data P2 a = P2 a a
src/Graphics/Rendering/Plot/Light/PlotTypes/TimeSeries.hs view
@@ -6,11 +6,11 @@ import qualified Data.Text as T import Graphics.Rendering.Plot.Light.Internal+import Graphics.Rendering.Plot.Light.Internal.Types+import Data.TimeSeries.Forex --- | An instant, defined by date (Day) and TimeOfDay-data Tick = Tick Day TimeOfDay- deriving (Eq, Show, Ord) + -- | Create a Tick from valid (year, month, day, hour, minute, second) mkTick :: Integer -> Int -> Int -> Int -> Int -> Pico -> Maybe Tick mkTick yy mm dd hr mi se = do@@ -23,12 +23,7 @@ fromTick :: Tick -> Rational fromTick (Tick d t) = fromIntegral (toModifiedJulianDay d) + timeOfDayToDayFraction t --- | A point in a time series-data TsPoint a =- Tsp {- _tick :: Tick,- _val :: a- } deriving (Eq, Show)+ -- | Transform the time coordinate of a timeseries point