SourceForge logo
SourceForge logo
Menu

matplotlib-devel

From: John H. <jdh...@ac...> - 2004年02月02日 17:07:35
>>>>> "John" == John Gill <jn...@eu...> writes:
Hi John, could you also subscribe to matplotlib-devel and CC the
messages to me (matplotlib-devel sometimes has a long lag). It would
be nice to have these discussions there for archival purposes and so
that others can offer suggestions. Hopefully, you'll have an easier
time getting sighed up there than you did on matplotlib-users.
 John> John, First the good news. I've had a good read of
 John> legend.py and now pretty much understand how it is working.
Excellent, between the 2 of us, that makes at least one person who
understands that code <wink>.
 John> Now the bad news. The way I'm thinking about these tables
 John> is that I will want to draw them below the main plot area,
 John> sort of where the xticklabels go at the moment + the area
 John> below.
But you should try and code it generally so people can place them
wherever they want right? Perhaps you should construct the table with
a list of horizontal lines and a list of vertical lines and their
respective transforms (see below). Or are you already doing this?
 John> Now I tried hacking about a table.py copy of legend.py and
 John> drawing a grid of lines in this area -- the code runs fine
 John> but I don't get a nice grid of lines :( (see snippet of code
 John> below).
 John> If I cheat and arrange for the drawing to take place within
 John> the main plot (by carefully fixing the ypos stuff below)
 John> then things work fine.
 John> I'm guessing I need to do something to let matplotlib know
 John> the extent of what I'm drawing, but I am at a loss as to
 John> what that something is.
 John> Can you point me in the right direction?
Without a complete code example, I can only guess. My guess is that
you are using the wrong transforms. Each axis instance has a
transAxis and a transData attribute you can use. When you want to
specify a coordinate in axis units (0,1), use the transAxis instance.
If you want to specify a coordinate in data units, use transData.
Eg, if you want the vertical lines (x coords) of your table to line up
with the xticks and the horizontal lines (y coords) of your table to
be in axis units (eg 10% of the axis apart), you would initialize your
line like
 ypos = 0.1 # 10% of axes height
 line = Line2D( self.dpi, self.bbox,
 xdata=(xpos, xpos), ydata=(0, ypos),
 color='k', linestyle=':',
 transx = self.axes.xaxis.transData,
 transy = self.axes.yaxis.transAxis,
 )
Make sure you turn clipping off (it appears you did for your
examples), particularly while developing.
 John> (aside: it did occur to me that one way i could cheat an
 John> nearly get what i want is to use the bar() method to draw my
 John> grid + then use the text() method to enter all the text I
 John> want in the grid...)
Cheating is usually a bad thing. I think you'll need to construct
your own text instances with the same x and y transforms you use for
your lines, eg, x coordinate in data units and y coordinate in axis
units. This will also encapsulate the table as a single instance which
will make it easier to manipulate; eg to set text properties for the
entire table.
Hope this helps, if not send me a complete example with demo script
and I can take a closer look.
JDH
From: John G. <jn...@eu...> - 2004年02月03日 11:44:34
John,
Thanks for the hints.
First I've tried subscribing to the devel list -- sourceforge is sulking
again, so no joy so far, i've cc'ed the list on this, so if it accepts
posts from non-subcribees it should get there.
I've looked a bit at the transforms stuff + things are making a bit more
sense, but I'm still unable to achieve what I'd like.
I think the basic problem is that Line2D and Rectangle are intended to
draw on the axes, whereas what I'd ideally like to do is draw outside
the axes (see the screenshot i sent originally) -- ie instead of doing
what is done with the legend and have it appear somewhere within the
axes of the plot I'd like the table of data to be outside this.
I was hoping I could do things like specify negative y-positions to draw
below the axes, but I now think I'm deluded in thinking this 'cos
matplotlib is smart and every time something gets drawn the axes are
automagically adjusted to make sure the latest lines/rectangles are
included.
I suspect I need some new sort of object to draw outside the axes - can
you confirm that is the case?
Plan B. would be to just live with putting the tables within the plot,
as per the legend, but this doesn't work too well in general 'cos the
table tends to obscure some important part of the plot.
Let me know if this is still hard to understand and I'll try and get
what I have into a state which demonstrates the problem I am running
into.
John
From: John H. <jdh...@ac...> - 2004年02月04日 06:37:08
>>>>> "John" == John Gill <jn...@eu...> writes:
 John> I was hoping I could do things like specify negative
 John> y-positions to draw below the axes, but I now think I'm
 John> deluded in thinking this 'cos matplotlib is smart and every
 John> time something gets drawn the axes are automagically
 John> adjusted to make sure the latest lines/rectangles are
 John> included.
If this is the case it appears to me that you are using the
axes.add_line command, no? That is where matplotlib does the
autoscale view limits thingie. There is nothing in the architecture
that prevents you from drawing outside the axes view limits, except
for clipping, which you can set.
I think you should have a Table class which is contained by the axes.
The Table should derive from an Artist and implement the required
_draw method, which is called with a renderer instance. This method
should forward the draw call to all the text, lines and patches
contained by the table, just as legend does.
class Table
 def _draw(self, renderer):
 for line in self._lines: line.draw(renderer)
 for t in self._texts: t.draw(renderer)
This is how Legend does it. If you set it up this way, the axes
instances won't know anything about the line instances and you can
definitely draw outside the axes bbox. If not, matplotlib.axes has
achieved consciousness and we are no longer in control <wink>. Note
that it is critical that you make the call
 self.line1.set_clip_on(False)
to allow drawing outside the axes bbox.
Here's an example table class that you can use to draw inside or
outside the axes bbox. Note there is no reason we can't do this at
the figure level, but the advantage of doing it at the axes level is
that you may want some of the lines to be in data coords, eg, the
vertical lines lining up with the xticks in the example you showed me.
It might be worth taking some time to figure out how to have figure
tables or axes tables, eg with a base class and 2 derived classes, but
for now focus on the axes table and we can generalize once you have
the nuances worked out.
class Table(Artist):
 def __init__(self, axes):
 Artist.__init__(self, axes.dpi, axes.bbox)
 self.axes = axes
 left = 0.9
 right = 1.2
 bottom = 0.9
 top = 1.5
 
 self.line1 = Line2D(
 axes.dpi, axes.bbox,
 (left, left), (bottom, top),
 transx=self.axes.xaxis.transAxis,
 transy=self.axes.yaxis.transAxis
 )
 self.line1.set_clip_on(False)
 def _draw(self, renderer):
 self.line1.draw(renderer)
You can add an add_table method to Axes, and define a list of 
 class Axes(Artis):
 def __init__(self, blah, blah):
 # ..snip the other Axes init stuff
 self._tables = [] 
 def add_table(self, table):
 self._tables.append(table)
 def _draw(self, renderer):
 # ..snip the other draw calls
 for table in self._tables:
 table.draw(renderer)
I tested my code above with this scheme and it works - it drew a
vertical blue line from inside the axes to outside.
If you have any more troubles send me some code and I'll take a look.
JDH
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /