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

Always add some padding to axis range

Open Shimuuar opened this issue 8 years ago • 10 comments

Otherwise it's possible that horizontal/vertical line coincides with axis and becomes invisible. Example:

toRenderable
  $ layout_plots .~
    [toPlot $ plot_lines_values .~ [[(0,1),(0,0),(1,0),(3,3)]] $ def]
  $ def

download

Shimuuar avatar May 24 '16 13:05 Shimuuar

I've been bitten by this one too

ghorn avatar Jun 03 '16 02:06 ghorn

Any suggestions as to what the default behaviour could be to avoid this?

ie how much padding would be added?

presumably you'd want it on the y axis as well?

timbod7 avatar Jun 03 '16 04:06 timbod7

In my experience 3% padding at both low and hi end of range gives decent results. Some plots however look better without padding. I don't remember details, but can look them up

Also current algorithm for range selection always set ticks on the borders which could result in some awkwardly placed plots:

download

I had even worse placement but don't have them at hand nor can reproduce them. IMHO padding as fraction of range gives much better looking plots.

And yes I want padding on X too.

Shimuuar avatar Jun 03 '16 15:06 Shimuuar

It has always been intended that the axes start and end on marked values. As per your examples I can see that this can have unintended consequences, but assumed that the ability to override the axis ranges would be enough.

Are you suggesting we should have another mode, or discard the existing behaviour in favour of fixed % padding? Can you point to examples output of other charting software that works this way?

timbod7 avatar Jun 04 '16 00:06 timbod7

I think fixed padding is most aesthetically pleasing option. Now few examples:

Matplotlib suffers from exactly same problem as Chart: download 1

R adds fixed padding and doesn't put ticks at axis limits rplot001

There's also ROOT but its defaults are atrocious.

And how one could set axis range? I couldn't find any easy way to force axis range to say 0.9-3.1

Shimuuar avatar Jun 04 '16 08:06 Shimuuar

And how one could set axis range? I couldn't find any easy way to force axis range to say 0.9-3.1

scaledAxis takes a range as an argument

ghorn avatar Jun 04 '16 08:06 ghorn

It seems it's not possible (or at least very difficult) to set axis range exactly (-0.2,3.2) for example. scaledAxis still requires integer number of ticks.

Shimuuar avatar Jun 27 '16 15:06 Shimuuar

I also have the same issue as @Shimuuar with setting the axis range values as exactly. This is particularly annoying when the units are in radians (0,2π) for example.

jcmartin avatar Jun 30 '16 06:06 jcmartin

You can take complete control of the axis, explicitly specifying the viewport and markings. eg a custom y axis:

import Control.Lens
import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Cairo


values :: [[(Double,Double)]]
values = [[(0,1),(0,0),(1,0),(3,3)]]

miny,maxy :: Double
(miny,maxy) = (-0.2,3.2)

labels :: [Double]
labels = [0,1,2,3]

main :: IO ()
main = toFile def "example.png" $ do
    plot (line "values" values)
    layout_y_axis . laxis_generate .= const AxisData {
         _axis_visibility = def,
         _axis_viewport = vmap (miny,maxy),
         _axis_tropweiv = invmap (miny,maxy),
         _axis_ticks    = [],
         _axis_grid     = labels,
         _axis_labels   = [[(l, show l) | l <- labels]]
    }

example

timbod7 avatar Jun 30 '16 23:06 timbod7

I'm still open to the idea of adding padding by default.

timbod7 avatar Jun 30 '16 23:06 timbod7