Skip to content
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

plot rescales and normalizes graph even if it has vertex x and y attributes #1492

Open
DOSull opened this issue Sep 6, 2024 · 2 comments
Open
Assignees

Comments

@DOSull
Copy link

DOSull commented Sep 6, 2024

What happens, and what did you expect instead?

I expect the graph drawing to be based on the x and y attributes of the vertices. The documentation for layout_nicely says

The current implementation works like this:

  1. If the graph has a graph attribute called ‘layout’, then this is used. If this attribute is an R function, then it is called, with the graph and any other extra arguments.
  2. Otherwise, if the graph has vertex attributes called ‘x’ and ‘y’, then these are used as coordinates. If the graph has an additional ‘z’ vertex attribute, that is also used.

When I force xlim and ylim to the range of those attributes, I get what I would expect by default, based on the documentation. There's a post in the forum where I asked about this, and the rescale = TRUE suggestion was made.

I think the issue is with the line of code where xlim = c(-1, 1) ylim = c(-1, 1) is imposed.

To reproduce

library(igraph)
n <- 11
a <- seq(0, 2 * pi, length.out = n + 1)[-1]
x <- 5 * cos(a)
y <- 3 * sin(a)
L <- matrix(c(x, y), ncol = 2)

G <- make_full_graph(n) |> 
  set_vertex_attr("x", value = x) |>
  set_vertex_attr("y", value = y)

par(mfrow = c(1, 3))
plot(G, layout = layout_nicely(G), axes = TRUE)
plot(G, layout = L, rescale=FALSE, axes = TRUE)
plot(G, xlim = range(V(G)$x), ylim = range(V(G)$y), 
     rescale = FALSE, asp = 1, axes = TRUE)

Created on 2024-09-08 with [reprex v2.1.1](https://reprex.tidyverse.org/)

image
To be clear, the third panel is what I expect.

System information

I don't think any of this is relevant, but for completeness:

> version
platform       aarch64-apple-darwin20      
arch           aarch64                     
os             darwin20                    
system         aarch64, darwin20           
status                                     
major          4                           
minor          3.3                         
year           2024                        
month          02                          
day            29                          
svn rev        86002                       
language       R                           
version.string R version 4.3.3 (2024-02-29)
nickname       Angel Food Cake

All packages updated today, and igraph at version 2.0.3

@krlmlr
Copy link
Contributor

krlmlr commented Sep 12, 2024

Thanks. I see, even without the asp argument:

options(conflicts.policy = list(warn = FALSE))
library(igraph)

n <- 11
a <- seq(0, 2 * pi, length.out = n + 1)[-1]
x <- 5 * cos(a)
y <- 3 * sin(a)
L <- matrix(c(x, y), ncol = 2)

G <- make_full_graph(n) |>
  set_vertex_attr("x", value = x) |>
  set_vertex_attr("y", value = y)

plot(G, layout = layout_nicely(G), axes = TRUE)

plot(G, layout = L, rescale = FALSE, axes = TRUE)

plot(G, xlim = range(V(G)$x), ylim = range(V(G)$y), rescale = FALSE, axes = TRUE)

Created on 2024-09-12 with reprex v2.1.0

I'm confused why the first two plots keep the aspect ratio, but the third plot doesn't. I agree that we could do xlim = NULL, ylim = NULL in the formals and use c(-1, 1) for rescale = FALSE and whatever is the best default for rescale = TRUE .

Tidyverse design guide re NULL defaults: https://design.tidyverse.org/defaults-short-and-sweet.html#null-default

@DOSull
Copy link
Author

DOSull commented Sep 12, 2024

I am in the habit when plotting geographical data (which is eventually the aim here) to include asp = 1 in plot options as usually you want geographic coordinates to be treated as equal in the two dimensions, which is why it is in my code example. Perhaps plot.igraph defaulting to asp = 1 has something to do with this line in the plot.R code:

asp <- params("plot", "asp")

but that's way too deep in the weeds of how igraph handles parameters and their defaults for me to have any certainty about that suggestion. But, e.g., I get

> igraph:::i.parse.plot.params(G, list())("plot", "asp")
[1] 1

which suggests that the plot function is setting asp to a default value of 1.

But really someone who knows how these internal workings of igraphwork (which might be you @krlmlr!) and especially understands how they are intended to work should comment.

In any case, there's a whole chunk of the code (starting at line 100) which is similar in format to above.

To be clear, I am totally guessing here. I only happened on the igraph:::i.etc. line above via this fairly random code snippet so I am way above my pay grade and outside my comfort zone here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants