plots icon indicating copy to clipboard operation
plots copied to clipboard

Heatmap Example just isn't building

Open MilesLitteral opened this issue 3 years ago • 5 comments

I made a test to use the heatmap example in:

import Plots
import Linear.V2 
import Control.Lens

main :: IO ()
main = do
    let xs = [[1,2,3],[4,5,6]]
    heatMap xs $ heatMapSize .= V2 10 10

But it fails and is unbuildable with the following errors:

    • No instance for (base-4.15.1.0:Data.Typeable.Internal.Typeable
                         a0)
        arising from a use of ‘heatMap’
    • In the first argument of ‘($)’, namely ‘heatMap xs’
      In a stmt of a 'do' block: heatMap xs $ (heatMapSize .= V2 10 10)
      In the expression:
        do let xs = ...
           heatMap xs $ (heatMapSize .= V2 10 10)
   |
19 |     heatMap xs $ (heatMapSize .= V2 10 10)


    • Ambiguous type variable ‘a0’ arising from the literal ‘10’
      prevents the constraint ‘(Num a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Num a => Num (Identity a)
          -- Defined in ‘Data.Functor.Identity’
        instance Num a => Num (V2 a) -- Defined in ‘Linear.V2’
        instance Num Integer -- Defined in ‘GHC.Num’
        ...plus four others
        ...plus 10 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘V2’, namely ‘10’
      In the second argument of ‘(.=)’, namely ‘V2 10 10’
      In the second argument of ‘($)’, namely ‘(heatMapSize .= V2 10 10)’
   |
19 |     heatMap xs $ (heatMapSize .= V2 10 10)
   |                                     ^^

I took out heatMapAxis because it keeps complaining that it's constraint (Axis B V2 Double) is unsolvable in terms of B and I don't understand how to remedy it not finding a backend. There doesn't seem to be a lens for it, or any reference to the backend being used but considering it's capitalized there has to be something?

Any advice is appreciated, Thanks

MilesLitteral avatar May 11 '22 18:05 MilesLitteral

I wanted to add on that writing the heatmap example like this also doesn't work

import Plots
import Linear.V2 
import Control.Lens

heatMapAxis :: Axis B V2 Double
heatMapAxis = r2Axis &~ do
  display colourBar
  axisExtend .= noExtend

  let xs = [[1,2,3],[4,5,6]]
  heatMap xs $ heatMapSize .= V2 10 10

instead it throws this error

    Not in scope: type constructor or class ‘B’
  |
5 | heatMapAxis :: Axis B V2 Double
  |                     ^

MilesLitteral avatar May 11 '22 19:05 MilesLitteral

You need to import a backend. Each backend exports a B type alias to make it easier to switch between backends. You can see some examples that hopefully still compile in https://github.com/cchalmers/plots/tree/master/examples. I don't have a heatMap example there but they should work the same. Those examples import Diagrams.Backend.Rasterific.CmdLine for the backend.

cchalmers avatar May 11 '22 20:05 cchalmers

Thanks! This updated version of the example code builds

{-# LANGUAGE FlexibleContexts #-}
module Main where 

import Plots
import Linear.V2 
import Control.Lens
import Control.Monad.IO.Class
import Diagrams.Backend.Rasterific.CmdLine

heatMapAxis :: Axis B V2 Double
heatMapAxis = r2Axis &~ do
  display colourBar
  axisExtend .= noExtend

  let xs = [[1,2,3],[4,5,6]]
  heatMap xs $ heatMapSize .= V2 10 10

main :: IO ()
main =  r2AxisMain $ heatMapAxis

when running the example GHC points out as follows: No output file given. Specify output file with -o

Is this the only way to force the output of the heatmap? Is there a way to SaveImage (like JuicyPixels)

Thank you very much your answered fixed the original problem and addressed my original question :)

MilesLitteral avatar May 11 '22 20:05 MilesLitteral

as a poor man's work around I discovered you can do this:

{-# LANGUAGE FlexibleContexts #-}

module Main where 

import Plots
import Linear.V2 
import Control.Lens
import Control.Monad.IO.Class

import Codec.Picture
import Diagrams.Backend.Rasterific.CmdLine

heatMapIndexedAxis :: Axis B V2 Double
heatMapIndexedAxis = r2Axis &~ do
  display colourBar
  axisExtend .= noExtend

  let f (V2 x y) = fromIntegral x + fromIntegral y
  heatMapIndexed (V2 3 3) f $ heatMapSize .= V2 10 10
  
main :: IO ()
main =  r2AxisMain $ heatMapIndexedAxis

Then run this in cmd: stack exec --<module> -o out.png

I'm sure a more standard solution will come up in time; thanks again for your help!

MilesLitteral avatar May 11 '22 21:05 MilesLitteral

Happy to help. Yes, rendering directly is possible. You can call renderAxis and then run renderRasterific on the resulting Diagram.

cchalmers avatar May 11 '22 22:05 cchalmers