-
-
Notifications
You must be signed in to change notification settings - Fork 28
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
[WIP] Non-Working Example for custom shapes #138
Conversation
This is fantastic! Sorry that I didn't get to this earlier, I have been quite busy lately. I think that I understand the problem now. Basically, the A way to fix the problem that you are seeing is to put the code: plotattributes[:markershape] = :none somewhere in the Anyway, I am quite excited to get this feature into the repo! Let me know if you have any questions and I will try to respond in a reasonable amount of time. |
Thank you, that solved the problem. How would you propose do document the custom nodeshapes? Additionally, I have added a test Function. Its a simple one, doesn't do much. Do you have any further suggestions on improving the work? |
You would need to make a PR to to PlotDocs repo. The relevant function is The function generates the table that you see here:
I like it! With the test function that you have created, you also need to add a test to the file Also, it seems that I slightly mislead you with the ]test GraphRecipes then the package manager should run the tests for your local development branch of GraphRecipes.jl.
I have some minor comments on the code itself, but at a high level, I think that this is fantastic. |
I have added the test and everything appears to be running, thank you for your help 👍 Could you comment on your suggestions to the code itself? I would be happy to learn and make the changes, squish the commits and change it into a final pull request? :) |
I have made some minor comments on the relevant lines. Overall, the code is really good and it looks like you have a pretty solid understanding of Julia/package development.
Don't worry about squishing/rebasing/anything else like that. There is a button that I can press that automatically squishes commits at the same time as merging. |
I... can't find them. They should show up either when I click on 'Files Changed' or 'Commits' in this pull request, right?
Okay, good to know. |
src/graphs.jl
Outdated
@@ -487,6 +487,9 @@ more details. | |||
nodeheight = (yextent[2] - yextent[1]) | |||
push!(node_vec_vec_xy, partialellipse(0, 2π, [x[i], y[i]], | |||
80, nodewidth/2, nodeheight/2)) | |||
elseif applicable(nodeshape[node_number], x[i], y[i], 0., 0.) | |||
nodeheight = (yextent[2] - yextent[1]) | |||
push!(node_vec_vec_xy, nodeshape[node_number](x[i], y[i], nodewidth/2, nodeheight/2)) | |||
else | |||
error("Unknown nodeshape: $(nodeshape[node_number]). Choose from :circle, ellipse, :hexagon, :rect or :rectangle.") |
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.
We should probably add something to this error message. Something like: ... Choose from :circle, ellipse, :hexagon, :rect, :rectangle or a custom shape. Custom shapes can be passed as a function customshape such that customshape(x, y, nodeheight, nodewidth) -> nodeperimeter. nodeperimeter must be an array of 2-tuples, where each tuple is a corner of your custom shape, centered at (x, y) and with height nodeheight, width nodewidth.
Additionally, it would be nice to add this feature to the documentation, although that is another PR.
src/graphs.jl
Outdated
@@ -355,6 +355,11 @@ more details. | |||
plotattributes[markerproperty] = nodeproperty | |||
end | |||
|
|||
# Remove the markershapes from the dictionary to allow for nodeshapes not | |||
# compatible with the shapes of plotting ( Custom nodeshape functions don't | |||
# work without this line) |
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 don't agree with this comment.
The nodeshape is placed into plotattributes[:markershape]
at line 355:
Line 355 in 7210d36
plotattributes[markerproperty] = nodeproperty |
However, if
plotattributes[:markershape]
is a function (or a symbol that the backend doesn't recognize), then the backend will fail to create the marker series even though we ultimately create our own marker series later on in the recipe.
Ultimately, the whole processing of the attributes that I did from lines 337-356 was a bit of a cludge. I think that the code there is ultimately what has generated the whole confusion.
I would recommend that you add the following to line 357;
# If we pass a value of plotattributes[:markershape] that the backend does not
# recognize, then the backend will throw an error. The error is thrown despite the
# fact that we override the default behavior.
if nodeshape isa Function
plotattributes[:markershape] = :circle
end
The conditional is not strictly necessary, but I think it helps to show that we are only changing the disctionary when plotattributes[:markershape]
is something that the backend does not recognize.
Feel free to alter the comment a little to make it easier to understand/add your own flare.
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 still don't agree with this comment. In particular, I don't understand the phrase "nodeshapes not compatible with the shapes of plotting". The phrase "shapes of plotting" does have a very sentimental/artistic flare, however, is not really specific enough for this context. Rather than "shapes of plotting", I think that you should say "symbols that the backend will recognize as a valid value of plotattributes[:markershape]".
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.
My main intention with the comment was to keep the knowledge why this special case had to be introduced. Your code and comment capture that much better. I just added a line to make clarify that the lines where introduced to allow custom nodeshapes.
I changed the code to match yours, the tests then suggested some further changes.
test/functions.jl
Outdated
function custom_nodeshapes() | ||
function shapy(x_i,y_i, s) | ||
out = Tuple{Float64, Float64}[(-0.5,0),(0,-0.5),(0.5,0),(0,0.5)] | ||
map(out) do t |
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.
There should be four spaces of indentation.
Since people might look at these tests for documentation, it might be nice to add a few different styles so that people can choose a style that they like. The style that I would use (and that I think that you should add to one of the functions) would be:
[(x_i + 0.5s*dx, y_i + 0.5s*dy) for (dx, dy) in [(1,1),(-1,1),(-1,-1),(1,-1)]]
It really is a matter of preference, although it is always nice to cater to all types. You also might want to check that my code returns the right shape. I am more just trying to give you the rough idea here, rather than the exact code
test/functions.jl
Outdated
end | ||
function shapy_wh(x_i,y_i, h, w) | ||
out = Tuple{Float64, Float64}[(-0.5,0),(0,-0.5),(0.5,0),(0,0.5)] | ||
map(out) do t |
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.
Same formatting issue
test/functions.jl
Outdated
@@ -141,6 +141,38 @@ function julia_dict_tree() | |||
plot(TreePlot(d), method=:tree, fontsize=10, nodeshape=:ellipse, size=(1000, 1000)) | |||
end | |||
|
|||
function custom_nodeshapes() | |||
function shapy(x_i,y_i, s) |
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.
Inconsistent whitespace conventions. I also like to have no spaces after a comma, however, the convention for the JuliaPlots orginisation is to have whitespace after commas, so shapy(x_i, y_i, s)
. Same for shap_wh
below
I forgot to click the 'submit review' button! I swear that is a new feature, because I have never seen it before. Sorry about that! |
Thanks for going through all of the suggestions 😄 Also, thanks for making the condition for changing I notice that you have a file |
Ah, it was a file from the old test. I removed it. |
The test failure on julia nightly looks unrelated. Thanks so much! |
Following the discussion in #136 I set up a simple extension to allow for custom shapes. I follow the proposal from @JackDevine to use a function taking position and nodewidth/height as input parameters. An example function would look like this:
However, this approach doesn't work. There is an error
(Which appears only when I try to use the new customshape function)
However, I don't find the position in the source code where the shapes are drawn. (Or given to Plots.jl to be drawn)
As far as I can deduce it from the error, nodeshapes are given to markershape. Does this happen implicitly by the Recipe Macros?