<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Parsing and drawing networks/admixture
Network inference, or the inference of admixture events on a phylogenetic tree, is becoming increasingly common in evolutionary biology. Toytree provides some tools for parsing and drawing networks, with aim of supporting the analysis of networks inferred by tools like SNAQ, or to describe hypotheses for coalescent simulations in tools like ipcoal.
In terms of how networks are drawn in toytree, we take the approach of assuming that a primary tree exists, which is drawn like a normal toytree, but with minor edges added to the tree as admixture edges.
Step1:  Quick example
The goal is to provide a simple, clear, and customizable option for drawing admixture edges on a tree. The simplest method is to provide a (source, destination) tuple to the admixture_edges argument in draw. Source in this context should be viewed backwards in time. The default style of drawing admixture edges in toytree tries to make the direction of introgression explicity by showing the inheritance of admixture towards the tips that inherit the introgressed alleles.
Multiple tuples can be provided to draw multiple admixture edges. The source and destination positions can be described either using node idx labels, or a list of tip names descendant from a node (preferred method since it is not affected by re-rooting the tree). Examples
Step2:  Styling admixture edges
The tuple argument to admixture_edges should be a tuple with up to five elements in it. Only the first two are required (source, dest), and any additional elements are used to add style options. 
Source
Destination
Admixture timing 
Admix edge style dictionary
Label
Step3:  Admixture timing
The third element is the admixture timing. This can be either a single float value (e.g., 0.5) or a tuple of float values (e.g., (0.2, 0.5)). These values describe the proportion of the length of an edge from tip toward the root. If a single value is used it will be the proportion of the shared edge (if one exists).
Step4:  Admixture edge style
You can style edges using CSS stroke style options.
Step5:  Label
The label is automatically placed near the admixture edge.
Step6:  Parsing SNAQ newick format
The hybrid newick format below contains the hybrid node "#H7". Toytree can parse this format using toytree.utils.parse_network() which returns the major tree as a ToyTree object and the admixture drawing information as a tuple.
Step7:  Works with re-rooting
The direction of introgression, E->A forward in time, is still preserved after re-rooting the tree.
Step8:  Muliple admixture arguments
You can provide multiple admixture edge tuples as a list. If no style argument is provided then they are automatically cycled through sequential color palette like in the example below. Or, the next example you can provide explicity styles, including low opacity to overlay many edges as a way of showing variation among many analyses.
Step9:  Parsing networks extended
If you want to see the actual placement of the hybrid nodes in a network you can parse the newick string with the argument disconnect=False, which will leave the hybrid nodes in the tree with 'name' labels indicating their connections. For example, in the network below you can see nodes labeled H7 that connect E to the ancestor of A.
<ASSISTANT_TASK:>
Python Code:
import toytree
Explanation: Parsing and drawing networks/admixture
Network inference, or the inference of admixture events on a phylogenetic tree, is becoming increasingly common in evolutionary biology. Toytree provides some tools for parsing and drawing networks, with aim of supporting the analysis of networks inferred by tools like SNAQ, or to describe hypotheses for coalescent simulations in tools like ipcoal.
In terms of how networks are drawn in toytree, we take the approach of assuming that a primary tree exists, which is drawn like a normal toytree, but with minor edges added to the tree as admixture edges.
End of explanation
# get a random tree with 10 tips
tree1 = toytree.rtree.unittree(ntips=10, seed=123)
# draw tree with admixture from node 2 to 3
tree1.draw(ts='s', admixture_edges=(2, 3));
# draw tree with admixture from tip r2 to ancestor of r4,r5
tree1.draw(ts='s', admixture_edges=('r2', ['r4', 'r5']));
Explanation: Quick example
The goal is to provide a simple, clear, and customizable option for drawing admixture edges on a tree. The simplest method is to provide a (source, destination) tuple to the admixture_edges argument in draw. Source in this context should be viewed backwards in time. The default style of drawing admixture edges in toytree tries to make the direction of introgression explicity by showing the inheritance of admixture towards the tips that inherit the introgressed alleles.
Multiple tuples can be provided to draw multiple admixture edges. The source and destination positions can be described either using node idx labels, or a list of tip names descendant from a node (preferred method since it is not affected by re-rooting the tree). Examples:
End of explanation
# draw tree with admixture from tip r2 to ancestor of r4,r5
tree1.draw(
    ts='c', 
    tip_labels=True,
    admixture_edges=[
        ('r2', 'r4', 0.5, {'stroke': 'blue', 'stroke-opacity': 0.3}, "0.32")
    ],
);
Explanation: Styling admixture edges
The tuple argument to admixture_edges should be a tuple with up to five elements in it. Only the first two are required (source, dest), and any additional elements are used to add style options. 
Source
Destination
Admixture timing 
Admix edge style dictionary
Label
End of explanation
# draw admixture at 0.5 height of the shared edge (default option)
tree1.draw(ts='c', tip_labels=True, admixture_edges=(2, 3, 0.5));
# draw admixture at 0.5 height of each edge separately
tree1.draw(ts='c', tip_labels=True, admixture_edges=(2, 3, (0.5, 0.5)));
# draw admixture at 0.2 and 0.8 heights, respectively
tree1.draw(ts='c', tip_labels=True, admixture_edges=(2, 3, (0.2, 0.8)));
# draw admixture between edges that do not overlap in time
tree1.draw(ts='c', tip_labels=True, admixture_edges=(1, 12, 0.5));
Explanation: Admixture timing
The third element is the admixture timing. This can be either a single float value (e.g., 0.5) or a tuple of float values (e.g., (0.2, 0.5)). These values describe the proportion of the length of an edge from tip toward the root. If a single value is used it will be the proportion of the shared edge (if one exists).
End of explanation
# draw admixture at 0.5 height of the shared edge (default option)
style = {'stroke': 'orange', 'stroke-width': 10, 'stroke-opacity': 0.4}
tree1.draw(ts='c', tip_labels=True, admixture_edges=(2, 3, 0.5, style));
Explanation: Admixture edge style
You can style edges using CSS stroke style options.
End of explanation
# draw admixture at 0.5 height of the shared edge (default option)
tree1.draw(ts='c', tip_labels=True, admixture_edges=(2, 3, 0.5, {}, "admixture"));
Explanation: Label
The label is automatically placed near the admixture edge.
End of explanation
# the example SNAQ network-1
hnewick = "(C,D,((O,(E,#H7:::0.196):0.314):0.664,(B,((A1,A2))#H7:::0.804):10.0):10.0);"
# parse tree and admixture dict
tree, admix = toytree.utils.parse_network(hnewick)
# the admix dictionary has key,val pairs where val is an admix drawing tuple
admix
# draw tree with tuple arg from admix dictionary 
tree.draw(ts='s', admixture_edges=admix.values());
Explanation: Parsing SNAQ newick format
The hybrid newick format below contains the hybrid node "#H7". Toytree can parse this format using toytree.utils.parse_network() which returns the major tree as a ToyTree object and the admixture drawing information as a tuple.
End of explanation
tree.root(wildcard="A").draw(ts='s', admixture_edges=admix.values());
Explanation: Works with re-rooting
The direction of introgression, E->A forward in time, is still preserved after re-rooting the tree.
End of explanation
# draw tree with admixture from tip r2 to ancestor of r4,r5
tree1.draw(
    ts='c', 
    tip_labels=True,
    admixture_edges=[
        (0, 2), (3, 4), (6, 7)
    ]
);
import numpy as np
# generate list of 100 admixture tuples w/ random timing
admix = []
for i in range(100):
    src = 2
    dest = 3
    time = np.random.normal(0.5, 0.2)
    style = {'stroke': 'blue', 'stroke-opacity': 0.01}
    tup = (src, dest, time, style)
    admix.append(tup)
# draw tree with admixture from tip r2 to ancestor of r4,r5
tree1.draw(
    ts='c', 
    tip_labels=True,
    admixture_edges=admix
);
Explanation: Muliple admixture arguments
You can provide multiple admixture edge tuples as a list. If no style argument is provided then they are automatically cycled through sequential color palette like in the example below. Or, the next example you can provide explicity styles, including low opacity to overlay many edges as a way of showing variation among many analyses.
End of explanation
hnewick = "(C,D,((O,(E,#H7:::0.196):0.314):0.664,(B,((A1,A2))#H7:::0.804):10.0):10.0);"
net, admix = toytree.utils.parse_network(hnewick, disconnect=False)
net.draw(ts='s', node_labels="name");
Explanation: Parsing networks extended
If you want to see the actual placement of the hybrid nodes in a network you can parse the newick string with the argument disconnect=False, which will leave the hybrid nodes in the tree with 'name' labels indicating their connections. For example, in the network below you can see nodes labeled H7 that connect E to the ancestor of A.
End of explanation
<END_TASK>