Many custom tick labelling issues can be solved by using one of mpl.ticker.FixedFormatter, FuncFormatter or even sometimes the FormatStrFormatter. But none of them give access to the offset string. In the simplest case, they could just override get_offset with a function that returns self.offset, which could be set via the constructor or just by attribute access. See e.g. http://stackoverflow.com/questions/29827807 .
I am currently looking for a way to start contributing to the matplotlib project and this issue looks like a good place to start as any. Moreover, the issue is something I have encountered myself several times.
I will read up on the relevant code for this in the next couple of days and formulate and post my plan here.
have a look at my stackoverflow answer, if I remember correctly, I described the process quite in detail. I was just too busy to actually make it into a PR.
I think there are two issues at play here, also looking at the ticket and the stackoverflow question/answer: (1) Setting an offset, i.e. a shift in the data. (2) Setting a scaling factor for the data. For scenarios are realistic use-cases with which I have dealt before myself.
I think this example should make it clear:
x=np.linspace(1000,1010)
y=x
when plotting (method do not exists [yet]):
with "plt.gca().get_xaxis().get_major_formatter().set_offset(1000)" -> the xticks should be 0,1,...,9 with a label +1e3
with "plt.gca().get_xaxis().get_major_formatter().set_scaling(1000)" -> the xticks should be 0,0.1,...,0.9 with label 1e3, i.e. the values are multiplied with 1e3.
The functionality for setting the offset value was/is hidden in set_useOffset in ticker.py which takes True, False, or value. The first two cases toggle the usage of an offset and set it the offset to 0. Using value v sets the offset to v, for example: plt.gca().get_xaxis().get_major_formatter().set_useOffset(1e3) subtracts 1e3 from the ticks and add a +1e3 label.
I propose the following changes to implement these two use cases:
(1) split the functionality of the current function set_useOffset() which should only toggle the offset into two functions: set_useOffset() for toggling and a separate function set_offset() to set the offset.
(2) I will add documentation for both functions.
(3) Add a function to set a fixed scaling factor used when running with ...set_scientific(True), again with documentation.
(4) A function to set/disable the string +1e3/1e3 string. This is useful if this information has to be included in the xlabel, for example plt.xlabel("atomic density (10^14 cm^2)"). , again with documentation.
Each will be a separate commit.
I apologize if this is going in the wrong direction and is wasting time (I honestly hope not).
It doesn't, although none of these functionalities should be very hard to add. What may be harder (especially if restarting from master) is to ensure that just setting the "wrong" combination of these parameters by hand does not completely mess up the formatting... and to avoid an even more blown up API than the one already there.
Combining offset and scaling is possible at the moment, but it makes the plot (very) hard to understand. I have never seen this in e.g. a journal article / presentation. I propose (and have implemented) that the user can have either an offset or a scaling factor but never both.
At the moment both an offset and scaling (via set_scientific). Unfortunately, this actually leads to incorrect results. For the code:
x=sp.rand(1000)*1E14
y=x+1000
plt.scatter(x,y)
plt.gca().get_xaxis().get_major_formatter().set_useOffset(100)
The plot is ignoring the set_useOffset(100) call, see also here: bugOffsetPlusSci.pdf
I will patch this while I am working on this ticket.
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
VincentVandalon commented on Feb 18, 2016
I am currently looking for a way to start contributing to the matplotlib project and this issue looks like a good place to start as any. Moreover, the issue is something I have encountered myself several times.
I will read up on the relevant code for this in the next couple of days and formulate and post my plan here.
burnpanck commented on Feb 18, 2016
have a look at my stackoverflow answer, if I remember correctly, I described the process quite in detail. I was just too busy to actually make it into a PR.
VincentVandalon commented on Feb 20, 2016
I think there are two issues at play here, also looking at the ticket and the stackoverflow question/answer: (1) Setting an offset, i.e. a shift in the data. (2) Setting a scaling factor for the data. For scenarios are realistic use-cases with which I have dealt before myself.
I think this example should make it clear:
x=np.linspace(1000,1010)
y=x
when plotting (method do not exists [yet]):
with "plt.gca().get_xaxis().get_major_formatter().set_offset(1000)" -> the xticks should be 0,1,...,9 with a label +1e3
with "plt.gca().get_xaxis().get_major_formatter().set_scaling(1000)" -> the xticks should be 0,0.1,...,0.9 with label 1e3, i.e. the values are multiplied with 1e3.
The functionality for setting the offset value was/is hidden in set_useOffset in ticker.py which takes True, False, or value. The first two cases toggle the usage of an offset and set it the offset to 0. Using value v sets the offset to v, for example: plt.gca().get_xaxis().get_major_formatter().set_useOffset(1e3) subtracts 1e3 from the ticks and add a +1e3 label.
I propose the following changes to implement these two use cases:
(1) split the functionality of the current function set_useOffset() which should only toggle the offset into two functions: set_useOffset() for toggling and a separate function set_offset() to set the offset.
(2) I will add documentation for both functions.
(3) Add a function to set a fixed scaling factor used when running with ...set_scientific(True), again with documentation.
(4) A function to set/disable the string +1e3/1e3 string. This is useful if this information has to be included in the xlabel, for example plt.xlabel("atomic density (10^14 cm^2)"). , again with documentation.
Each will be a separate commit.
I apologize if this is going in the wrong direction and is wasting time (I honestly hope not).
tacaswell commented on Feb 21, 2016
@anntzer Does your formatter re-factor take this into account?
anntzer commented on Feb 21, 2016
It doesn't, although none of these functionalities should be very hard to add. What may be harder (especially if restarting from master) is to ensure that just setting the "wrong" combination of these parameters by hand does not completely mess up the formatting... and to avoid an even more blown up API than the one already there.
VincentVandalon commented on Feb 26, 2016
Combining offset and scaling is possible at the moment, but it makes the plot (very) hard to understand. I have never seen this in e.g. a journal article / presentation. I propose (and have implemented) that the user can have either an offset or a scaling factor but never both.
At the moment both an offset and scaling (via set_scientific). Unfortunately, this actually leads to incorrect results. For the code:
x=sp.rand(1000)*1E14
y=x+1000
plt.scatter(x,y)
plt.gca().get_xaxis().get_major_formatter().set_useOffset(100)
The plot is ignoring the set_useOffset(100) call, see also here:
bugOffsetPlusSci.pdf
I will patch this while I am working on this ticket.
github-actions commented on Mar 12, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!