Opened 10 years ago
Closed 9 years ago
#13078 closed enhancement (fixed)
Make it easier to do custom tick formatting
Reported by:  kcrisman  Owned by:  jason, was 

Priority:  minor  Milestone:  sage5.9 
Component:  graphics  Keywords:  
Cc:  ppurka  Merged in:  sage5.9.beta1 
Authors:  Punarbasu Purkayastha  Reviewers:  Volker Braun, KarlDieter Crisman 
Report Upstream:  N/A  Work issues:  
Branch:  Commit:  
Dependencies:  Stopgaps: 
Description (last modified by )
This sagesupport thread raised the interesting question of having not just custom ticks, but then custom formatting of said ticks onebyone (say, setting the ticks but wanting them labeled x_0
, x_1
, etc.).
User "ObsessiveMathsFreak?" contributed the following code there.
========================== def plot_labels(x_ticks,x_labels,y_ticks,y_labels,fontsize=12): import matplotlib.ticker def latex_ticklabels(lbls_x,lbls_y): return [matplotlib.ticker.FixedFormatter(lbls_x),matplotlib.ticker.FixedFormatter(lbls_y)] ft=fontsize return plot([],ticks=[x_ticks,y_ticks],tick_formatter=latex_ticklabels(x_labels,y_labels),fontsize=ft) PL=plot_labels([1,3],["$x_1$","$x_2$"],[1,2,3.5],["$y_1$","$y_2$","$y_3$"],fontsize=15) P0=plot(x,(x,0,2)) P1=plot(x^2,(x,0,4)) show(P0+PL) show(P1+PL) ========================== I hope this is useful
Maybe there is a way we can work that into our tick and formatting framework.
Apply trac_13078add_custom_tick_labeling.patch to devel/sage.
Attachments (1)
Change History (25)
comment:1 Changed 10 years ago by
 Cc ppurka added
comment:2 Changed 10 years ago by
comment:3 Changed 10 years ago by
I already have a solution for this. See the originally linked thread. I am waiting for some of the other tickets related to the plot commands to get merged so that I don't need to rebase this.
comment:4 Changed 10 years ago by
I'll put that here as well.

sage/plot/graphics.py
# patch diff git a/sage/plot/graphics.py b/sage/plot/graphics.py
a b 1913 1913 raise ValueError('Expand the range of the dependent variable to allow two multiples of your tick locator (option `ticks`).') 1914 1914 1915 1915 x_formatter, y_formatter = tick_formatter 1916 from matplotlib.ticker import FuncFormatter 1916 from matplotlib.ticker import FuncFormatter, FixedFormatter 1917 1917 from sage.misc.latex import latex 1918 1918 from sage.symbolic.ring import SR 1919 1919 if x_formatter is None: … … 1924 1924 x_formatter = FuncFormatter(lambda n,pos: _multiple_of_constant(n,pos,x_const)) 1925 1925 elif x_formatter == "latex": 1926 1926 x_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n)) 1927 elif isinstance(x_formatter, (list, tuple)): 1928 x_formatter = FixedFormatter(x_formatter) 1927 1929 if y_formatter is None: 1928 1930 y_formatter = OldScalarFormatter() 1929 1931 elif y_formatter in SR: … … 1932 1934 y_formatter = FuncFormatter(lambda n,pos: _multiple_of_constant(n,pos,y_const)) 1933 1935 elif y_formatter == "latex": 1934 1936 y_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n)) 1937 elif isinstance(y_formatter, (list, tuple)): 1938 y_formatter = FixedFormatter(y_formatter) 1935 1939 1936 1940 subplot.xaxis.set_major_locator(x_locator) 1937 1941 subplot.yaxis.set_major_locator(y_locator)
You also said:
This can be tested with a plot like this:
plot(x, (x,0,2), ticks=[[1,2],[1,2,3.5]], tick_formatter=[["$x_1$","$x_2$"],["$y_1$","$y_2$","$y_3$"]])
There should probably be more checks like
len(ticks[0]) == len(tick_formatter[0])
and so on, but that can be addressed in a proper patch.
comment:5 Changed 10 years ago by
There should probably be more checks like
Yeah, and that ticks
was in fact passed in, etc. This will be very nice.
comment:6 Changed 10 years ago by
 Description modified (diff)
 Status changed from new to needs_review
