TomP
TomP

Reputation: 108

Set Size of Plot in IHaskell (Jupyter) with Chart Package

I am able to do a simple 2D plot inside a Jupyter Notebook (with IHaskell) using the Haskell Chart Package. The code is here,

import Graphics.Rendering.Chart.Easy
cData = [1,2,3,4,3,2,1]
toRenderable  $ do
    layout_title .= "Recovered Signal"
    layout_x_axis . laxis_title .= "Time (msecs)"
    layout_y_axis . laxis_title .= "Original Input Level"
    plot (line "Amplitude" [zip [0,1..] cData])

The plot is automatically displayed in a Jupyter cell when the code cell returns a 'Renderable'

I would like to make the plot smaller.

I've tried,

I'm a mid-level Haskeller but never learned lenses which may be part of my problem. Maybe it's time to learn ..

Any help appreciated!

Tom

Upvotes: 0

Views: 101

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120751

Lenses won't help you much... the problem is that IHaskell.Display.Charts hard-codes width and height. It's a bit silly...

What you could do is write your own wrapper type for custom-sized charts, and copy the instances with the specified sizes.

import           System.Directory
import           Data.Default.Class
import           Graphics.Rendering.Chart.Renderable
import           Graphics.Rendering.Chart.Backend.Cairo
import qualified Data.ByteString.Char8 as Char
import           System.IO.Unsafe

import           IHaskell.Display

data SizedRenderable a = Sized
  { size :: (Width, Height)
  , theChart :: Renderable a
  }

instance IHaskellDisplay (SizedRenderable a) where
  display renderable = do
    pngDisp <- chartData renderable PNG

    -- We can add `svg svgDisplay` to the output of `display`, but SVGs are not resizable in the IPython
    -- notebook.
    svgDisp <- chartData renderable SVG

    return $ Display [pngDisp, svgDisp]

chartData :: Renderable a -> FileFormat -> IO DisplayData
chartData (Sized size@(w,h) renderable) format = do
  switchToTmpDir

  -- Write the PNG image.
  let filename = ".ihaskell-chart.png"
      opts = def { _fo_format = format, _fo_size = size }
  mkFile opts filename renderable

  -- Convert to base64.
  imgData <- Char.readFile filename
  return $
    case format of
      PNG -> png w h $ base64 imgData
      SVG -> svg $ Char.unpack imgData


-- TODO add signature, I can't be bothered to look it up
mkFile opts filename renderable = renderableToFile opts filename renderable

Upvotes: 1

Related Questions