-
-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Implementation of Issue #4044. Added ScientificTable and ScientificCell subclasses. #4259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
We now have two implementations of this #4245 |
Looking at this PR and #4245, I like the implementation of the new |
Thanks for responding so quickly @tacaswell. The newest commit removes the ScientificTable subclass and implements a similar cell type selection mechanic as you liked. |
That's strange. Travis failed this single test: https://travis-ci.org/matplotlib/matplotlib/jobs/55347259#L6121 But running the |
That failure is just travis being flaky. That particular test is verifying that an optimization actually makes things better. If the VM chokes (due to a greedy neighbour or other VM related things) during the timing of the optimized section the test will fail. I kicked it to restart the 2.7 tests. |
Tests pass! Thanks @tacaswell |
@tacaswell We've spoken to the groups who contributed the other PRs. We've agreed that this PR provides a sound implementation that we are all happy with. The other PRs have been closed while this remains open - any updates on potentially merging this feature? Thanks! |
I should have time this weekend unless someone beats me to it. |
@tacaswell - thanks for the heads up. Cheers! |
Just a quick thought: I suggest you reconsider the names. This is really about two alternative styles, neither of which has anything to do with science. Fundamentally, a table can have horizontal and/or vertical dividers, or no dividers, or dividers in some locations and not in others. If we are never going to have options other than whether to use vertical dividers, then the styles might be "open cells" (what you are calling "Scientific" versus "closed cells". But it might be good to look farther ahead, and lay the groundwork for a more complete set of formatting options. |
@efiring Maybe the term |
Yes, with a cell-based approach, that would be better. But might it make sense to simply have one Cell class that can put lines on any or all of the sides? The general specification would be a string, e.g. 'LRBT' for all sides, 'BT' for bottom and top, etc. Aliases could be 'open' for no lines (''), 'closed' for all sides, 'horizontal' for horizontal lines ('BT'), and 'vertical' for vertical lines ('LR'). |
@efiring Wouldn't the Cell-based approach potentially be simpler in the case that the logic for each type of Cell is more complex than simply swapping the Path instance? Instead of having all of that logic inside of a single Cell class we have multiple subclasses of Cell. Do end-users interact with the Cell types directly? |
No, I expect users will interact with the table, not the Cell types. But I also expect that the next request from users will be for the ability to control the cell type on a cell-by-cell basis, not just for the table as a whole. Based on a very quick look, I think one could allow (but not require) an array of cell types, just as there is an array of text entries. Either way, the Table is drawing cells with properties. If the Cell (or a single FancyCell subclass) accepts a boxstyle property (or perhaps even a dictionary of properties), then there is no need for more and more subclasses. |
@efiring At the moment there isn't a way for users to declare exactly what kind of Cell they want at (x, y) position. It seems that for a single Table, one type of Cell is used throughout. It might be a premature optimization to give the Table class and table() factory function the ability to declare what Cell is used for what position. Maybe it's best left for some future point in time to change the API for selecting separate kinds of Cells. |
Agreed; I'm not arguing that you need to do all of that, but rather that what you do now should leave the door open as much as possible. That's why I am thinking in terms of having a minimum number of Cell subclasses (like one) instead of adding on the specialized HorizontalCell and VerticalCell (or just one of these). Once they exist, they have to be supported for quite a while. |
@efiring We've created another version of the code to work as you've suggested. Here is the new code. To provide a quick summary:
Please let us know if this is what you had in mind. |
Yes, that is what I had in mind, thank you. It looks like you might be able to factor out the validation of the edge letter string; typically, if there is a setter, then this can be used in the init to handle validation. Also, for the "closed" or "LRBT" case, maybe you need to just use the rectangle; one way or another, the polygon should be closed so that when it is drawn there is no line-end artifact at the starting/ending corner. |
I also like the new version much better (but have not read it in detail). |
@tacaswell @efiring Cleaned up some of the code created by @zairmubashar and added it to this PR. Please have a look and let us know what you think. |
|
||
""" | ||
|
||
EDGES = 'BRTL' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lower case for variable name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The EDGES variable is also called in the init() and get_path() methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I was confused, and had to amend my comment.
@efiring I've added changes to the test that you wanted and changed the default edges type to "closed". |
Thank you. @tacaswell or @WeatherGod, any more suggestions? |
@tacaswell @WeatherGod, are there any more suggestions or should we pull together some entries for the docs? |
I haven't had a good look though this yet, but from what I see, it looks like we should use this to implement the Does |
@OceanWolf we're not sure. We can look into it. But might that not be a topic for another issue/PR? |
@dkua sure thing, I only ask now to double check on the |
@OceanWolf Overhauling |
""" | ||
|
||
_edges = 'BRTL' | ||
_edge_aliases = {'open': '', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trim the extra white space please.
We much not have pep8 compliance on the rest of this file or the test would be failing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tacaswell do you mean the extra whitespace inside the _edge_aliases dictionary? I can't see any other whitespace and yeah pep8 isn't failing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect pep8 to require
_edge_aliases = {'open': '',
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tacaswell afaik spaces are allowed after colons inside of dictionaries.
Nothing against it is mentioned in the PEP 8 style guide: https://www.python.org/dev/peps/pep-0008/
And running pep8 on a minimal example and people on SO seem to confirm: http://stackoverflow.com/questions/13497793/python-alignment-of-assignments-style
I'm also at PyCon right now, I could ask people here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, learn something every day.
👍 Looks good! I like the path-based solution to drawing the edges. @efiring I think this just needs a whats_new, not an api_changes as I don't think it breaks any existing API. |
@tacaswell, good point; I was confused as to when an api_changes entry is needed. |
@tacaswell @efiring could you point us to where (or how) we would write up a whats_new entry? |
https://github.com/matplotlib/matplotlib/tree/master/doc/users/whats_new The readme in that folder as an explanation. On Sun, Apr 12, 2015 at 11:38 AM David Kua notifications@github.com wrote:
|
I think this is waiting on a what's new entry and that PEP8 issues? |
@tacaswell yes it seems just those two issues |
I am apparently confused about PEP8, so just one issue left 😄 |
@tacaswell, I could have sworn the same thing until someone called me out On Mon, Apr 13, 2015 at 9:45 PM, Thomas A Caswell notifications@github.com
|
@tacaswell I've added a What's New entry to the docs. We've also added an extra tests for the Cells themselves just for extra assurance that things work. |
ENH : Make cell edges in Table configurable Closes #4044
@dkua @zairmubashar Thanks! |
@tacaswell @efiring thank you very much. |
This implements the requested feature in issue #4044
Two subclasses,
ScientificTable
andScientificCell
, were created ofTable
andCell
respectively. An extra kwarg was added to thetable()
factory function for choosing the type ofTable
to use.The factory function and the table types were tested with the
test_table_types
test intest_table.py
. A new test image was also added. The test passes in Ubuntu 12.04 64-bit.The feature was implemented by having
ScientificCell
extendCell
with an additional methodget_path()
which simply returns a newPath
instance that doesn't draw a line when moving between the vertices that make up a vertical line.This works because
Cell.draw()
callsRectangle.draw()
which callsself.get_path()
. HoweverCell
passes intoRectangle.draw()
the argumentsself, renderer
. So theself.get_path()
call is actually callingCell
but since it doesn't have that method it uses it's super class' definition which isRectangle
. By creating the new subclass with our ownget_path()
method we can implement this feature while following the same logic.