<div dir="ltr">My main concern is that this proposal would change the role of <span style="font-family:monospace,monospace">Axes</span>.  Currently, it's primarily a container.  <div><br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">If I understand you correctly you don't like the idea of forcing
    Artists to use the transform.  <br></blockquote><div> </div><div>Actually, my key problem is having the <span style="font-family:monospace,monospace">Axes</span> responsible for going between "data" coordinates and "screen"/"display" coordinates.  Right now, the <span style="font-family:monospace,monospace">Axes</span> is not at all responsible for that.  If I'm understanding this proposal correctly, it would shift even more into <span style="font-family:monospace,monospace">Axes</span>.  <br><br></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><div>As far as I see it, all coordinates supplied to an Artist
    will come in the form of Axes coordinates, i.e. Axes space, and thus
    we need to transform those coordinates to screen coordinates...</div></blockquote><div><br>The problem here is that most <span style="font-family:monospace,monospace">Artists</span> don't work in data coordinates.  Only a very small number, such as those produced by user-focused plotting methods, are actually in data coordinates.  Most of the artists that belong to the <span style="font-family:monospace,monospace">Axes</span> actually don't have `<span style="font-family:monospace,monospace">ax.transData</span>` as their transform.  For example, consider the Axes patch, the ticks, tick labels, spines, titles and labels, etc.  Even artists produced by user-facing functions often aren't in "data" space. Consider `<span style="font-family:monospace,monospace">annotate</span>`, for example.<br></div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"> however on a spherical geometry, these "straight" lines
    do not conform to the Euclid definition of straight, we need to draw
    them curved.  Because of this the transform will need to come very
    late in the drawing process.</blockquote><div><br></div><div>For what it's worth, that's exactly the type of thing that I don't think it makes sense to have the <span style="font-family:monospace,monospace">Axes</span> responsible for.  Right now, <span style="font-family:monospace,monospace">Transform</span> handles this.  Specifically the `<span style="font-family:monospace,monospace">tranform_path_non_affine</span>` method. This allows these sort of transformations to happen at draw time.<br><br><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">I think the solution here comes from using a dual approach.  With
    the functions above I used the term base, as in the ``axes_to_base``
    and ``base_to_axes`` functions.  Here ``base`` defines the projected
    coordinates.  We can then leave it up to the user to decide whether
    to plot in axes coordinates or base coordinates.  We can start of
    leaving the axes side unimplemented, and perhaps we will never
    implement the axes side for some Axes classes... what do you think?<br></blockquote><div><br></div><div>For what it's worth, that's what we currently have, in my opinion.<br><br></div><div>Each artist has a Transform.  Its only role is to convert points and paths (to handle non-euclidian geometries) from whatever the data for the artist is in to display coordinates.  The Transform that the artist has defines what coordinates system that artist's data is in.<br><br></div><div>This makes it easy to do things like:<br><br><div style="margin-left:40px"><span style="font-family:monospace,monospace">import matplotlib.pyplot as plt<br><br>fig, ax = plt.subplots()<br><br>ax.text(0.1, 0.9, 'This will stay in-place', transform=ax.transAxes)<br><br>ax.plot(range(10), color='royalblue', lw=3)<br>ax.set(title='Be sure to pan and zoom')<br><br>plt.show()<br></span></div><br></div><div><br>Cartopy is another fantastic example.  Have a look at how Cartopy handles the difference between projected coordinates and geodetic coordinates: <a href="http://scitools.org.uk/cartopy/docs/latest/matplotlib/intro.html#adding-data-to-the-map">http://scitools.org.uk/cartopy/docs/latest/matplotlib/intro.html#adding-data-to-the-map</a>  Which transform you specify defines which coordinate system is being used for the data.<br><br></div><div>The key here is that the Axes isn't doing the transformation at all.  Making the Axes responsible for the transformation between "data" and "display" coordinates makes it much harder to implement things such as this.  There are a lot of artists that are logically a part of the Axes but aren't in the "data" coordinate system.<br><br></div><div>Hopefully that helps clarify my viewpoint, at any rate.<br></div><div>Cheers!<br></div><div>-Joe<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 5, 2015 at 3:10 PM, OceanWolf <span dir="ltr"><<a href="mailto:juichenieder-nabb@yahoo.co.uk" target="_blank">juichenieder-nabb@yahoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div text="#000000" bgcolor="#FFFFFF">
    <br>
    <br>
    <br>
    <br>
    Not too sure what you meant by ````.  <br><span>
    <br>
    <br>
    <br>
    <div>On 05/09/15 19:25, Joe Kington wrote:<br>
    </div>
    <blockquote type="cite">
      <div dir="ltr">
        <div><br>
          First off, I don't intend this to come across as overly
          critical!  I think this is a very good discussion to have.<br>
        </div>
        <div>Also, I tend to have a bad "knee-jerk" reaction to change
          and tend to come around over time, so keep that in mind too.
          :)<br>
        </div>
      </div>
    </blockquote></span>
    No worries, I experience the same, and yes I wanted to open this up
    for just this kind of interrogation, especially as we have a lot of
    axes related code, and I have only touched a fraction of it to date.<br>
    <br>
    To explain where I come from, I should say that I like to work
    bottom-up.  I find designing good code starts with asking probing
    questions about what you want to model, in this case we have an
    ``_AxesBase`` class and so by definition it should model an abstract
    Axes,  because of this in the "Detailed Description" of this MEP I
    begin by asking the question probing the definition of an Axes.  I
    believe that if we model the world intutitively as we see it,
    everything else will fall into place.  I find the most direct route
    in code usually contains lots of inflexibility, like building a road
    through the mountain, you might go the direct route, but it becomes
    very difficult to maintain and expand upon.  Hence the focus lies in
    the journey.<span><br>
    <br>
    <blockquote type="cite">
      <div dir="ltr">
        <div><br>
          However, while I agree that `Axes` is quite a beast, I'm not
          sure this proposal simplifies things.  From my perspective, it
          adds complexity. If I'm understanding correctly, this would
          effectively tie the Transform stack to the Axes, instead of
          having the Axes generate a Transform object that may or may
          not be used by the artists in the Axes.<br>
          <br>
        </div>
      </div>
    </blockquote></span>
    If I understand you correctly you don't like the idea of forcing
    Artists to use the transform.  I don't see this as a problem (at the
    moment).  As far as I see it, all coordinates supplied to an Artist
    will come in the form of Axes coordinates, i.e. Axes space, and thus
    we need to transform those coordinates to screen coordinates... at
    least at some point, probably when it comes to drawing... I
    especially think of drawing a triangle onto a spherical geometry,
    see <a href="https://en.wikipedia.org/wiki/Spherical_geometry" target="_blank">https://en.wikipedia.org/wiki/Spherical_geometry</a>.  We create a
    Polygon patch and supply the three vertices that define our
    Triangle... however on a spherical geometry, these "straight" lines
    do not conform to the Euclid definition of straight, we need to draw
    them curved.  Because of this the transform will need to come very
    late in the drawing process.<span><br>
    <blockquote type="cite">
      <div dir="ltr">
        <div>
          <blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">
            <p>First we define our coordinate transformation functions:
              axes_to_base(self, *q)
              base_to_axes(self, x, y)</p>
            <p>The term <code>base</code> could get replaced with <code>screen</code>
              but for now we will keep
              it simple to reflect another transformation from base
              coords to screen coords,
              e.g. perhaps to differentiate between window and screen
              coords.</p>
          </blockquote>
          <div><br>
          </div>
          <div>This is my main concern.  We have a (i.m.o.) very
            flexible and actually quite clean Transform system to handle
            this.  Why shift away from it? `ax.transData` may be
            non-PEP8 naming, but it's a good way to do this.  The
            concept of having Transform objects that handle this but are
            separate from the Axes gives a lot of flexibility.  In my
            opinion, the core concept of having this transformation
            handled by a Transform object that's separate from the Axes
            is one of the best things about matplotlib's design.  <br>
            <br>
          </div>
          <div>Or am I misunderstanding, and this is just a refactoring
            of `_get_core_transform` and `_get_affine_transform` into
            one method? <br>
          </div>
          <br>
        </div>
      </div>
    </blockquote></span>
    As far as I know, I want to keep the transform system.  I think I do
    just mean refactoring that into one method.  I say think as I still
    don't feel fully understand how it all works, the Transform system,
    brilliant, but very mind-boggling.  I had to delve into it to find a
    bug reported by a user on github, and went through around 50
    (perhaps more) Transform operations before I got to the problem.  If
    you need to debug part of it, like i had to, it becomes a tangled
    mess, luckily for most people they don't have to, and the usage
    works quite simply.  When I tracked down the bug I also spent quite
    some time trying to figure out the Transform classes, prior to the
    bug I only knew of Rotation, Shear and Reflection Transforms. 
    Anyway my point here comes that while great, it can become quite the
    head-ache for the average user developer, especially for those who
    know even less then I do about transforms, and so I want to blackbox
    the transforms in the Axes with simple names such as
    axes_to_***_coords(self, *q), and ***_to_axes_coords(self, x, y).<br>
    <br>
    So I want to make it easy for people to write their own axes with
    their own transform methods without having to worry about how the
    rest of the Artist code and plot methods work (unless it works
    really bizarrely); and I want people to work on Artist code, and
    creating their own tools and user interaction stuff without having
    to worry about learning about transforms (they just need to know
    that these two methods will do the conversion for them from data
    coordinates, which they understand, to the location on the screen or
    whatever, which they will also understand, start talking about
    AffineTransforms and I think we will scare people off).<span><br>
    <blockquote type="cite">
      <div dir="ltr">
        <div>---------------------<br>
        </div>
        <div><br>
          My other main concern centers on map projections. The MEP
          currently mentions:<br>
          <br>
        </div>
        <blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">an
          anticipated structure of a base mapping class with a
          coordinate system in
          lat/lon coordinates, but with different mapping projections
          available for the
          conversion between the Axes coordinate system and the screen.<br>
        </blockquote>
        <div><br>
        </div>
        <div>However, this is a bad approach for cartographic data.
          Geographic is not the base for a projected coordinate system.
          There are several reasons for that.<br>
          <br>
        </div>
        <div>1. Map data is usually _in the projected coordinate
          system_.  Lat, long data is actually not terribly common
          unless you're working with global datasets.  <br>
        </div>
        <div>2. Raster data (i.e. anything displayed with imshow) is
          typically going to be gridded on a regular grid in the
          projected coordinate system.  Forcing a transformation back to
          a non-uniform grid in lat, long space then back onto a
          different uniform grid than the original in display space is
          unnecessarily expensive.  <br>
          <br>
          One of the great things about Cartopy is that it leaves the
          fundamental Cartesian projected space unchanged, and let's you
          specify the transform if you want to use geographic
          coordinates.  Basemap handles it a bit differently but has the
          same core concept.  Latitudes and longitudes aren't the data
          coordinate system.  The projected coordinate system is.<br>
          <br>
          There's a reason for that approach.  Forcing people to convert
          their data into a geographic coordinate system before plotting
          it is a bad idea. It's good to have plotting methods that
          allow geographic coordinates, but bad to require that
          transformation.  (I'll skip the very important datum part for
          the moment.  Just be aware that a lat, long only gets you to
          within ~1km of a location without more information.)<br>
        </div>
      </div>
    </blockquote></span>
    Hmm, when I have used Basemap, the data files I work with I always
    get in lat/lon format.  One of my biggest annoyances with Basemap
    comes from having to work projection coordinates.  I move the mouse
    over the map and statusbar shows me useless projection coordinate
    information; I want to rotate the globe (in 'ortho' projection), but
    I can't, it becomes very difficult to use from a user interface
    point of view.<br>
    <br>
    I think the solution here comes from using a dual approach.  With
    the functions above I used the term base, as in the ``axes_to_base``
    and ``base_to_axes`` functions.  Here ``base`` defines the projected
    coordinates.  We can then leave it up to the user to decide whether
    to plot in axes coordinates or base coordinates.  We can start of
    leaving the axes side unimplemented, and perhaps we will never
    implement the axes side for some Axes classes... what do you think?<br>
    <br>
    Best,<br>
    OceanWolf<br>
  </div>

</blockquote></div><br></div></div></div>