Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

DOC: add tutorial explaining imshow *origin* and *extent*#10947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jklymak merged 4 commits intomatplotlib:masterfromtacaswell:doc_imshow_extent
May 2, 2018

Conversation

tacaswell
Copy link
Member

PR Summary

Sort out howorigin and 'extent interact.

attn@efiring

PR Checklist

@tacaswelltacaswell added this to thev2.2-doc milestoneApr 3, 2018
Copy link
Member

@dstansbydstansby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

A couple of suggestions for improvement.

from matplotlib.gridspec import GridSpec


def generate_imshow_demo_grid(auto_limits, extents):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Might be worth having these as keyword arguments? When I read the tutorial I scrolled past this big block of code, and then was confused as to whatgenerate_imshow_demo_grid(True...) did, but I thinkgenerate_imshow_demo_grid(auto_limits=True...) would be much better.

# ``np.arange(42).reshape(6, 7)`` with varying parameters.
#

generate_imshow_demo_grid(True, extents[:1])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

There isn't a massive change in these images from L --> R, but a clear different from top to bottom. Maybe a good place to use a colourmap that isn't perceptually uniform to illustrate changes in orientation?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

At least when I look a these what I see is the direction of highest-lowest vector, changed to a diagonal gradient.

@ImportanceOfBeingErnest
Copy link
Member

Geat tutorial! I did suggest to have such example around in#10982 without seeing this one being created.

I used triangular shaped data to explain a point I wanted to make in that PR, something like

image

This would make it easier to grasp at which corner the data is shown compared to the original array. Would this be an option here?


d =np.arange(42).reshape(6, 7)
x, y = np.ogrid[0:6, 0:7]
d =x + y

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

👍 yes, that's what I meant!

# ``(left, bottom)`` corner of the bounding box and moving closer to
# ``(left, top)`` moves along the ``[:, 0]`` axis of the array to
# higher indexed rows and moving towards ``(right, bottom)`` moves you
# along the ``[0, :]`` axis of the array to higher indexed columns
Copy link
Member

@timhoffmtimhoffmApr 16, 2018
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Possibly better as a bullet list or table than plain text:

Generally, for an array of shape (M,N), the first index runs along the vertical, the second index runs along the horizontal.origin determines how to the data is filled in the bounding box.

Fororigin='lower':

  • [0, 0] is at(left, bottom)
  • [M, 0] is at(left, top)
  • [0, N] is at(right, bottom)
  • [M, N] is at(right, top)

origin='upper' reverses the vertical filling:

  • [0, 0] is at(left, top)
  • [M, 0] is at(left, bottom)
  • [0, N] is at(right, top)
  • [M, N] is at(right, bottom)

# is ``(-0.5, numcols-0.5, numrows-0.5, -0.5)`` when ``origin ==
# 'upper'`` and ``(-0.5, numcols-0.5, -0.5, numrows-0.5)`` when ``origin
# == 'lower'`` which puts the pixel centers on integer positions and the
# ``[0, 0]`` pixel at ``(0, 0)`` in dataspace.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think it's simpler to understand if this was a table with colums 'origin == upper', 'origin == lower' and rows

  • [0, 0] pixel position
  • default extent
  • maybe more.

'xy': (1, .5)}
if extent is None:
ax.annotate('None', **text_kwargs)
ax.set_title('`extent=`')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Backticks don't work here. We can just leave them out.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

man, talk about muscle memory....

from matplotlib.gridspec import GridSpec


def generate_imshow_demo_grid(extents, auto_limits):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I find it more natural with a reversed logic that usesexplicit_limits=False instead ofauto_limits, or alternatively,xlims=None, ylims=None.


###############################################################################
#
# If we fix the axes limits so ``(0, 0)`` is at the bottom left and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

If we fix the axes limits by explicity settingset_xlim /set_ylim, we force a certain orientation of the axes. This can decouple the 'left-right' and 'top-bottom' sense of the image from the orientation on the screen.

In the example below (0, 0) is explicitly put at the bottom left and values increase to up and to the right (from the viewer point of view). We can see that:

@timhoffm
Copy link
Member

timhoffm commentedApr 16, 2018
edited
Loading

Also it helps to display the indices in the plots:

grafik

def index_to_coordinate(index, extent, origin):    left, right, bottom, top = extent    # convert from extent to corner pixel centers        hshift = 0.5 if left < right else -0.5    left, right = left + hshift, right - hshift    vshift = 0.5 if bottom < top else -0.5    bottom, top = bottom + vshift, top - vshift        # handle vertical fill order    if origin == 'upper':        bottom, top = top, bottom        return {        '0, 0': (left, bottom),        'M, 0': (left, top),        '0, N': (right, bottom),        'M, N': (right, top),    }[index]

and in the inner for loop:

            for index in ['0, 0', '0, N', 'M, 0', 'M, N']:                ax.text(*index_to_coordinate(index, extent, origin),                        index, color='white', ha='center', va='center')
anntzer reacted with thumbs up emoji

@ImportanceOfBeingErnest
Copy link
Member

ImportanceOfBeingErnest commentedApr 16, 2018
edited
Loading

