timbod7 / haskell-chart

A 2D charting library for haskell
430 stars 85 forks source link

How to show LocalTime axis using diagrams backend? #93

Open peterljung opened 9 years ago

peterljung commented 9 years ago

I'm not able to figure out how convert example2 to use the diagrams backend.

https://github.com/timbod7/haskell-chart/wiki/example-2

I simply change the import:

--import Graphics.Rendering.Chart.Backend.Cairo
import Graphics.Rendering.Chart.Backend.Diagrams

And changed output to SVG

fileopts = fo_format .~ SVG
     $ fo_size .~ (800,600)
     $ def

-- main = renderableToFile def "example2_big.png" chart
main = renderableToFile fileopts "example2_big.svg" chart

I get the following in all my attempts:

No instance for (PlotValue LocalTime) arising from a use of ‘def’

I have successfully used renderableToSVGFile in a previous version of the library.

"How to use backends" doesn't seem to be up to date for 1.5 version.

timbod7 commented 9 years ago

This works:

import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Diagrams
import Data.Time.LocalTime

import Prices(prices,mkDate,filterPrices)

prices' :: [(LocalTime,Double,Double)]
prices' = filterPrices prices (mkDate 1 1 2005) (mkDate 31 12 2006)

fileopts = fo_format .~ SVG
     $ fo_size .~ (800,600)
     $ def

