subset.neuron() doesn't work inside nmapply()
kjheinz opened this issue · comments
I commonly use subset.neuron()
inside nmapply()
in order to apply the same operation to all members of a neuronlist, but following a recent update this no longer seems to work (I am on nat version 1.9.1.9000).
Example:
y5 = read.neurons.catmaid("annotation:NAMK_putative_PAM-y5_RIGHT")
y5.axon.nodes = nlapply(y5, function(x) distal_to(x, node.pointno = x$tags$KJH_dend_cut))
y5.SMP = nmapply(subset, y5, y5.axon.nodes, invert=T)
is the code I would have used to subset a group of neurons in the past, but throws the following error:
Error in eval(e, x$d, parent.frame()) : object 'dots' not found
I am able to achieve the result I need with the following workaround:
for (i in 1:length(y5)){
y5.SMP = c(y5.SMP, neuronlist(subset(y5[[i]], y5.axon.nodes[[i]], invert=T)))
}
Hi @kjheinz, thanks a lot for the report. This is indeed a change of behaviour. It actually happens specifically because I have given nmapply a progress bar which introduces an extra wrapper function. See 6a76320.
subset.neuron
and friends are actually rather special in their use of non-standard evaluation to allow you to use columns inside the neuron object $d
data.frame as part of the subset specification. It will be difficult (but not impossible) to reenable the behaviour you were used to.
Nevertheless, there are other better ways to achieve what you set out to do. I give some examples below starting with your workaround, which does not quite achieve the same result as your original code (missing names and attached metadata data.frame).
y5.SMP=neuronlist()
for (i in 1:length(y5)){
y5.SMP = c(y5.SMP, neuronlist(subset(y5[[i]], y5.axon.nodes[[i]], invert=T)))
}
y5.SMP.2 = nlapply(y5, function(x) {
axon.nodes <- distal_to(x, node.pointno = x$tags$KJH_dend_cut)
prune_vertices(x, axon.nodes)
})
> all.equal(y5.SMP, y5.SMP.2)
[1] "names for current but not for target"
[2] "Attributes: < Length mismatch: comparison on first 1 components >"
y5.SMP.3 = nmapply(prune_vertices, y5, y5.axon.nodes)
> all.equal(y5.SMP.3, y5.SMP.2)
[1] TRUE
y5.SMP.4 = nlapply(y5, function(x) {
axon.nodes <- distal_to(x, node.pointno = x$tags$KJH_dend_cut)
subset(x, axon.nodes, invert=TRUE)
})
> all.equal(y5.SMP.4, y5.SMP.2)
[1] TRUE
Basically you can either use prune_vertices
inside nmapply
or apply a function which both calculates the axonal nodes and uses them subset the neuron (using subset
or prune_vertices
).
Thanks @jefferis ! Your final suggestion is particularly intuitive to me, and seems very obvious now that you've pointed it out. I think I originally devised my approach when I was still finding my feet with nat and co, and I've copied it ever since. Thanks for alerting me to these better approaches!
Have decided not to try and fix this as workarounds are better style.