Just mind the notation. In the imshow docs (#10982), arrays are of shape(N,M).This is consistent with widely used conventions. So if updating the coordinates as proposed above, it would make sense to use this convention as well, and not suddenly chage it to(M,N). Independently something seems to be wrong in the above suggestion.

  • For a tuplea,b one needs to decide if this is a cartesian point(x,y) or an array index[i,j]
  • In either case, the last coordinate or index should beN-1 andM-1 respectively.

@timhoffm
Copy link
Member

@ImportanceOfBeingErnest Agreed on all points.

  • Should use (N,M).
  • The exact notation would be[N-1, M-1], but there is no way of fitting that in square pixels while maintaining a reasonably small figure size. I could discuss away the square brackets with a sentence: "Values in pixels describe their indices". No good idea how to cope with the-1 issue. One could define them one-smaller by "array of shape (N+1,M+1)". That would be consistent within the example, but other than the original docstring notation (N, M).

@timhoffm
Copy link
Member

timhoffm commentedApr 18, 2018
edited
Loading

Probably the best solution is using boxes for the indices as well:

grafik

whereN' = N-1 andM' = M-1

and code:

def get_color(index, data, cmap):    val = {        "[0, 0]": data[0, 0],        "[0, M']": data[0, -1],        "[N', 0]": data[-1, 0],        "[N', M']": data[-1, -1],    }[index]    return cmap(val / data.max())
            for index in ["[0, 0]", "[0, M']", "[N', 0]", "[N', M']"]:                ax.text(*index_to_coordinate(index, extent, origin),                        index, color='white', ha='center', va='center',                        bbox={'boxstyle': 'square',                              'facecolor': get_color(index, d, im.get_cmap())}                        )

@tacaswell
Copy link
MemberAuthor

@timhoffm@ImportanceOfBeingErnest feel free to push directly to this branch, I think all of these suggestions are great 👍

Would probably push the index labels in a bit or give them some alpha, they are covering the tick labels and the arrow. The index labels make also make the arrow superfluous.

@efiring
Copy link
Member

@ImportanceOfBeingErnest Why is the convention (N, M)? Is this only for images? I find it quite confusing--why use reversed-alphabetical order? What about indices--are they (i, j), or (j, i)?

@ImportanceOfBeingErnest
Copy link
Member

@efiring Good point. For some reason we're using this convention, but upon reflection and googling, I did not find profound evidence for it being "widely used". I was then somehow confirmed by the recently proposed changes to the imshow docs (#10982). (@timhoffm Might this be a typical german thing?)

So restart from scratch: theimshow docs need to decide for one convention (#10323,#10982), this convention needs to be documented (#10225). This guide here needs to use the same convention.

From a bit of googling and also looking at wikipedia it seems(m,n) /(M,N) /M x N could be preferable above(n,m) /(N,M) /N x M.

@timhoffm
Copy link
Member

@timhoffm
Copy link
Member

(-0.5, 6.5, 5.5, -0.5),
(6.5, -0.5, -0.5, 5.5),
(6.5, -0.5, 5.5, -0.5)]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This set of examples doesn't really help me because the "extents" is still the same as the extents I'd expect from the underlying data array size. Wouldn't it be more illustrative to go from 0-15 or something? The phrase "...a bounding box in data space" is also mysterious. I think of the matrix as being the data and a bounding box on the data means a clip to me. But what you mean is that the extents are the x and y co-ordinates over which the matrix is placed.

The docs say "The location, in data-coordinates, of the lower-left and upper-right corners" ; I prefer "data-coordinates"

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The point is to show how inverting the left vs right or top vs bottom changes the image around. Using different limits would make that a harder apples-to-apples comparison.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

yes But it didn’t help me understand what extents actually is on the first place

I’ll admit this flipping the axes seems like the wrong behaviour. I’d have expected the matrix to flip. But I doubt I’ll get that changed here. ;-)

@tacaswell
Copy link
MemberAuthor

I really like the changes! Thanks@ImportanceOfBeingErnest and@timhoffm !

I am 👍 on merging this, but don't want to push the button as I have commits in this and can not approve is github things this is my PR.

@timhoffm
Copy link
Member

  • Rephrased the section with "bounding box in data space".
  • Fixed some typos.

Probably this example could be improved even further, but that would require significant restructuring of code and description. I'm pushing this forward to have a reference to point to from the imshow docstring and get my associated PR#10982 approved. As a first step this PR is now good enough for that. Further improvements can be added later.

@jklymakjklymak merged commite22a16a intomatplotlib:masterMay 2, 2018
@jklymak
Copy link
Member

I merged as a stand-alone improvement. Can be refined upon...

jklymak added a commit that referenced this pull requestMay 2, 2018
@tacaswelltacaswell deleted the doc_imshow_extent branchMay 3, 2018 12:49
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@jklymakjklymakjklymak left review comments

@timhoffmtimhoffmtimhoffm left review comments

@dstansbydstansbydstansby left review comments

@ImportanceOfBeingErnestImportanceOfBeingErnestImportanceOfBeingErnest left review comments

Assignees
No one assigned
Projects
None yet
Milestone
v2.2-doc
Development

Successfully merging this pull request may close these issues.

7 participants
@tacaswell@ImportanceOfBeingErnest@timhoffm@efiring@jklymak@dstansby@QuLogic

[8]ページ先頭

©2009-2025 Movatter.jp