statnet / ndtv

ndtv: Network Dynamic Temporal Visualizations in R
https://cran.r-project.org/web/packages/ndtv/index.html
46 stars 5 forks source link

render.d3movie errors on empty slice with vertex.cex specified #24

Closed skyebend closed 6 years ago

skyebend commented 7 years ago

michael writes

Dear Mr. Skye Bender-deMoll,

I might have found a bug in the ndtv package in the render.d3movie procedure: if one chooses the interval and aggregate.dur parameter values in a way that results in an empty network slice AND in addition provides e.g. vertex.cex = 'mycex, then the rendering process fails at the "empty" slice with the error message: Attribute 'vertex.cex' had illegal missing values for vertex.cex or was not present in plot.network.default.

However, if one wraps the cachePlotValues call inside render.d3movie with a check for network.size>0, everything works fine:

Bildschirmfoto 2016-08-26 um 14.49.05.png This may not be the right channel for bug reports, and even may not be the best fix for the bug, but I thought I let you know...

All the best, Michael

skyebend commented 7 years ago

example posted in http://stackoverflow.com/questions/39295734/how-can-i-determine-robust-slice-parameters-for-dynamic-network-renderings-in-r

skyebend commented 7 years ago

a minimal example:

# create a network that will always have zero vertices
test<-network.initialize(0)
activate.vertices(test)
# define a dynamic vertex attribute
activate.vertex.attribute(test,'foo',1,onset=0,terminus=1)

# works correctly in render.animation because it knows to skip processing
# attributes for an 'empty' network
render.animation(test,vertex.cex='foo')

# gives error because doesn't know how to deal with missing attributes
render.d3movie(test,vertex.cex='foo')

Calculating layout for network slice from time  0 to 1
caching 10 properties for slice 0
Error in plotArgs.network(x = slice, argName = arg, argValue = dataVals) : 
  Attribute 'foo' had illegal missing values for vertex.cex or was not present in plot.network.default.
In addition: There were 14 warnings (use warnings() to see them)
nextensible commented 7 years ago

I have just checked, whether or not the code from the bugfix branch eliminates the errors reported in http://stackoverflow.com/questions/39295734/how-can-i-determine-robust-slice-parameters-for-dynamic-network-renderings-in-r/39298836#39298836

It turns out, that while the first error ("Attribute 'vertex.sides' had illegal missing values...", which is raised when one "activates" the first version of the slice.par parameter list) seems to be solved now, the second error ("Attribute 'weight' had illegal missing values for edge.lwd...", which is raised when one "activates" the second version of the slice.par parameter list) is still showing up.

sbellan61 commented 6 years ago

I'm having the same problem noted by @nextensible regarding edge.lwd errors (but not edge.col for whatever reason) for frames when the network has no edges.

this is using ndtv_0.10.0 from CRAN

sbellan61 commented 6 years ago

it actually looks like there's code written to solve this problem in the dev version of this repo (statnet/ndtv). However, I cannot get this to install > install_github('statnet/ndtv') Downloading GitHub repo statnet/ndtv@master from URL https://api.github.com/repos/statnet/ndtv/zipball/master Installation failed: Does not appear to be an R package (no DESCRIPTION) ideas?

smjenness commented 6 years ago

Try this (R package itself is in a subdirectory of the repo):

devtools::install_github("statnet/ndtv", subdir = "ndtv/")
sbellan61 commented 6 years ago

thanks @smjenness . I'm still having a related bug with ndtv 0.12. The code only breaks when two criteria are met:

  1. edge.color is specified and used in render.d3movie
  2. there are periods when there are vertices but no edges.

The error it gives is

Error in col2rgb(x, alpha = TRUE) : invalid color name 'edge.col'

Reproducible code:

wheel <- network.initialize(10)
add.edges.active(wheel,tail=1:9,head=c(2:9,1),onset=1:9, terminus=11)
add.edges.active(wheel,tail=10,head=c(1:9),onset=10, terminus=12)
espells <- as.data.table(get.edge.activity(wheel, as.spellList=T))
espells <- rbind(espells[,.(id=head, onset, terminus)], espells[,.(id=tail, onset, terminus)])
vspells <- espells[,.(onset=min(onset), terminus=Inf), id]
vspells[id==1, onset:=-5] ## make 1st vertex appear before any edges
activate.vertices(wheel, onset=vspells[,onset], terminus=vspells[,terminus], v=vspells[,id])
get.vertex.activity(wheel, as.spellList = T)
get.edge.activity(wheel, as.spellList = T)
staticCoords<-data.table(network.layout.kamadakawai(wheel,layout.par = list()))
names(staticCoords) <- c('x','y')
activate.vertex.attribute(wheel,'x',staticCoords$x,onset=-Inf,terminus=Inf)
activate.vertex.attribute(wheel,'y',staticCoords$y,onset=-Inf,terminus=Inf)
activate.edge.attribute(wheel, 'edge.lwd', 1, onset = -Inf, terminus=5) ## this line breaks ndtv0.10, but not ndtv0.12
activate.edge.attribute(wheel, 'edge.lwd', 5, onset = 5, terminus=Inf) ## this line breaks ndtv0.10, but not ndtv0.12

##Either of below 2 lines activating an edge.col cause an error but
##only if there are time periods during which there are no edges.
activate.edge.attribute(wheel, 'edge.col', 'orange', ## this line breaks ndtv0.12 but not ndtv0.10
                        onset=espells[,onset], terminus=espells[,terminus])#, v=espells[,id])
# activate.edge.attribute(wheel, 'edge.col', 'orange') ## this line only breaks ndtv0.12 but not ndtv0.10
## for(yy in slice.par$start:slice.par$end) print(get.edge.attribute.active(wheel, 'edge.col', onset = yy, terminus=yy, rule='latest'))

slice.par <- list(start=1, ## edge.col code above breaks if start is < min(espells$onset) = 1
                  end=13,  ## or if end > max(espells$terminus) = 12
                  interval=1, aggregate.dur=1, rule='latest') 
compute.animation(wheel,animation.mode='useAttribute', slice.par = slice.par, verbose=F) 

render.d3movie(wheel,render.par=list(tween.frames=1),
               vertex.col='blue', vertex.lwd=8, vertex.border='black',
               edge.lwd = 'edge.lwd',
               edge.col='edge.col',
               launchBrowser=T, d3.options=list(animationDuration=400*slice.par$interval, animateOnLoad=T, debugFrameInfo=F))
skyebend commented 6 years ago

hmm, looks like the fix may have introduced another error?

simpler code to reproduce (or throw a related error)

test<-network.initialize(2)
add.edges.active(test,1,2,onset=0,terminus=1)
activate.edge.attribute(test,'edge.col','blue',onset = 0,terminus=1)
render.d3movie(test,edge.col='edge.col')

this gives me

No slice.par found, using
slice parameters:
  start:0
  end:1
  interval:1
  aggregate.dur:1
  rule:latest

Calculating layout for network slice from time  0 to 1
Calculating layout for network slice from time  1 to 2
caching 10 properties for slice 0
caching 10 properties for slice 1
Error in col2rgb(x, alpha = TRUE) : invalid color name 'edge.col'
> traceback()
4: col2rgb(x, alpha = TRUE)
3: col2rgbaString(dataVals)
2: cachePlotValues(slice, render, plot_args, onset = starts[s], 
       terminus = ends[s], vertices = which(activev), edges = activeE)
1: render.d3movie(test, edge.col = "edge.col")

I assume this must have something to do with no edge attribute being defined if no edges exist, but I'll need to dig into it more