From: John H. <jdh...@ac...> - 2004-09-14 14:25:29
|
>>>>> "Alan" == Alan G Isaac <ai...@am...> writes: Alan> Crudely: I'm looking for something just as simple in Alan> matplotlib.matlab. My last post outlined what I think the Alan> current procedure is to achieve the same effect, and it is Alan> much more cumbersome. While this matters little when one is Alan> leisurely writing a script, it matters a lot when one is Alan> doing interactive plotting in a classroom setting. Alan> Now you point out that this request has an ambiguity: what Alan> "physical" medium am I talking about? Specifically, a true Alan> compression ratio on screen requires tricky stuff if dpiy != Alan> dpix. OK, I assume ignoring this will yield a "close Alan> enough" result in a classroom setting, so the only time I Alan> need it to be exact is when I produce figures for paper Alan> display. w/o having to worry about dpi differences in the x and y direction, it is much easier, and your hardcopy will be correct in any case. Do you really need arbitrary compression ratios, or just ratios equal to 1. I added the option 'equal' to the axis command, which simply sets the xlim and ylim to be equal and includes the range of both. I'll include the modified axis method from matlab.py at the end of this email. Thus you can do from matplotlib.matlab import * figure(figsize=(6,6)) ax = axes([0.1, 0.1, 0.8, 0.8]) plot(rand(100), rand(100), 'o') axis('equal') show() Admittedly this is more typing than you want to do in an interactive session. I experimented with a function 'square' which isn't the right name but you get the idea. It handles setting the figure size, axes ratio and lim ratio for you. Some suitably named function could be included in the standard interface from matplotlib.matlab import * def square(): fig = gcf() ax = gca() figw, figh = fig.get_size_inches() l,b,axw,axh = ax.get_position() side = min([figw, figh]) frac = min([axw, axh]) fig.set_figsize_inches(side, side) ax.set_position([l,b,frac,frac]) axis('equal') draw() plot(rand(100), rand(100), 'o') square() show() It's the right idea, but it doesn't work currently if you are using a GUI backend. The reason it fails is has to do with the pipeline order in which figure managers, figures etc are created by default, and the fact that configure events and resize events change the figure width and height (so you can for example, resize your figure window). It *does* work if you specify the figure size figure(figsize=(8,8)) plot(rand(100), rand(100), 'o') square() show() because then matplotlib has the information it needs at figure creation time. Of course, you can set the figure size to have a unity aspect ratio in your rc file and then you could do without the figsize command altogether. I'll think about how to best fix the GUI resizing problem. I'll probably need to add an observer to the figure limits so that the GUI backend can update its size from script calls to figure size. As an aside, traits are starting to look very useful, with their build in observer framework. For now, any feedback on whether this approach looks like the right one, whether any ratios other than 1 are actually needed, what the function square should be called and anything else is welcome. JDH def axis(*v): """ axis() returns the current axis as a length a length 4 vector axis(v) where v= [xmin xmax ymin ymax] sets the min and max of the x and y axis limits axis('off') turns off the axis lines and labels axis('equal') sets the xlim and ylim to be identical """ if len(v)==1 and is_string_like(v[0]): s = v[0] if s.lower()=='on': gca().set_axis_on() elif s.lower()=='off': gca().set_axis_off() elif s.lower()=='equal': ax = gca() xmin, xmax = ax.get_xlim() ymin, ymax = ax.get_ylim() vmin = min([xmin, ymin]) vmax = max([xmax, ymax]) ax.set_xlim((vmin, vmax)) ax.set_ylim((vmin, vmax)) draw_if_interactive() else: error_msg('Unrecognized string %s to axis; try on or off' % s) return try: v[0] except IndexError: xlim = gca().get_xlim() ylim = gca().get_ylim() return [xlim[0], xlim[1], ylim[0], ylim[1]] v = v[0] if len(v) != 4: error_msg('v must contain [xmin xmax ymin ymax]') return gca().set_xlim([v[0], v[1]]) gca().set_ylim([v[2], v[3]]) draw_if_interactive() |