Skip to content

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

Merged
merged 14 commits into from
May 7, 2018
Merged

Conversation

HHest
Copy link
Contributor

@HHest HHest commented Jan 25, 2018

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:

image

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.

image

This PR implements the fixed-scaling feature via a small change to ticker.py

@@ -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:
Copy link
Member

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...

Copy link
Contributor Author

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.
@jklymak
Copy link
Member

jklymak commented Jan 25, 2018

I think this needs a test and a what's new. See https://matplotlib.org/devdocs/devel/testing.html

@tacaswell
Copy link
Member

👍 It is a slight change in behavior,. Would it be better to make a slightly bigger change and let scilimits also take a scaler which would trigger this behavior? This would like the user type ax.ticklabel_format(style='sci', scilimits=6, axis='y') which is much less arcane.

@tacaswell tacaswell added this to the v2.2 milestone Jan 25, 2018
@HHest
Copy link
Contributor Author

HHest commented Jan 26, 2018

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 scilimits, however, since this is a plural word. We could introduce a new style='fixed', but this is even a larger change.

Will create at test for the scilimits cases, jklymak, but I guess this will depend on what we decide to do regarding scilimits.


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')``
Copy link
Member

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),
]
Copy link
Member

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?

Copy link
Contributor Author

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.

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:
Copy link
Member

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).

@tacaswell
Copy link
Member

Looking at the changes to support a scalar scilimits it looks like it may be more trouble than it's worth. Merging the (x, x) change looks like a nice improvement and does not prevent us from adding the scalar support in the future. Sorry for sending you down a rabbit hole!

Is there a way with this change to get the previous scaling and tick labels back?

@HHest
Copy link
Contributor Author

HHest commented Jan 27, 2018

No worries. That's why we have discussions.

Sorry I don't follow your last question.

@dstansby dstansby modified the milestones: needs sorting, v3.0 May 7, 2018
@dstansby dstansby merged commit fb98a9a into matplotlib:master May 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants