Well, I seem to have really dove into this.
Here are 4 different patches against the latest svn of axes.py (rev 2495). Note that the rest of my install is the 0.87.3 release (I had to copy over quiver.py to get the latest axes.py to work).
patch1 has the following changes to bar() and barh():
- fixed ignoring the rcParams['patch.facecolor'] for bar color: the default value for the color arg is now None, and the Patch class is left to handle fetching the rcparams['patch.facecolor']
- set default error bar color to None, so that errorbar() can handle fetching the rcParams['lines.color']
- added an edgecolor keyword arg
- left and height can now both be scalars in bar(), same goes for x and y in barh(). Previously, this raised a TypeError upon testing their lengths. Code that preventively checked for this in barh() (but not in bar()) has been removed.
- fixed a bug where patches would be cleared when error bars were plotted if rcParams['axes.hold'] was False
- it looks like the code for barh() was copied from bar(), with some of the args renamed. There was an error in the color checking code in barh() where len(left) from bar() hadn't been properly renamed to len(x)
- found one or two changes that had been made to bar() that hadn't been propagated to barh(), or vice versa
- rearranged the order of some code segments so that they follow the order of the arguments
- updated the docstrings
Hopefully I haven't introduced any new bugs.
patch2 has everything in patch1, except it removes some code duplication by calling bar() from within barh(). I thought this would be a good idea, since it's easy to make a change in bar() and forget to do the same in barh(). It turns out that this takes up almost as many lines of code as having two independent functions, but this is only due to inconsistent behaviour: barh() draws bars vertically centered on the y values (ala matlab 6.0), while bar() draws bars aligned according to their left edge (not ala matlab). I prefer the edge aligning behaviour. It's easy to convert from one behaviour to the other, but I had to duplicate all the error checking code before conversion, which bloated it back up.
So... patch3 has everything in patch2, but renames the x and y args in barh() to width and bottom respectively. This makes barh() draw bars vertically aligned to their bottom edge, consistent with bar()'s behaviour. Also, this makes hist(orientation='horizontal') do the same, which makes it consistent with hist(orientation='vertical'). Finally, it removes the code bloat mentioned above. However, it'll break any existing code that relies on x or y as named args in barh(), or code that expects barh() bars to be vertically centered on their y values.
And lastly... I find it odd that barh() has the width and bottom args (formerly x and y) in that order: barh(width, bottom). The general matlab convention is that the first argument is the positions, and the second arg is the values. So it would make more sense to me to have barh(bottom, width). That way, you could switch back and forth between bar() and barh() and get the expected behaviour without having to switch around the arguments. In fact, that's exactly how barh() in matlab 6 interprets the first two arguments: arg1 is the vertical positions, and arg2 is the lengths of the bars at those positions. Same goes for matlab's bar() function. As it is now in matplotlib, the first and second arguments are interpreted differently for bar() and barh()
I don't know if anyone agrees with this change, but patch4 has all of the changes in patch3, plus the order of the width and bottom args are switched in barh(). This of course will break existing code that depends on this order. I had to modify the barh() call in hist(orientation='horizontal') to reflect this. I couldn't find any other barh() call in matplotlib. For consistency, I also switched the order of the yerr and xerr args, but these have default values and are usually passed as keyword args, so this shouldn't break (much) code.
The patches are numbered in increasing order of preference. They look rather big (and I'm not sure if my file compare util is bug-free). If there seem to be problems with them, I can provide the full axes.py file that corresponds to each patch.
patch1.txt (12 KB)
patch2.txt (12.4 KB)
patch3.txt (12.2 KB)
patch4.txt (12.7 KB)