Added patch for custom tick labeling.
comment:7 Changed 10 years ago by
Swift glance is all I have time for now, but on the face of it this seems good. ppurka, do we want the possibility of custom formatting even if for some reason someone just guesses that there are three ticks and then pass in the correct list? What about if people send in other custom tick options? For instance, I could imagine
plot(sin(x),(x,2*pi,2*pi),ticks=pi,tick_formatter=['$2\pi$','','','','$2\pi$'])
or something. Notice also that we want to make sure that it works properly with the tick_formatter
convention that if there is only one item, not a list of two lists/None
, then it corresponds to the horizontal axis. Otherwise things get too weird.
comment:8 Changed 10 years ago by
The docstring says
If the value of this keyword is a single item, then this will give the formatting for the horizontal axis *only* (except for the ""latex"" option). If it is a list or tuple, the first is for the horizontal axis, the second for the vertical axis. The options are below:
Notice that prior to this, a list was not allowed only for the horizontal axis. It was always a single item
, whatever that meant (and it didn't mean a list).
I really want to force the requirement of having ticks
and tick_formatter
being of correct lengths. I want to avoid situations where,for instance, the user inputs ticks=pi
and then doesn't give the correct number of custom labels. Is there some easy way of determining how many tick positions will be present in an axis?
comment:9 Changed 10 years ago by
Yeah, that was probably a little sloppy, and in any case, this is new functionality. If it doesn't break the old one... since these things have to be strings, maybe one could check if the first item was a string, and then let it go through... Just seems like
plot(sin(x),(x,2*pi,2*pi),ticks=[1,2,3],tick_formatter=['a','b','c'])
should work, by analogy with the other things that already work.
My point is that there isn't an easy way to determine how many there will be, but that once one does know (for instance, by plotting the picture with ticks=pi
), then they might as well be able to do the formatting I suggest. Wouldn't matplotlib raise an error we could catch if the formatter (at least, the FixedFormatter
) had too many/too few entries?
comment:10 followup: ↓ 11 Changed 10 years ago by
Actually matplotlib does not complain at all. I can remove the check for the lengths of ticks
and tick_formatter
and it will do all of what you mention above. Then it will be up to the user to ensure sane input.
EDIT: Also, the entries of the list passed in tick_fomratter
need not be strings. They can be even numbers.
comment:11 in reply to: ↑ 10 Changed 10 years ago by
Actually matplotlib does not complain at all. I can remove the check for the lengths of
ticks
andtick_formatter
and it will do all of what you mention above. Then it will be up to the user to ensure sane input.
Oh, that's actually bad. I happen to like sanity checks for things like this  despite the fact that we should know what we're doing, this is math software, not software software, so I think it's better to have that. Hmm, I'm not sure to do now. Is there a way to get the number of major ticks from mpl before using the formatter? Sorry for so many questions; hopefully someone else will have more wellbaked ideas.
comment:12 followup: ↓ 13 Changed 10 years ago by
EDIT: Also, the entries of the list passed in tick_fomratter need not be strings. They can be even numbers.
Hmm, but what would it do with the preparser? Like if tick_formatter=[[1,3,88],None]
? Would we get just the printed version, or ... just curious. I'm sorry I only have time to kibitz and not actually try this out.
comment:13 in reply to: ↑ 12 Changed 10 years ago by
Replying to kcrisman:
EDIT: Also, the entries of the list passed in tick_fomratter need not be strings. They can be even numbers.
Hmm, but what would it do with the preparser? Like if
tick_formatter=[[1,3,88],None]
? Would we get just the printed version, or ... just curious. I'm sorry I only have time to kibitz and not actually try this out.
It seems to work just fine. It evaluates the expression and prints the result as the tick label.
comment:14 Changed 9 years ago by
Please fill in your real name as Author.
comment:15 Changed 9 years ago by
comment:17 in reply to: ↑ 16 Changed 9 years ago by
Looks good to me.
Is that a positive review? My suggestions were not enough to warrant holding this up.
comment:18 Changed 9 years ago by
*ping*: Hello! It looks like we are really close here! Can we look into this and see if we can merge this into Sage? :)
comment:19 Changed 9 years ago by
 Status changed from needs_review to positive_review
comment:20 Changed 9 years ago by
 Reviewers changed from Volker Braun to Volker Braun, KarlDieter Crisman
Thanks ;)
comment:21 Changed 9 years ago by
 Milestone changed from sage5.8 to sage5.9
comment:22 Changed 9 years ago by
 Status changed from positive_review to needs_work
This should be rebased to sage5.9.beta0:
applying /padic/release/merger/patches/trac_13078add_custom_tick_labeling.patch patching file sage/plot/graphics.py Hunk #1 succeeded at 1420 with fuzz 2 (offset 31 lines). patching file sage/plot/plot.py Hunk #1 succeeded at 134 with fuzz 1 (offset 0 lines).
comment:23 Changed 9 years ago by
 Status changed from needs_work to positive_review
Rebased it to sage5.9.beta0. There are no updates, and the only changes should be zero fuzz and zero offset. Hence, I am setting it back to positive review.
comment:24 Changed 9 years ago by
 Merged in set to sage5.9.beta1
 Resolution set to fixed
 Status changed from positive_review to closed
See also #9578 and #2189.