Adjusting zero and negative values (or maybe just zero)
> would be unacceptable in a numerics library, but in the
> context of our graphical transforms it is analogous to
> clipping, and this we do all the time--we don't raise an
> exception if someone tries to plot outside the box. (This
> clipping strategy to handle nonpositive values is present
> already in the LogLocator.)
I'm more comfortable dropping points than I am altering the data.
Consider some use case like
ax.hist(...)
rect = Rectangle(...)
ax.add_patch(rect)
ax.set_xscale('log')
In set_xscale we only see a bunch of rectangles. User defined
rectangles may be used to store data (eg the JPL uses custom bars with
xlimits that are the start and stop times when orbiting spacecraft are
within view of a ground station). Some of these users will also want
to "pick" the rectangle and inspect the data values. If we are
altering them, they have no guarantee that what they put in is what
they get out. Now we might argue that they get what they deserve if
they are using invalid data for a log scale, but one good solution in
my view is to fail noisily with helpful messages, and provide an easy
interface to do it right.
But if I am missing your point or you have an implementation that will
address these concerns, I'm certainly open to them. One possibility
is to flag artists that we create internally (eg hist) and take more
liberty with these, or have some flag like the Artist "clip_on"
property which allows the user to control whether their data is
mutable to support "helpful" alterations for log or other
transformations.
> We can use such a small adjustment value that a problem such
> as you mention above is highly unlikely--and note that
> floating point itself has limitations, and does not permit
> arbitrarily small or large numbers. Furthermore, note that
> the user can always take advantage of the bottom kwarg. And
> if in some extreme case the user has not used the bottom
> kwarg and the bars really are shorter than the adjustment
> value, it will probably be quite obvious.
The other thing to think about is choosing a bottom so that the
natural range of the tops is revealed. Eg if the bottom is 1e-200,
all the bars will appear the same height in many cases.
> It is in ordinary line plotting that adjusting the value
> could be misleading--it plots an extremely small number (if
> the data limits are set to include it) instead of zero.
> Maybe this is enough of a drawback to nix the whole idea.
I am happy with the current behavior of culling the non-positive
points. matlab does it and noone has complained here. There is a
difference in lines created with "plot" and bars created with hist: in
the former case the users explicitly picked the x,y points. In the
latter they implicitly do so with a default bottom kwarg that they may
have overlooked. This suggests to me that we need not treat the two
cases the same.
> Every alternative that you propose is more complicated and
> less comprehensive than the low-level adjustment, however,
> and I see little if any real advantage to the alternatives.
If you would like to take a stab at an implementation I am happy to be
persuaded (with caveats below). In the simple case of
ax.hist()
ax.set_xscale('log')
this would indeed be fairly easy because you know how the data were
created. In the general case where the user has added lots-o-patches
to the axes, it may not be easy to do well. I'm still inclined to the
"explicit is better than implicit" and either require them to do one of
1) use the bottom kwarg
2) set log scaling before calling hist -- we can make the default
bottom=None and do different things for linear and log scaling
3) use a loghist function
> If you still don't want the adjustment, then the easiest way
> to improve the error message would be to raise a Python
> exception instead of a c++ error in places like
> for(int i=0; i < length; i++) { if (x<=0) { throw
> std::domain_error("Cannot take log of nonpositive value"); }
> else newx[i] = log10(x[i]);
> }
> The domain error message above is informative, but it never
> makes it out to the user.
I really don't feel too strongly about this -- my gut reaction is that
a helpful message and an easy way to fix it is enough and it won't get
us into a possible quagmire of trying to be too smart. Personally, I
don't like it when computers try to be too helpful (think MS windows
and clippy); I like it when they do what I tell them to do. With the
snippet I posted previously we can easily warn them before doing the
transformation and with bottom=None we can handle the case when the
log scale is set before the call to hist. That in conjunction with
some additional docstrings in hist should work reasonably well.
That said, if you want to try something more ambitious I won't get in
your way. I recommend at a minimum that you have some artist flag
that governs whether mpl can make helpful data alterations (just as we
do with clip) so the power user can turn it off.
JDH