haskell-chart icon indicating copy to clipboard operation
haskell-chart copied to clipboard

Different height of charts in grid

Open pshemass opened this issue 7 years ago • 7 comments

mychrt

I'm trying to build stock chart with price and volume. I'm able to create both charts and put them in the grid however I have a problem with set proportion between them 2:1.

i tried to use weights but I cannot get rid of space between charts. Could you please help me with that?

pshemass avatar Oct 27 '18 05:10 pshemass

You haven't shown any code? @pshemass

chrissound avatar Oct 27 '18 09:10 chrissound

You are right :) Here is the code

price ts = layoutToGrid $ layout
  where
    layout = layout_background .~ solidFillStyle (opaque white)
           $ layout_left_axis_visibility . axis_show_ticks .~ False
           $ layout_legend .~ Nothing
           $ layout_margin .~ 0
           $ layout_plots .~ [ toPlot candleStock ]
          -- $ setLayoutLRForeground (opaque black)
           $ def:: Layout UTCTime Double
    candleStock = plot_candle_line_style .~ (lineStyle 1 blue)
                $ plot_candle_fill .~ True
                $ plot_candle_rise_fill_style .~ solidFillStyle (opaque yellow)
                $ plot_candle_fall_fill_style .~ solidFillStyle (opaque blue)
                $ plot_candle_tick_length .~ 0
                $ plot_candle_width .~ 5
                $ plot_candle_values .~ [ Candle d lo op 0 cl hi | (d,(lo,op,cl,hi)) <- ts]
                $ def

volume ts = layoutToGrid $ layout
  where
    layout = layout_plots .~ [ (plotBars bars) ]
           $ layout_legend .~ Nothing
           $ layout_margin .~ 0
           $ def :: Layout UTCTime Double
    bars = plot_bars_titles .~ ["volume"]
         $ plot_bars_values .~  [(d, [op]) | (d,(lo,op,cl,hi)) <- ts]
         $ def

grid ts =  (G.above  (price ts)  (G.weights (0, 0.1) (volume ts)))

void $ renderableToFile def{_fo_format = PNG, _fo_size = (1440, 768)} "mychrt.PNG" $ fillBackground def $ G.gridToRenderable $  grid r

pshemass avatar Oct 27 '18 14:10 pshemass

The extra space is being allocated to display titles or legends or something like that. You could see this be setting titles on the charts.

But I don't think you want to use grid to combine related charts vertically. It gives no guarantees that the elements of the charts (eg the vertical axes) will be lined up. For this you should use StackedLayout, as per this test:

https://github.com/timbod7/haskell-chart/blob/master/chart-tests/tests/Tests.hs#L223

timbod7 avatar Oct 28 '18 21:10 timbod7

@timbod7 yeah I figured that the space is for title and legend. I tried to use StackedLayout but I don't see any option to change proportion between charts. I would like to make upper chart twice as height as lower one. Do you have any idea how to do that?

pshemass avatar Oct 30 '18 02:10 pshemass

hi @timbod7 any update on that?

if this functionality is missing I could add that if you guide me a little bit.

pshemass avatar Nov 14 '18 05:11 pshemass

One thing you could try to eliminate the gaps would be to expose layoutPlotAreaToGrid and then call that instead of layoutToGrid. This will leave out the grid cells for the legends and titles.

timbod7 avatar Nov 17 '18 01:11 timbod7

sorry for slow response.

I made the change you mentioned and then code below produce what I want:

splitGrid :: Grid (Renderable a) -> Grid (Renderable a) -> Grid(Renderable a)
splitGrid top bottom = aboveN [
    besideN [
        aboveN $ replicate 2 $ tval $ spacer (0, 300),
        tspan ( gridToRenderable top ) (width bottom, 2)
     ],
     bottom
  ]

but I would like to somehow avoid using this magic number (300) and make this just 2 * (height bottom) but when I try to use spacer1 $ gridToRederable bottom instead of spacer (0,300) i'm getting something like below:

mychrt_grid

is there other way to make that works?

pshemass avatar Dec 20 '18 05:12 pshemass