3

I'm trying to use Haskell-Charts (http://hackage.haskell.org/package/Chart) to generate some graphs. It works fine and I get a nice graph enter image description here

My only "problem" are the numbers on the left, that's a bit hard to read. Is there a way to maybe provide a function that would convert those numbers before displaying them ? I could convert the numbers before plotting, but I would lose precision. I've been looking at the doc but I don't see it, if it exists.

Thanks

EDIT : Here is the code.

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

main = do
  -- Get datas
  toFile def "test.svg" $ do
    layout_title .= "Active mem"
    plot (line "Active" $ [L.map (\v -> ((utcToLocalTime utc $ time v) :: LocalTime, (fromIntegral $ value v) :: Int)) $ V.toList q])

Unfortunately I get the data from a database, and I can't give public access to it. But a list of [(LocalTime, Int)] with big numbers should give you something similar. I'm using the Diagrams backend btw

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
Ulrar
  • 895
  • 8
  • 17
  • Could you provide your code so we can tinker with it? – Cirquit Sep 21 '17 at 07:42
  • I added what I can, but it's missing the datas. You can probably use something like [[(some LocalTime, "2000000000"), (some LocalTime + 10s, "2000005000")]] or something and get a similar result. – Ulrar Sep 21 '17 at 07:54
  • I'm sure this is possible to do. But – without disrecommending it – I've always found `chart` to be a bit clumsly in regard to _simply plotting some stuff without issues like those badly-formatted numbers_. I'd like to advertise [dynamic-plot](http://hackage.haskell.org/package/dynamic-plot-0.2.2.0/docs/Graphics-Dynamic-Plot-R2.html), which does this kind of thing automatically. (But is nowhere near as feature-rich in terms of labels etc..) – leftaroundabout Sep 21 '17 at 08:29
  • I didn't know it existed, but as far as I understand it that's a graphical window type thing, right ? The goal for me there is to make an API with snap to graph datas from a database on the fly, I loved the toFile function of charts because it makes that very easy to accomplish, if I could just figure out how to adjust the graph. But I'll read up on dynamic, the screenshots do look pretty good – Ulrar Sep 21 '17 at 08:38
  • Well, since `dynamic-plot` actually renders everything through `diagrams`, it would in principle be easy to output to a file instead of GTK window. In fact I've meant to implement this for a long time, but always postponed it... should definitely put it in the next release. – leftaroundabout Sep 21 '17 at 09:00
  • Well to a file, a string or something, but yeah an option to skip the GTK dependecy would be great, to run that on headless servers. – Ulrar Sep 21 '17 at 09:03

1 Answers1

5

Digging into the source of the Chart, maybe I found the solution.

Here's working code. you can change func to anything you like

This will show label of y-axis 10,20,30,40, when actual data is 100,200,300,400

import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Diagrams

func :: Int -> String
func x = show $ x `quot` 10

vals :: [(Int,Int)]
vals = [(1,100),(2,200),(3,300),(4,400)]
main = do
  toFile def "test.svg" $ do
    layout_title .= "test"
    layout_y_axis . laxis_generate .= autoScaledIntAxis(LinearAxisParams{
        _la_labelf = map func,
        _la_nLabels = 5,
        _la_nTicks = 10
        })
    plot $ points "Score" vals
ymonad
  • 11,710
  • 1
  • 38
  • 49
  • That's pretty good, thanks ! I went with that for func : (\y -> TL.unpack $ FO.format (FO.prec 3 FO.% " GB") $ (fromIntegral y) / 1073741824.0). It gives some pretty good result, I might have to fiddle with the precision depending on the results but that's allright – Ulrar Sep 21 '17 at 10:46