Missed the `tree = ...` line.
Can you post a version of the above that I can copy and paste (here, or
link to a gist) to recreate the timings and look at it locally?
On Thursday, September 24, 2015 at 8:41:32 PM UTC-4, Ben Ward wrote:
>
> As an update: We have tested fetching annotations without trying to
> enforce type, and then another in which we don't. I don't understand why,
> but the one in which we don't enforce type, is faster, it is also puzzling
> for me as the one where we don't enforce type allocates memory, and yet is
> still faster:
>
> function getannotations{T}(x::Phylogeny, name::ASCIIString, ::Type{T})
> x.annotations[T][name]::T
> end
>
>
>
> function getannotations(x::Phylogeny, name::ASCIIString)
> for (k, v) in x.annotations
> if haskey(v, name)
> return(v[name])
> end
> end
> error("No such key in the phylogeny")
> end
>
>
> *julia> **@time for i in 1:10000; a = tree["Node Names", ASCIIString];*
> *end*
>
> 0.002090 seconds
>
> *julia> **@time for i in 1:10000; a = tree["Node Names"]; **end*
>
> 0.001367 seconds (10.00 k allocations: 312.500 KB)
>
>
>
>
>
>
>
> On Thursday, September 24, 2015 at 8:17:52 PM UTC+1, Ben Ward wrote:
>>
>> Hi Julia Users,
>>
>> I'm one of the Core-Devs in the BioJulia organisation, with a background
>> in evolutionary biology/genetics, and, with a few other contributors I'm
>> writing Bio.jl's Phylo submodule.
>>
>> The primary type of this submodule is the Phylogeny. Which is a composite
>> type, used to describe a model of evolution. At the very minimum it looks
>> like this:
>>
>> type PhyNode
>> children::Vector{PhyNode}
>> parent::PhyNode
>>
>> function PhyNode(children::Vector{PhyNode} = PhyNode[],
>> parent = nothing)
>> x = new()
>> if parent != nothing
>> graft!(parent, x)
>> else
>> x.parent = x
>> end
>> x.children = PhyNode[]
>> for child in children
>> graft!(x, child)
>> end
>> return x
>> end
>> end
>>
>> type Phylogeny
>> root::PhyNode
>> rooted::Bool
>> rerootable::Bool
>>
>> Phylogeny() = new(PhyNode(), false, true)
>> end
>>
>> PhyNodes are types which link to their children and to their parent -
>> they are the individual objects that form the tree structure. The Phylogeny
>> type describes the overall tree, and contains a variable pointing to a
>> PhyNode that forms the root of the tree, and determines whether the tree is
>> rooted in the phylogenetic sense, and whether the phylogeny is re-rootable.
>> So far so good. We can represent the structure of a phylogeny - a model of
>> how various species are related through history.
>>
>> Here is where I'd like comments from the julia-users, if possible: With a
>> phylogeny, often additional information is annotated to the tree, like
>> branch lengths, confidence intervals, sequences, labels, colours for
>> plotting, and so on. Well, we can do this with a Dict, and use PhyNodes as
>> keys:
>>
>> typealias NodeAnnotation{T} Dict{PhyNode, T}
>>
>> We can then store thee annotations in the Phylogeny type like this:
>> type Phylogeny{S <: AbstractString}
>> root::PhyNode
>> rooted::Bool
>> rerootable::Bool
>> annotations::Dict{S, Any}
>> end
>>
>> However, I don't like the type uncertainty of Any because if I'm correct,
>> it could propagate up through a user's code. But we will always have some
>> uncertainty, because we don't know in advance what the user might want to
>> annotate the Phylogeny with - could be anything from simple float values,
>> to other composite types.
>>
>> Am I correct that the uncertainty getting and setting such annotations,
>> would propagate through the user's code when they deal with annotations?
>> If so, we have tried to think of ways to get around this. One idea was to
>> store the NodeAnnotations in the phylogeny according to the type of their
>> values, and then provide getter and setter methods that make the return
>> type predictable from the types of the parameters passed in the method:
>>
>> type Phylogeny{S<:AbstractString}
>> root::PhyNode
>> rooted::Bool
>> rerootable::Bool
>> annotations::Dict{Type, Dict{S, NodeAnnotation{Any}}}
>> end
>>
>> function setannotation!{T}(x::Phylogeny, name::ASCIIString, ann::
>> NodeAnnotation{T})
>> if haskey(x.annotations,T)
>> x.annotations[T][name] = ann
>> else
>> x.annotations[T] = [name => ann]
>> end
>> end
>>
>> function getannotations{T}(x::Phylogeny, name::ASCIIString, ::Type{T})
>> x.annotations[T][name]::Dict{PhyNode, T}
>> end
>>
>> This seems like it works and would indeed make getting and setting more
>> type predictable, the only annoying part is that Dicts get converted:
>>
>> julia> setannotation!(tree, "Node Names", NodeAnnotation{ASCIIString}())
>> Dict{PhyNode,ASCIIString} with 0 entries
>>
>>
>> julia> tree
>> Phylogeny{ASCIIString}(PhyNode(),false,false,Dict{Type{T},Dict{
>> ASCIIString,Dict{PhyNode,Any}}}(ASCIIString=>Dict("Node Names"=>Dict{
>> PhyNode,Any}())))
>>
>> You see Dict{PhyNode, ASCIIString} got converted to Dict{PhyNode, Any}.
>>
>> If anyone has comments on this or has advice on how to prevent type
>> uncertainty propagating, please do share. How should we be approaching this?
>>
>> Many thanks,
>> Ben.
>>
>