[matplotlib-devel] Data limit oddity when combining normal line and axvline collections
Hi, I am hesitant to call the following a bug. It might just be a misunderstanding on my side. Anyhow... I am plotting a normal line collection and an "axvline" collection on the same Axes. The latter is a collection of lines with data coordinates for x and axes coordinates for y, using a blended transform. I find that the data limits are messed up by the axvline collection, which unexpectedly sets the bottom y limit to 0. This results in a badly scaled plot when adjusting the view with autoscale_view. Interestingly, this problem goes away if the normal line collection is viewed first via autoscale_view, if the normal line collection is replaced by a normal plot command, or if the axvline collection is replaced by a normal axvline command. The problem appears if the two collections are added to the Axes without an autoscale_view in between. I ran the code below with matplotlib trunk (SVN r8646) on Mac OS 10.5 with TkAgg backend. The same behaviour appears in matplotlib 0.99.1.1. Please let me know if I am doing something obviously stupid, especially in the way I create the axvline collection. At the moment I am working around the behaviour by inserting an autoscale_view between the two collections, so it is not a major show-stopper. Regards, Ludwig ### Start code snippet ### import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np # Create sine wave to plot (offset from zero) t = np.arange(200) x = 10 + np.cos(2 * np.pi * t / 20) plt.figure(1) plt.clf() ax = plt.gca() # Add main plot as a line collection containing one segment segments = mpl.collections.LineCollection([zip(t, x)]) ax.add_collection(segments) print ax.dataLim # Output: Bbox(array([[ 0.,9.], [ 199., 11.]])) # Uncommenting the line below actually fixes the problem... #ax.autoscale_view() # Add break lines as a collection of axvlines breaks = np.arange(0, 200, 20) transFixedY = mpl.transforms.blended_transform_factory(ax.transData, ax.transAxes) break_lines = mpl.collections.LineCollection([[(s, 0), (s, 1)] for s in breaks], transform=transFixedY, colors='k', linewidths=0.5, linestyles='dotted') ax.add_collection(break_lines) print ax.dataLim # Output: Bbox(array([[ 0.,0.], [ 199., 11.]])) # Notice that y0 is now 0 instead of the expected 9 # Autoscaling now inserts a lot of space below the original plot ax.autoscale_view() ### End code snippet ### -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] Colormap that prints nicely in black and white
On Tue, Aug 17, 2010 at 4:19 PM, Friedrich Romstedt < friedrichromst...@gmail.com> wrote: > 2010/8/17 Benjamin Root : > > "...it will not be necessary..." > > > > I think we are still getting confused here. I was listing off several > > different kinds of use-cases where one would like to have a mix of grey > > colormaps and colored colormaps. The reason I mention being able to save > a > > greyscale and a color version of the same figure is in the context of my > > approach to solving this problem (the swapping out of colormaps). > Honestly, > > I think that your approach is better for dealing with that particular use > > case. > > Okay, may be you're right and we should include the usecase you're > having in mind. > > > However, I mention other cases where one is merely wanting a modified > > version of a particular colormap to use, be it greyscale, or inverse, or > > brighter/darker, etc. > > Yes, that's neat. > > > What I envision your solution to be solving would be > > something like this: > > > fig = plt.figure() > > ax = fig.add_subplot(1, 2, 1) > > ax.plot(np.linspace(1, 10, 10), np.linspace(2, 8, 10)) > > ax.plot(np.linspace(1, 10, 10), np.linspace(4, 9, 10)) > > > > ax = fig.add_subplot(1, 2, 2) > > ax.set_grey(True) > > ax.plot(np.linspace(1, 10, 10), np.linspace(1, 8, 10)) > > ax.plot(np.linspace(1, 10, 10), np.linspace(3, 7, 10)) > > ax.plot(np.linspace(1, 10, 10), np.linspace(2, 9, 10)) > > Hmm, that's much more complicated ... For Collections, one could set a > local flag, but it would be nevertheless quite buried in the API ... > When setting it in the axes, one has to care about all artists added > later too, and all pathes an artist may sneak into the axes. > > I had a thought... and it is based on my admittedly incomplete understanding of matplotlib. Everything that gets drawn is derived from the artist class, right? So, what if there was a 'grey' boolean in that base class, and the .draw() function passes that bool down through all the subsequent .draw() calls of its child objects (it could be None by default to accept the parent's property, or allowed to be explicitly set by the user to override the parent's value.) By the time we get to the backends, all the color data should be in a clean, broadcasted rgba form, so it should then be a relatively simple check of the grey flag before writing out the color information. Admittedly, I would much rather have this flag check done before getting to the backends and through a single point of code. At first, I thought that ColorConverter would be it, but as I now understand it, it is treated more like a utility module rather than an important step in the rendering process. It gets used for things at different points in the matplotlib process. Maybe I am just going overboard here... > What I'm going to solve is simply a toplevel boolean 'gray' switch in > the rcParams. It's working in an abstract way. > > Maybe a complementary approach would be useful. A global switch for > everything, and more fine-tuning control coming from your side? > > I think the issue with my approach is that it would only impact things that uses colormaps. Anything that explicitly sets its colors without a colormap will be totally unaffected. > For the "road map", I cannot put myself under strong pressure with > this, I would say, although being a rather tiny thing, I will finish > it until end of next week. > > Can't wait to see what you have. > Ahh, and shall we name the switch 'gray' or 'grey' > > Heh, even matplotlib can't provide too much precedence here because it tries to cater to both spellings (and I keep flipping back and forth due to a stupid bug in the Ubuntu packaging that packaged a en_UK spell-checker instead of en_US, but my Fedora setup has it right...). I should note that for Colormaps, there is only a "is_gray" function. Cheers, Ben Root -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] small patch for trunk/matplotlib/lib/matplotlib/axis.py
This is a small patch to enable get_gridlines to be able to get the grid lines for the minor ticks as well. 1052c1052 < def get_gridlines(self): --- > def get_gridlines(self,minor=False): 1054c1054,1055 < ticks = self.get_major_ticks() --- > if minor: ticks = self.get_minor_ticks() > else: ticks = self.get_major_ticks() -- Daniel Hyams dhy...@gmail.com -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] ax.scatter broken for triangular markers
Hi, I updated to the latest svn version of matplotlib this morning, and Axes.scatter seems to be broken when using marker='v', '>', '<', or '^': import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as mpl fig = mpl.figure() ax = fig.add_subplot(1,1,1) ax.scatter([1,2,3], [4,5,6], marker='v') fig.savefig('test.png') gives: Traceback (most recent call last): File "test.py", line 7, in ax.scatter([1,2,3], [4,5,6], marker='^') File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/axes.py", line 5764, in scatter transOffset = self.transData, File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/collections.py", line 695, in __init__ self._paths = [self._path_generator(numsides)] File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/path.py", line 415, in unit_regular_polygon path = cls(verts, codes) File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/path.py", line 117, in __init__ assert len(codes) == len(vertices) AssertionError This did not occur when I updated to the latest svn a couple of days ago, so it must be due to a pretty recent change. Cheers, Tom -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] ax.scatter broken for triangular markers
Should be fixed in r8648 now. Mike On 08/18/2010 11:45 AM, Thomas Robitaille wrote: > Hi, > > I updated to the latest svn version of matplotlib this morning, and > Axes.scatter seems to be broken when using marker='v', '>','<', or '^': > > import matplotlib > matplotlib.use('Agg') > import matplotlib.pyplot as mpl > > fig = mpl.figure() > ax = fig.add_subplot(1,1,1) > ax.scatter([1,2,3], [4,5,6], marker='v') > fig.savefig('test.png') > > gives: > > Traceback (most recent call last): >File "test.py", line 7, in > ax.scatter([1,2,3], [4,5,6], marker='^') >File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/axes.py", > line 5764, in scatter > transOffset = self.transData, >File > "/Users/tom/Library/Python/2.6/site-packages/matplotlib/collections.py", line > 695, in __init__ > self._paths = [self._path_generator(numsides)] >File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/path.py", > line 415, in unit_regular_polygon > path = cls(verts, codes) >File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/path.py", > line 117, in __init__ > assert len(codes) == len(vertices) > AssertionError > > This did not occur when I updated to the latest svn a couple of days ago, so > it must be due to a pretty recent change. > > Cheers, > > Tom > -- > This SF.net email is sponsored by > > Make an app they can't live without > Enter the BlackBerry Developer Challenge > http://p.sf.net/sfu/RIM-dev2dev > ___ > Matplotlib-devel mailing list > Matplotlib-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/matplotlib-devel > -- Michael Droettboom Science Software Branch Space Telescope Science Institute Baltimore, Maryland, USA -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] ax.scatter broken for triangular markers
I can confirm that this now works fine - thanks for the quick fix! Tom On Aug 18, 2010, at 12:09 PM, Michael Droettboom wrote: > Should be fixed in r8648 now. > > Mike > > On 08/18/2010 11:45 AM, Thomas Robitaille wrote: >> Hi, >> >> I updated to the latest svn version of matplotlib this morning, and >> Axes.scatter seems to be broken when using marker='v', '>','<', or '^': >> >> import matplotlib >> matplotlib.use('Agg') >> import matplotlib.pyplot as mpl >> >> fig = mpl.figure() >> ax = fig.add_subplot(1,1,1) >> ax.scatter([1,2,3], [4,5,6], marker='v') >> fig.savefig('test.png') >> >> gives: >> >> Traceback (most recent call last): >> File "test.py", line 7, in >> ax.scatter([1,2,3], [4,5,6], marker='^') >> File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/axes.py", >> line 5764, in scatter >> transOffset = self.transData, >> File >> "/Users/tom/Library/Python/2.6/site-packages/matplotlib/collections.py", >> line 695, in __init__ >> self._paths = [self._path_generator(numsides)] >> File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/path.py", >> line 415, in unit_regular_polygon >> path = cls(verts, codes) >> File "/Users/tom/Library/Python/2.6/site-packages/matplotlib/path.py", >> line 117, in __init__ >> assert len(codes) == len(vertices) >> AssertionError >> >> This did not occur when I updated to the latest svn a couple of days ago, so >> it must be due to a pretty recent change. >> >> Cheers, >> >> Tom >> -- >> This SF.net email is sponsored by >> >> Make an app they can't live without >> Enter the BlackBerry Developer Challenge >> http://p.sf.net/sfu/RIM-dev2dev >> ___ >> Matplotlib-devel mailing list >> Matplotlib-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel >> > > > -- > Michael Droettboom > Science Software Branch > Space Telescope Science Institute > Baltimore, Maryland, USA > > > -- > This SF.net email is sponsored by > > Make an app they can't live without > Enter the BlackBerry Developer Challenge > http://p.sf.net/sfu/RIM-dev2dev > ___ > Matplotlib-devel mailing list > Matplotlib-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/matplotlib-devel -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] small patch for trunk/matplotlib/lib/matplotlib/axis.py
On Wed, Aug 18, 2010 at 9:25 AM, Daniel Hyams wrote: > This is a small patch to enable get_gridlines to be able to get the grid > lines for the minor ticks as well. > 1052c1052 > < def get_gridlines(self): > --- >> def get_gridlines(self,minor=False): > 1054c1054,1055 > < ticks = self.get_major_ticks() > --- >> if minor: ticks = self.get_minor_ticks() >> else: ticks = self.get_major_ticks() Thanks for the contribution. Can you regenerate using: diff -u so we can easily apply to the tree? Thanks, Ryan -- Ryan May Graduate Research Assistant School of Meteorology University of Oklahoma -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] small patch for trunk/matplotlib/lib/matplotlib/axis.py
Sure: --- axis.py 2010-08-18 09:59:25.0 -0400 +++ axis.py.orig2010-08-18 09:58:13.0 -0400 @@ -1049,12 +1049,9 @@ def _get_offset_text(self): raise NotImplementedError('Derived must override') -def get_gridlines(self,minor=False): +def get_gridlines(self): 'Return the grid lines as a list of Line2D instance' -if minor: - ticks = self.get_minor_ticks() -else: - ticks = self.get_major_ticks() +ticks = self.get_major_ticks() return cbook.silent_list('Line2D gridline', [tick.gridline for tick in ticks]) def get_label(self): On Wed, Aug 18, 2010 at 1:05 PM, Ryan May wrote: > On Wed, Aug 18, 2010 at 9:25 AM, Daniel Hyams wrote: > > This is a small patch to enable get_gridlines to be able to get the grid > > lines for the minor ticks as well. > > 1052c1052 > > < def get_gridlines(self): > > --- > >> def get_gridlines(self,minor=False): > > 1054c1054,1055 > > < ticks = self.get_major_ticks() > > --- > >> if minor: ticks = self.get_minor_ticks() > >> else: ticks = self.get_major_ticks() > > Thanks for the contribution. Can you regenerate using: diff -u > so we can easily apply to the tree? > > Thanks, > > Ryan > > -- > Ryan May > Graduate Research Assistant > School of Meteorology > University of Oklahoma > -- Daniel Hyams dhy...@gmail.com -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] Colormap that prints nicely in black and white
2010/8/18 Benjamin Root : > I had a thought... and it is based on my admittedly incomplete understanding > of matplotlib. Everything that gets drawn is derived from the artist class, > right? So, what if there was a 'grey' boolean in that base class, and the > .draw() function passes that bool down through all the subsequent .draw() > calls of its child objects (it could be None by default to accept the > parent's property, or allowed to be explicitly set by the user to override > the parent's value.) It's a neat idea again. I like it very much. I propose the following: 1) As you said, a gray flag in mpl.artist.Artist, which can be automatically transmitted to the child artists *on render time*. 2) Counting the "grayishness" (single, double, ... :-) in mpl.backends.renderer_bases.RendererBase. 3) Evaluating the grayishness in mpl.backends.renderer_bases.RendererBase.new_gc() [i.e., new graphics context]. Passing it on to the GraphicsContext as initialisaion argument. mpl.backends.renderer_bases.GraphicsContextBase has ONLY ONE COLOUR ARGUMENT, namely .set_foreground(). It seems everythings breaks down to foreground rendering of pathes and symbols. Indeed, it uses once again mpl.colors.colorConverter, and I think my refactoring of this one is not useless at all, but the main point is, it stores an rgb colour in the end, and in fact *all* rgb colours ever used in any graphics drawing context. Also for text, etc. pp. 4) Introducing a decorator: def draw_with_grayishness(fn): def decorated(self, renderer): if self.is_gray(): renderer.increase_grayishness() fn(self, renderer) renderer.decrease_grayishness() else: fn(self, renderer) return decorated This turns on grayishness in the renderer if it is requested by *self*, which is an Artist. > By the time we get to the backends, all the color data should be in a clean, > broadcasted rgba form, so it should then be a relatively simple check of the > grey flag before writing out the color information. Mmmh, for some reason colorConverter is used there again, maybe historical. > Admittedly, I would much rather have this flag check done before getting to > the backends and through a single point of code. At first, I thought that > ColorConverter would be it, but as I now understand it, it is treated more > like a utility module rather than an important step in the rendering > process. It gets used for things at different points in the matplotlib > process. Yes, it's not the only point, there is at least one more, mpl.collection.Collection.update_scalaramappable(). And there may be tons of other selfish procedures ... So I agree fully with you. > Maybe I am just going overboard here... Well, I come with you :-) So, the code point would be outside of the Renderer, but in the GraphicsContext, which is abstract enough to be shared by all implementations of the rendering. It is passed on to the implementation's methods as an argument, so its .foreground or whatever is the same to all rendering implementations. Friedrich -- This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel