Repository: bokeh/bokeh

Issue:
Easily control aspect ratio
Includes being able to set aspect (e.g. if you want `1:1` aspect) and also have resize and zoom tools, etc. respect the existing aspect ratio. 



Discussion:
Useful reference implementation in https://github.com/enthought/chaco/blob/master/chaco/grid_mapper.py#L61 and https://github.com/enthought/chaco/blob/master/chaco/grid_mapper.py#L150

User request for `equal_axes` on SO: http://stackoverflow.com/questions/26674779/bokeh-plot-with-equal-axes

Interesting idea: https://github.com/bokeh/bokeh/issues/2522#issue-93385094

I feel this limitation should gain more attention, at least for the aspect_ratio=1 case.
Now in bokeh there is no way to display a full image in its original aspect ratio.
If x_range and y_range is not set, only part of the image will be shown. If they are set, the image will be resized to the full figure size and will be distorted. 

Hi @cwhy I agree this is a very important issue, but importance is unfortunately not the only issue to consider. There is also the unavoidable matter of limited (human) resources, as well as the entire context of other competing (important) priorities, as well as any blockers that affect the order of work. In this case this feature has long been blocked by the need to re-vamp the low level layout system entirely first. To do otherwise would be to commit resources to "bolt on" a quick fix that would only get thrown away. With a very limited amount of time/work between the current team, that is just not justifiable. 

However, the large layout work has been completed (or largely completed), so this implementation  feature can finally _begin_ to be discussed in detail. Unfortunately we are also passed the point where we can "experiment" with APIs. Since this feature will require new APIs we have to be _certain_ that its the right one, so there is a higher planning, testing, documentation burned at this stage of the project. Would you care to start the discussion? If you can describe how you might like to be able to "spell" this in Bokeh, that would be helpful. 

Hi @bryevdv, I feel that a similar one as matplotlib is quite sufficient.(http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.set_aspect)
As for Bokeh, it would be something like 
f = bokeh.plotting.figure(aspect_ratio=1)
or 
f = bokeh.plotting.figure()
f.aspect_ratio=1

For the box-zoom function, if the aspect ratio is fixed, the box can be forced to the same ratio as well. Alternatively, just allow box-zoom to break the ratio.

Really appreciate the work on Bokeh from your guys~

I can't offer an elegant solution to this problem, but I've got something that almost works well enough for me. The problem I'm running into is that `fig.plot_width` and `fig.plot_height` include axes, titles, etc, but I'd like to control the width and height of just the plot area. Any advice?

This is a big deal in geo contexts as mentioned in [#2522](https://github.com/bokeh/bokeh/issues/2522#issue-93385094). The aspect ratio is respected by the wheel zoom and pan tool right? So probably the easiest solution is just to turn off the box-zoom tool, so that the user doesn't have access to tools that allow distortion.

> The aspect ratio is respected by the wheel zoom and pan tool right?

Just to be super clear. The answer to this question is "not always".
1) If you are hovered over an axis and do a wheel zoom, it will wheel zoom for that axis only stretching the plot out (@bryevdv I wonder whether we should remove that feature in favor of something more explicit)
2) It used to be that if you panned and had range bounds then the plot could get stretched out - but I may have fixed that.

I'd like to add my support to this issue. As a materials scientist, I've started using bokeh to plot spatially-resolved structural data and I love the interactivity. Unfortunately the aspect ratio of nature is fixed, at least at sub-relativistic velocities.
@StevenCHowell FYI I have scheduled this for `0.12.7` I think all the necessary groundwork around layout is finally in place
I agree aspect ratio manipulation is an important feature to have, but I have found the wheelzoom axis only stretching feature very convenient. @birdsarah I vote to keep it around.  
The wheel zoom is very useful, but it should be made more configurable (i.e. off-able if you don't want it)

Resolving patch:
diff --git a/bokeh/models/plots.py b/bokeh/models/plots.py
--- a/bokeh/models/plots.py
+++ b/bokeh/models/plots.py
@@ -4,7 +4,7 @@
 from __future__ import absolute_import
 
 from ..core.enums import Location, OutputBackend
-from ..core.properties import Bool, Dict, Enum, Include, Instance, Int, List, Override, String
+from ..core.properties import Bool, Dict, Enum, Include, Instance, Int, List, Override, String, Float
 from ..core.property_mixins import LineProps, FillProps
 from ..core.query import find
 from ..core.validation import error, warning
@@ -692,3 +692,35 @@ def webgl(self, webgl):
         When set to ``webgl``, glyphs without a WebGL rendering implementation
         will fall back to rendering onto 2D canvas.
     """)
+
+    match_aspect = Bool(default=False, help="""
+    Specify the aspect ratio behavior of the plot. Aspect ratio is defined as
+    the ratio of width over height. This property controls whether Bokeh should
+    attempt the match the (width/height) of *data space* to the (width/height)
+    in pixels of *screen space*.
+
+    Default is ``False`` which indicates that the *data* aspect ratio and the
+    *screen* aspect ratio vary independently. ``True`` indicates that the plot
+    aspect ratio of the axes will match the aspect ratio of the pixel extent
+    the axes. The end result is that a 1x1 area in data space is a square in
+    pixels, and conversely that a 1x1 pixel is a square in data units.
+
+    .. note::
+        This setting only takes effect when there are two dataranges. This
+        setting only sets the initial plot draw and subsequent resets. It is
+        possible for tools (single axis zoom, unconstrained box zoom) to
+        change the aspect ratio.
+    """)
+
+    aspect_scale = Float(default=1, help="""
+    A value to be given for increased aspect ratio control. This value is added
+    multiplicatively to the calculated value required for ``match_aspect``.
+    ``aspect_scale`` is defined as the ratio of width over height of the figure.
+
+    For example, a plot with ``aspect_scale`` value of 2 will result in a
+    square in *data units* to be drawn on the screen as a rectangle with a
+    pixel width twice as long as its pixel height.
+
+    .. note::
+        This setting only takes effect if ``match_aspect`` is set to ``True``.
+    """)


Test patch: