-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Ability to scale axis by a fixed factor #10321
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
lib/matplotlib/ticker.py
Outdated
@@ -727,7 +727,10 @@ def _set_orderOfMagnitude(self, range): | |||
oom = 0 | |||
else: | |||
oom = math.floor(math.log10(val)) | |||
if oom <= self._powerlimits[0]: | |||
if self._powerlimits[0] == self._powerlimits[1] != 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this if statement could go up above to save calculating oom
, which we don't end up using in this case...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. I've moved it higher up.
per jklymak suggestion.
I think this needs a test and a what's new. See https://matplotlib.org/devdocs/devel/testing.html |
👍 It is a slight change in behavior,. Would it be better to make a slightly bigger change and let |
Thanks for the feedback tacaswell. Yes, it's true that as it stands now, (m, m) is equivalent to (0, 0), which makes (0, 0) not quite special even though the document specifically mentions it. The proposed change would alter this behavior. I am slightly hesitant about allowing a scalar input to Will create at test for the |
|
||
To scale an axis by a fixed order of magnitude, set the *scilimits* argument | ||
of ``Axes.ticklabel_format`` to the same lower and upper limits. Say to scale | ||
the y axis by a million (1e6), use ``ax.ticklabel_format(style='sci', scilimits=(6, 6), axis='y')`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a little mysterious to the un-initiated. i.e. why the heck do I have to specify 6 twice in this argument. I'd say something before that about the "old" way that this worked, and how this is a special case.
I think I agree w/ @tacaswell that this might as well also allow a single integer. Having a plural in the kwarg name isn't really a good reason to not allow this; limits collapse to single values all the time.
(True, (-2, 2), (-.001, 0.002), -3), | ||
(True, (0, 0), (-1e5, 1e5), 5), | ||
(True, (6, 6), (-1e5, 1e5), 6), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a scalar example into here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we've decided not to take in scalar anymore, this is a moot point..., but just for posterity sake, my intention was to allow scalar input at the ticklabel_format API level, not at this lower level, where the test sits. The scalar input would then be translated to pair of (repeated) values for lower level consumption.
lib/matplotlib/axes/_base.py
Outdated
m + n + 1 # check that both are numbers | ||
except (ValueError, TypeError): | ||
raise ValueError("scilimits must be a sequence of 2 integers") | ||
if type(scilimits) == int: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing type(foo) == XX
tests is not the best way to do this sort of thing (for example, it will fail on type(np.int8(5)) == int
which is something that a user would reasonably expect to work) and it will fail on all sub-classes. It is better to do isinstance(foo, XX)
which will correctly handle sub-classes (but that still fails np.int8
). In this case I think something like
try:
m, n = scilimits
except (TypeError, ValueError):
try:
m = n = scilimits
except TypeError:
raise ValueError(...)
try:
m + n + 1
except TypeError:
raise ValueError(...)
It also looks like below scilimits
is passed through to set_powerlimits
(not m and n).
Looking at the changes to support a scalar Is there a way with this change to get the previous scaling and tick labels back? |
No worries. That's why we have discussions. Sorry I don't follow your last question. |
Often we would like to scale the axis by a certain fixed factor, and we do not want to adjust the values prior to plotting in matplotlib. Here's an example of the behavior, with fixed-scaling of 1e6:
We can turn on scaling by
ax.ticklabel_format(style='sci', scilimits=(6, 6), axis='y')
; however, matplotlib would adjust the scaling factor such that the largest label would be greater than one. In other words, the scaling is on, but it is not fixed.This PR implements the fixed-scaling feature via a small change to ticker.py