main = toFile fileopts "test.svg" $ do
    layoutlr_title .= "Price History"
    layoutlr_left_axis . laxis_override .= axisGridHide
    layoutlr_right_axis . laxis_override .= axisGridHide
    plotLeft (line "price 1" [ [ (d,v) | (d,v,_) <- prices'] ])
    plotRight (line "price 2" [ [ (d,v) | (d,_,v) <- prices'] ])

or if you prefer the non-monadic style:

import System.Environment(getArgs)
import Data.Colour.Names
import Data.Colour
import Control.Lens
import Data.Default.Class
import Data.Time.LocalTime
import Graphics.Rendering.Chart
import Graphics.Rendering.Chart.Backend.Diagrams

import Prices(prices,mkDate,filterPrices)

prices' :: [(LocalTime,Double,Double)]
prices' = filterPrices prices (mkDate 1 1 2005) (mkDate 31 12 2006)

chart = toRenderable layout 
  where

    price1 = plot_lines_style . line_color .~ opaque blue
           $ plot_lines_values .~ [ [ (d,v) | (d,v,_) <- prices'] ]
           $ plot_lines_title .~ "price 1"
           $ def

    price2 = plot_lines_style . line_color .~ opaque green
           $ plot_lines_values .~ [ [ (d,v) | (d,_,v) <- prices'] ]
           $ plot_lines_title .~ "price 2"
           $ def

    layout = layoutlr_title .~"Price History"
           $ layoutlr_left_axis . laxis_override .~ axisGridHide
           $ layoutlr_right_axis . laxis_override .~ axisGridHide
           $ layoutlr_x_axis . laxis_override .~ axisGridHide
           $ layoutlr_plots .~ [Left (toPlot price1),
                                Right (toPlot price2)]
           $ layoutlr_grid_last .~ False
           $ def

fileopts = fo_format .~ SVG
     $ fo_size .~ (800,600)
     $ def

main = renderableToFile fileopts "test-2.svg" chart

Note that the ordering on parameters to renderableToFile change last year with this commit: https://github.com/timbod7/haskell-chart/commit/545a8e1852179fa9a1514988e1be349863987d5a, which might be causing some confusion?

peterljung commented 9 years ago

Thanks for your reply!

But, I can't really see any difference from my code. And the same problem persist.

$ cat example2_fixed.hs 
import System.Environment(getArgs)
import Data.Colour.Names
import Data.Colour
import Control.Lens
import Data.Default.Class
import Data.Time.LocalTime
import Graphics.Rendering.Chart
import Graphics.Rendering.Chart.Backend.Diagrams

import Prices(prices,mkDate,filterPrices)

prices' :: [(LocalTime,Double,Double)]
prices' = filterPrices prices (mkDate 1 1 2005) (mkDate 31 12 2006)

chart = toRenderable layout 
  where

    price1 = plot_lines_style . line_color .~ opaque blue
           $ plot_lines_values .~ [[ (d,v) | (d,v,_) <- prices']]
           $ plot_lines_title .~ "price 1"
           $ def

    price2 = plot_lines_style . line_color .~ opaque green
           $ plot_lines_values .~ [[ (d,v) | (d,_,v) <- prices']]
           $ plot_lines_title .~ "price 2"
           $ def

    layout = layoutlr_title .~"Price History"
           $ layoutlr_left_axis . laxis_override .~ axisGridHide
           $ layoutlr_right_axis . laxis_override .~ axisGridHide
           $ layoutlr_x_axis . laxis_override .~ axisGridHide
           $ layoutlr_plots .~ [Left (toPlot price1),
                                Right (toPlot price2)]
           $ layoutlr_grid_last .~ False
           $ def

fileopts = fo_format .~ SVG
     $ fo_size .~ (800,600)
     $ def

main = renderableToFile fileopts "test-2.svg" chart

$ ghc example2_fixed.hs 
[2 of 2] Compiling Main             ( example2_fixed.hs, example2_fixed.o )

example2_fixed.hs:35:14:
    No instance for (PlotValue LocalTime) arising from a use of ‘def’
    In the second argument of ‘($)’, namely ‘def’
    In the second argument of ‘($)’, namely
      ‘layoutlr_grid_last .~ False $ def’
    In the second argument of ‘($)’, namely
      ‘layoutlr_plots .~ [Left (toPlot price1), Right (toPlot price2)]
       $ layoutlr_grid_last .~ False $ def’

I suppose it must be something in my environment that is different.

$ ghc-pkg list
/Library/Frameworks/GHC.framework/Versions/7.8.3-x86_64/usr/lib/ghc-7.8.3/package.conf.d
   Cabal-1.18.1.4
   GLURaw-1.4.0.1
   GLUT-2.5.1.1
   ...
   zlib-0.5.4.1
/Users/peter/.ghc/x86_64-darwin-7.8.3/package.conf.d
   Cabal-1.22.4.0
   Chart-1.5
   Chart-diagrams-1.5
   ...
   diagrams-core-1.3.0.2
   diagrams-lib-1.3.0.2
   diagrams-postscript-1.3.0.2
   diagrams-solve-0.1
   diagrams-svg-1.3.1.2
   time-1.5.0.1
   ...

I also checked dependencies in cabal file for Chart-diagrams.

$ cabal info Chart-diagrams
* Chart-diagrams   (library)
    Synopsis:      Diagrams backend for Charts.
    Versions available: 1.1, 1.2.3, 1.2.4, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.4,
                        1.5 (and 3 others)
    Versions installed: 1.5
    Homepage:      https://github.com/timbod7/haskell-chart/wiki
    Bug reports:   [ Not specified ]
    Description:   Diagrams backend for Charts.
    Category:      Graphics
    License:       BSD3
    Author:        Jan Bracker <jan.bracker@googlemail.com>
    Maintainer:    Jan Bracker <jan.bracker@googlemail.com>
    Source repo:   https://github.com/timbod7/haskell-chart
    Dependencies:  base >=3 && <5, old-locale -any, time -any, mtl -any,
                   diagrams-core ==1.3.*, diagrams-lib >=1.2 && <1.4,
                   diagrams-svg >=1.3.1 && <1.4,
                   diagrams-postscript >=0.7 && <1.4, SVGFonts >=1.4 && <1.6,
                   colour >=2.2.1 && <2.4, blaze-markup ==0.7.*,
                   lucid-svg ==0.4.*, bytestring >=0.9 && <1.0,
                   operational >=0.2.2 && <0.3, containers >=0.4 && <0.6,
                   data-default-class <0.1, lens >=3.9 && <4.12, Chart ==1.5.*,
                   text -any
    Documentation: /Users/peter/Library/Haskell/ghc-7.8.3-x86_64/lib/Chart-diagrams-1.5/doc/html
    Cached:        Yes
    Modules:
        Graphics.Rendering.Chart.Backend.Diagrams
eflister commented 9 years ago

i am also getting a missing PlotValue instance when using the Diagrams backend for this example, using either Easy or regular.

  No instance for (PlotValue y20) arising from a use of ‘toFile’
    The type variable ‘y20’ is ambiguous
    Note: there are several potential instances:
      instance PlotValue Double
        -- Defined in ‘Graphics.Rendering.Chart.Axis.Floating’
      instance PlotValue Float
        -- Defined in ‘Graphics.Rendering.Chart.Axis.Floating’
      instance PlotValue LogValue
        -- Defined in ‘Graphics.Rendering.Chart.Axis.Floating’
      ...plus five others

i'm on osx, ghc 7.8.3.

the example at the bottom of https://github.com/timbod7/haskell-chart/wiki/How-to-use-backends worked, after modifications - i had to use:

  renderableToFile (fo_size .~ (800,600) $ fo_format .~ SVG $ def) "example5.svg" chart

because there no longer seems to be a renderableToSVGFile

eflister commented 9 years ago

oop my bad -- seems to be because i thought i didn't need both a plotLeft and a plotRight and can't import both Easy and regular at the same time. works now.

timbod7 commented 9 years ago

Sorry you had the problem. I've updated this documentation:

https://github.com/timbod7/haskell-chart/wiki/How-to-use-backends

warreee commented 9 years ago

@peterljung did you find a solution yet?

timbod7 commented 9 years ago

I'm interested too - Is this still a problem?

peterljung commented 9 years ago

No, I haven't been able to get this working ...

The example that Tim suggested above doesn't work for me. If I don't use DateTime on x-axis it does work (using v on both axis).

price1 = plot_lines_style . line_color .~ opaque blue
       $ plot_lines_values .~ [[ (v,v) | (d,v,_) <- prices']]
       $ plot_lines_title .~ "price 1"
       $ def

price2 = plot_lines_style . line_color .~ opaque green
       $ plot_lines_values .~ [[ (v,v) | (d,_,v) <- prices']]
       $ plot_lines_title .~ "price 2"
       $ def

The diagrams example in "How to use backends" works fine.

timbod7 commented 9 years ago

Hmm. Do you still see the same problem if you import Graphics.Rendering.Chart.Axis.LocalTime explicitly?

On Tue, Aug 25, 2015 at 5:17 AM, peterljung notifications@github.com wrote:

No, I haven't been able to get this working ...

The example that Tim suggested above doesn't work for me. If I don't use DateTime on x-axis it does work (using v on both axis).

price1 = plot_lines_style . line_color .~ opaque blue $ plot_linesvalues .~ [[ (v,v) | (d,v,) <- prices']] $ plot_lines_title .~ "price 1" $ def

price2 = plot_lines_style . line_color .~ opaque green $ plot_linesvalues .~ [[ (v,v) | (d,,v) <- prices']] $ plot_lines_title .~ "price 2" $ def

The diagrams example in "How to use backends" works fine.

— Reply to this email directly or view it on GitHub https://github.com/timbod7/haskell-chart/issues/93#issuecomment-134345479 .

warreee commented 9 years ago

Hey Timbod, I got the same problem, and yes I have the same problem when import Graphics.Rendering.Chart.Axis.LocalTime explicitly: No instance for (PlotValue LocalTime) arising from a use of `toFile'

peterljung commented 9 years ago

Yes, same here.

I get a slightly different error message though.

ghc example2_fixed.hs [2 of 2] Compiling Main ( example2_fixed.hs, example2_fixed.o )

$ ghc example2_fixed.hs
[2 of 2] Compiling Main             ( example2_fixed.hs, example2_fixed.o )

example2_fixed.hs:36:14:
    No instance for (PlotValue LocalTime) arising from a use of ‘def’
    In the second argument of ‘($)’, namely ‘def’
    In the second argument of ‘($)’, namely
      ‘layoutlr_grid_last .~ False $ def’
    In the second argument of ‘($)’, namely
      ‘layoutlr_plots .~ [Left (toPlot price1), Right (toPlot price2)]
       $ layoutlr_grid_last .~ False $ def’

From the following code

import System.Environment(getArgs)
import Data.Colour.Names
import Data.Colour
import Control.Lens
import Data.Default.Class
import Data.Time.LocalTime
import Graphics.Rendering.Chart
import Graphics.Rendering.Chart.Backend.Diagrams
import Graphics.Rendering.Chart.Axis.LocalTime

import Prices(prices,mkDate,filterPrices)

prices' :: [(LocalTime,Double,Double)]
prices' = filterPrices prices (mkDate 1 1 2005) (mkDate 31 12 2006)

chart = toRenderable layout 
  where

    price1 = plot_lines_style . line_color .~ opaque blue
           $ plot_lines_values .~ [[ (d,v) | (d,v,_) <- prices']]
           $ plot_lines_title .~ "price 1"
           $ def

    price2 = plot_lines_style . line_color .~ opaque green
           $ plot_lines_values .~ [[ (d,v) | (d,_,v) <- prices']]
           $ plot_lines_title .~ "price 2"
           $ def

    layout = layoutlr_title .~"Price History"
           $ layoutlr_left_axis . laxis_override .~ axisGridHide
           $ layoutlr_right_axis . laxis_override .~ axisGridHide
           $ layoutlr_x_axis . laxis_override .~ axisGridHide
           $ layoutlr_plots .~ [Left (toPlot price1),
                                Right (toPlot price2)]
           $ layoutlr_grid_last .~ False
           $ def

fileopts = fo_format .~ SVG
         $ fo_size .~ (800,600)
         $ def

main = renderableToFile fileopts "test-2.svg" chart
timbod7 commented 9 years ago

I'm at a bit of a loss here. I don't see why this instance for Double can be found ok:

https://github.com/timbod7/haskell-chart/blob/master/chart/Graphics/Rendering/Chart/Axis/Floating.hs#L44

whereas this corresponding instance for LocalTime is not found for you:

https://github.com/timbod7/haskell-chart/blob/master/chart/Graphics/Rendering/Chart/Axis/Floating.hs#L44

I'm clutching at straws, but is it possible that somehow you have a different version of the time package visible when compiling the example, compared with when the library was build?

peterljung commented 9 years ago

I made a clean install of Haskell Platform, cabal and chart-diagrams on OSX Yosemite (0.10.4) and now the example works as expected.

$ ghc example2_fixed.hs
[1 of 2] Compiling Prices           ( Prices.hs, Prices.o )
[2 of 2] Compiling Main             ( example2_fixed.hs, example2_fixed.o )
Linking example2_fixed ...

$ ghc -v
Glasgow Haskell Compiler, Version 7.10.2, stage 2 booted by GHC version 7.10.1.20150612
...

$ ghc-pkg list
/Library/Frameworks/GHC.framework/Versions/7.10.2-x86_64/usr/lib/ghc-7.10.2/package.conf.d
   Cabal-1.22.4.0
   GLURaw-1.5.0.1
   GLUT-2.7.0.1
   ghc-7.10.2
   ghc-prim-0.4.0.0
   ...
   time-1.5.0.1
   ...
/Users/peter/.ghc/x86_64-darwin-7.10.2/package.conf.d
   Chart-1.5.3
   Chart-diagrams-1.5.1
    ...

Unfortunate that I wasn't able to figure out this dependency problem on my own. Is there a good way to ensure exact dependencies in a build like this? A cabal config with restrictive dependencies?

Anyway, thank a lot for trying to help out!

timbod7 commented 9 years ago

It's good that you've got it working. The error you are seeing is quite surprising.

warreee commented 9 years ago

I'm also thinking about a clean install to see if this would solve my problem too. I will keep you informed.