Skip to content

Instantly share code, notes, and snippets.

@gtsambos
Created December 12, 2018 01:33
Show Gist options
  • Save gtsambos/58b625d4a953989fbde86548d9aff663 to your computer and use it in GitHub Desktop.
Save gtsambos/58b625d4a953989fbde86548d9aff663 to your computer and use it in GitHub Desktop.
test
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Import packages.\n",
"import msprime, pyslim, numpy"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"===========================\n",
"Epoch: 0 -- 5.0 generations\n",
"===========================\n",
" start end growth_rate | 0 1 \n",
" -------- -------- -------- | -------- -------- \n",
"0 | 100 100 0 | 0 0 \n",
"1 | 100 100 0 | 0 0 \n",
"\n",
"Events @ generation 5.0\n",
" - Mass migration: lineages move from 1 to 0 with probability 1.0\n",
"=============================\n",
"Epoch: 5.0 -- inf generations\n",
"=============================\n",
" start end growth_rate | 0 1 \n",
" -------- -------- -------- | -------- -------- \n",
"0 | 100 100 0 | 0 0 \n",
"1 | 100 100 0 | 0 0 \n",
"\n"
]
}
],
"source": [
"# Create a very basic msprime setup with population structure, test.\n",
"\n",
"population_configurations =[\n",
" msprime.PopulationConfiguration(\n",
" sample_size=3, initial_size=100),\n",
" msprime.PopulationConfiguration(\n",
" sample_size=3, initial_size=100)\n",
"]\n",
"\n",
"demographic_events = [\n",
" msprime.MassMigration(\n",
" time=5, source=1, destination=0, proportion=1.0)\n",
"]\n",
"\n",
"rho = 1e-4\n",
"mu = 1e-3 \n",
"\n",
"dd = msprime.DemographyDebugger(\n",
" population_configurations=population_configurations,\n",
" demographic_events=demographic_events\n",
")\n",
"dd.print_history()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Simulate with msprime.\n",
"\n",
"ts = msprime.simulate(\n",
" population_configurations=population_configurations,\n",
" demographic_events=demographic_events,\n",
" length=10,\n",
" recombination_rate=rho,\n",
" mutation_rate=mu,\n",
" random_seed=1\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 11 \n",
"┏━━┻━━┓ \n",
"┃ 10 \n",
"┃ ┏━━┻━┓ \n",
"┃ ┃ 9 \n",
"┃ ┃ ┏━┻┓ \n",
"┃ 8 ┃ ┃ \n",
"┃ ┏┻┓ ┃ ┃ \n",
"┃ ┃ ┃ ┃ 6 \n",
"┃ ┃ ┃ ┃ ┏┻┓ \n",
"2 0 1 3 4 5 \n",
"\n",
" 11 \n",
"┏━━┻━━┓ \n",
"┃ 10 \n",
"┃ ┏━┻━━┓ \n",
"┃ ┃ 9 \n",
"┃ ┃ ┏┻┓ \n",
"┃ 8 ┃ ┃ \n",
"┃ ┏━┻┓ ┃ ┃ \n",
"┃ ┃ 7 ┃ ┃ \n",
"┃ ┃ ┏┻┓ ┃ ┃ \n",
"2 0 1 5 3 4 \n",
"\n"
]
}
],
"source": [
"for tree in ts.trees():\n",
" print(tree.draw(format=\"unicode\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's now investigate the `TreeSequence` class a little further, following the tutorial in the [msprime documentation](https://msprime.readthedocs.io/en/latest/api.html#using-simulation-results).\n",
"\n",
"TreeSequence objects can be generated in `msprime` (or `SLiM`), and loaded from existing `.trees` files,`.txt` files or `TableCollection` objects. See the text for more.\n",
"\n",
"Note that TreeSequences are immutable; you can only change the data held in a particular TreeSequence indirectly, by getting the table information, editing the tables and then creating a TreeSequence with the new set of tables using `TableCollection.tree_sequence()`. Perhaps let's investigate that later.\n",
"\n",
"First, let's look at all of the sub-classes and constants contained within a TreeSequence:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['__class__',\n",
" '__delattr__',\n",
" '__dict__',\n",
" '__dir__',\n",
" '__doc__',\n",
" '__eq__',\n",
" '__format__',\n",
" '__ge__',\n",
" '__getattribute__',\n",
" '__gt__',\n",
" '__hash__',\n",
" '__init__',\n",
" '__init_subclass__',\n",
" '__le__',\n",
" '__lt__',\n",
" '__module__',\n",
" '__ne__',\n",
" '__new__',\n",
" '__reduce__',\n",
" '__reduce_ex__',\n",
" '__repr__',\n",
" '__setattr__',\n",
" '__sizeof__',\n",
" '__str__',\n",
" '__subclasshook__',\n",
" '__weakref__',\n",
" '_ll_tree_sequence',\n",
" 'breakpoints',\n",
" 'diffs',\n",
" 'dump',\n",
" 'dump_tables',\n",
" 'dump_text',\n",
" 'edge_diffs',\n",
" 'edges',\n",
" 'edgesets',\n",
" 'file_uuid',\n",
" 'first',\n",
" 'genotype_matrix',\n",
" 'get_ll_tree_sequence',\n",
" 'get_num_mutations',\n",
" 'get_num_nodes',\n",
" 'get_num_records',\n",
" 'get_num_sites',\n",
" 'get_num_trees',\n",
" 'get_pairwise_diversity',\n",
" 'get_population',\n",
" 'get_sample_size',\n",
" 'get_samples',\n",
" 'get_sequence_length',\n",
" 'get_time',\n",
" 'haplotypes',\n",
" 'individual',\n",
" 'individuals',\n",
" 'll_tree_sequence',\n",
" 'load',\n",
" 'load_tables',\n",
" 'migrations',\n",
" 'mutation',\n",
" 'mutations',\n",
" 'newick_trees',\n",
" 'node',\n",
" 'nodes',\n",
" 'num_edges',\n",
" 'num_individuals',\n",
" 'num_migrations',\n",
" 'num_mutations',\n",
" 'num_nodes',\n",
" 'num_populations',\n",
" 'num_provenances',\n",
" 'num_samples',\n",
" 'num_sites',\n",
" 'num_trees',\n",
" 'pairwise_diversity',\n",
" 'population',\n",
" 'populations',\n",
" 'provenance',\n",
" 'provenances',\n",
" 'records',\n",
" 'sample_size',\n",
" 'samples',\n",
" 'sequence_length',\n",
" 'simplify',\n",
" 'site',\n",
" 'sites',\n",
" 'tables',\n",
" 'trees',\n",
" 'variants',\n",
" 'write_vcf']"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dir(ts)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Firstly, some useful summary info about the TreeSequence:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"number of edges: 14 \n",
"\n",
"number of individuals: 0 \n",
"\n",
"number of migrations: 0 \n",
"\n",
"number of mutations: 14 \n",
"\n",
"number of nodes: 12 \n",
"\n",
"number of populations: 2 \n",
"\n",
"number of provenances: 1 \n",
"\n",
"number of samples: 6 \n",
"\n",
"number of sites: 14 \n",
"\n",
"number of trees: 2 \n",
"\n",
"sequence length: 10.0 \n",
"\n"
]
}
],
"source": [
"print(\"number of edges: \", ts.num_edges, \"\\n\")\n",
"print(\"number of individuals: \", ts.num_individuals, \"\\n\")\n",
"print(\"number of migrations: \", ts.num_migrations, \"\\n\")\n",
"print(\"number of mutations: \", ts.num_mutations, \"\\n\")\n",
"print(\"number of nodes: \", ts.num_nodes, \"\\n\")\n",
"print(\"number of populations: \", ts.num_populations, \"\\n\")\n",
"print(\"number of provenances: \", ts.num_provenances, \"\\n\")\n",
"print(\"number of samples: \", ts.num_samples, \"\\n\")\n",
"print(\"number of sites: \", ts.num_sites, \"\\n\")\n",
"print(\"number of trees: \", ts.num_trees, \"\\n\")\n",
"print(\"sequence length: \", ts.sequence_length, \"\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**NOTE!** The sequence length is NOT the number of segregating sites - it is with respect to whatever unit you specify as input into ```msprime.simulate()```."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, let's examine the TreeSequence. \n",
"\n",
"The topology of the tree indicates the relationships of each node to each other node. These can be drawn using `draw()` (although for complicated trees, this sort of screws up - see below).\n",
"\n",
"Printing the tree directly outputs a list showing all child:parent node relationships."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{0: 8, 1: 8, 2: 11, 3: 9, 4: 6, 5: 6, 6: 9, 8: 10, 9: 10, 10: 11}\n",
"{0: 8, 1: 7, 2: 11, 3: 9, 4: 9, 5: 7, 7: 8, 8: 10, 9: 10, 10: 11}\n"
]
}
],
"source": [
"for tree in ts.trees():\n",
" print(tree)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 11 \n",
"┏━━┻━━┓ \n",
"┃ 10 \n",
"┃ ┏━━┻━┓ \n",
"┃ ┃ 9 \n",
"┃ ┃ ┏━┻┓ \n",
"┃ 8 ┃ ┃ \n",
"┃ ┏┻┓ ┃ ┃ \n",
"┃ ┃ ┃ ┃ 6 \n",
"┃ ┃ ┃ ┃ ┏┻┓ \n",
"2 0 1 3 4 5 \n",
"\n",
" 11 \n",
"┏━━┻━━┓ \n",
"┃ 10 \n",
"┃ ┏━┻━━┓ \n",
"┃ ┃ 9 \n",
"┃ ┃ ┏┻┓ \n",
"┃ 8 ┃ ┃ \n",
"┃ ┏━┻┓ ┃ ┃ \n",
"┃ ┃ 7 ┃ ┃ \n",
"┃ ┃ ┏┻┓ ┃ ┃ \n",
"2 0 1 5 3 4 \n",
"\n"
]
}
],
"source": [
"for tree in ts.trees():\n",
" print(tree.draw(format=\"unicode\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Because the TreeSequence is stored compactly as an iterator object, you can't simply access the trees by subsetting the object. Each subsequent tree is built upon the information in the current tree, so they cannot be accessed out of order.\n",
"\n",
"However, it is sometimes useful to visualise a smaller part of the TreeSequence for basic sanity checks. For this purpose you can use `first()` to print just the first tree in the TreeSequence."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{0: 8, 1: 8, 2: 11, 3: 9, 4: 6, 5: 6, 6: 9, 8: 10, 9: 10, 10: 11}\n"
]
}
],
"source": [
"print(ts.first())"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 11 \n",
"┏━━┻━━┓ \n",
"┃ 10 \n",
"┃ ┏━━┻━┓ \n",
"┃ ┃ 9 \n",
"┃ ┃ ┏━┻┓ \n",
"┃ 8 ┃ ┃ \n",
"┃ ┏┻┓ ┃ ┃ \n",
"┃ ┃ ┃ ┃ 6 \n",
"┃ ┃ ┃ ┃ ┏┻┓ \n",
"2 0 1 3 4 5 \n",
"\n"
]
}
],
"source": [
"print(ts.first().draw(format=\"unicode\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A single tree in a TreeSequence is a SparseTree. This is an object of it's own type, to be considered in a separate notebook!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each of these trees depicts the genealogical history of a particular genomic interval along the simulated chromosome. To see the intervals, use `breakpoints()`. The intervals spanning each consecutive pair of coordinates in this list each have the same history with respect to the sample, corresponding to each tree in the above TreeSequence.\n",
"\n",
"Note that the breakpoints have a floating coordinate. This is because, at present msprime model throws down recombination events (and mutation events) at continuous points along the simulated chromosome, even if you specify an integer chromosome length in `msprime.simulate()` (as wel have done above). This is important to keep in mind for later, when we attempt to initialise `msprime` with a `SLiM`-generated .trees file."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n",
"8.805353552756214\n",
"10.0\n"
]
}
],
"source": [
"for pt in ts.breakpoints():\n",
" print(pt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each node in these trees corresponds to the genome of a specific ancestor at some time in the past. (See the [msprime documentation](https://msprime.readthedocs.io/en/latest/interchange.html#node-table) for more description). These can be accessed sequentially, or individually: "
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 0, 'time': 0.0, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 1}\n",
"{'id': 1, 'time': 0.0, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 1}\n",
"{'id': 2, 'time': 0.0, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 1}\n",
"{'id': 3, 'time': 0.0, 'population': 1, 'individual': -1, 'metadata': b'', 'flags': 1}\n",
"{'id': 4, 'time': 0.0, 'population': 1, 'individual': -1, 'metadata': b'', 'flags': 1}\n",
"{'id': 5, 'time': 0.0, 'population': 1, 'individual': -1, 'metadata': b'', 'flags': 1}\n",
"{'id': 6, 'time': 65.92482819029316, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}\n",
"{'id': 7, 'time': 71.57784790772325, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}\n",
"{'id': 8, 'time': 87.05704331323707, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}\n",
"{'id': 9, 'time': 125.58636700016072, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}\n",
"{'id': 10, 'time': 265.89952008528115, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}\n",
"{'id': 11, 'time': 487.9155837953282, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}\n"
]
}
],
"source": [
"for node in ts.nodes():\n",
" print(node)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'id': 6, 'time': 65.92482819029316, 'population': 0, 'individual': -1, 'metadata': b'', 'flags': 0}"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.node(6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We're often most interested in the nodes that correspond to the present-day samples whose genomes we've simulated. To see the ids corresponding to these, use ```samples()```:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 1, 2, 3, 4, 5], dtype=int32)"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.samples()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the two trees have a very similar topology.\n",
"\n",
"Call `edges()` to see each unique edge (parent:child relationship) of the TreeSequence. Each row of this output corresponds to a single edge. The parent and child nodes of the edge are listed, as well as the endpoints of the genomic interval over which the edge ranges.\n",
"\n",
"Note that shared aspects of the topologies of consecutive trees need only be recorded once. For instance, both of these trees share an edge between parent node 11 and child node 2. This is listed in a single row; the fact that this edge is a feature of the entire sequence's history is recorded by the endpoints of the interval (0,10). \n",
"\n",
"This is the main reason why TreeSequences are so efficient! "
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{left=0.000, right=8.805, parent=6, child=4}\n",
"{left=0.000, right=8.805, parent=6, child=5}\n",
"{left=8.805, right=10.000, parent=7, child=1}\n",
"{left=8.805, right=10.000, parent=7, child=5}\n",
"{left=0.000, right=10.000, parent=8, child=0}\n",
"{left=0.000, right=8.805, parent=8, child=1}\n",
"{left=8.805, right=10.000, parent=8, child=7}\n",
"{left=0.000, right=10.000, parent=9, child=3}\n",
"{left=8.805, right=10.000, parent=9, child=4}\n",
"{left=0.000, right=8.805, parent=9, child=6}\n",
"{left=0.000, right=10.000, parent=10, child=8}\n",
"{left=0.000, right=10.000, parent=10, child=9}\n",
"{left=0.000, right=10.000, parent=11, child=2}\n",
"{left=0.000, right=10.000, parent=11, child=10}\n"
]
}
],
"source": [
"for edge in ts.edges():\n",
" print(edge)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To see how to construct each tree from the previous tree, moving left-to-right, use `edge_diffs()`:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"((0.0, 8.805353552756214), [], [{left=0.000, right=8.805, parent=6, child=4}, {left=0.000, right=8.805, parent=6, child=5}, {left=0.000, right=10.000, parent=8, child=0}, {left=0.000, right=8.805, parent=8, child=1}, {left=0.000, right=10.000, parent=9, child=3}, {left=0.000, right=8.805, parent=9, child=6}, {left=0.000, right=10.000, parent=10, child=8}, {left=0.000, right=10.000, parent=10, child=9}, {left=0.000, right=10.000, parent=11, child=2}, {left=0.000, right=10.000, parent=11, child=10}]) \n",
"\n",
"((8.805353552756214, 10.0), [{left=0.000, right=8.805, parent=9, child=6}, {left=0.000, right=8.805, parent=8, child=1}, {left=0.000, right=8.805, parent=6, child=5}, {left=0.000, right=8.805, parent=6, child=4}], [{left=8.805, right=10.000, parent=7, child=1}, {left=8.805, right=10.000, parent=7, child=5}, {left=8.805, right=10.000, parent=8, child=7}, {left=8.805, right=10.000, parent=9, child=4}]) \n",
"\n"
]
}
],
"source": [
"for edge in ts.edge_diffs():\n",
" print(edge, \"\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At the first tree spanning `(0.0, 8.8)`, there is no previous tree to modify, so no edges need to be removed to construct this tree. This is why the second value of the first edge difference is `[]`, the empty tree. \n",
"\n",
"The final element in this tuple is the entire list of edges needed to construct the tree. Since this is the first tree in the sequence, every edge must be provided.\n",
"\n",
"Next, let's examine the second tuple corresponding to the second tree in this TreeSequence. This tree spans the interval `(8.8, 10.0)`, which is the first element in the tuple.\n",
"\n",
"The second element is a list of edges indicating the parts of the previous tree that must be removed to construct the current tree. As my hand-drawn diagram indicates, the edges that must be removed are those connecting the nodes 9:6, 8:1, 6:5, 6:4. \n",
"\n",
"The third element is a list of edges indicating the parts of the current tree that must be added to create it. These are the edges connecting nodes 7:1, 7:5, 8:7, 9:4. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**How to access the entire sample of simulated genotypes?** \n",
"\n",
"Simply use `genotype_matrix()`. Columns are individual haplotypes, rows are the variants. Note that only segregating sites are printed."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0, 0, 1, 0, 0, 0],\n",
" [1, 1, 0, 0, 0, 0],\n",
" [0, 1, 0, 0, 0, 0],\n",
" [1, 1, 0, 1, 1, 1],\n",
" [0, 0, 1, 0, 0, 0],\n",
" [1, 1, 0, 1, 1, 1],\n",
" [0, 1, 0, 0, 0, 0],\n",
" [0, 0, 0, 1, 1, 1],\n",
" [0, 0, 1, 0, 0, 0],\n",
" [0, 0, 1, 0, 0, 0],\n",
" [0, 1, 0, 0, 0, 0],\n",
" [1, 0, 0, 0, 0, 0],\n",
" [0, 0, 1, 0, 0, 0],\n",
" [0, 0, 1, 0, 0, 0]], dtype=uint8)"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.genotype_matrix()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At each of these sites, a mutation has occured somewhere in the tree, leading to differences in the genotypes inherited by different leaf nodes. Information about these mutations can be accessed sequentially via the `mutations()` iterator..."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 0, 'site': 0, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 0.18288280116394162, 'index': 0}\n",
"{'id': 1, 'site': 1, 'node': 8, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 0.592431970871985, 'index': 1}\n",
"{'id': 2, 'site': 2, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 0.8171439440980768, 'index': 2}\n",
"{'id': 3, 'site': 3, 'node': 10, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 2.2212454839609563, 'index': 3}\n",
"{'id': 4, 'site': 4, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 3.1551563390530646, 'index': 4}\n",
"{'id': 5, 'site': 5, 'node': 10, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 4.461345006711781, 'index': 5}\n",
"{'id': 6, 'site': 6, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 4.562516381453547, 'index': 6}\n",
"{'id': 7, 'site': 7, 'node': 9, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 5.930655167903751, 'index': 7}\n",
"{'id': 8, 'site': 8, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 6.865009246394038, 'index': 8}\n",
"{'id': 9, 'site': 9, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 7.501443123910576, 'index': 9}\n",
"{'id': 10, 'site': 10, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 7.616809090278551, 'index': 10}\n",
"{'id': 11, 'site': 11, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 7.783892354927957, 'index': 11}\n",
"{'id': 12, 'site': 12, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 8.346256734803319, 'index': 12}\n",
"{'id': 13, 'site': 13, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b'', 'position': 9.888610874768347, 'index': 13}\n"
]
}
],
"source": [
"for mut in ts.mutations():\n",
" print(mut)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... or individually via the `mutation()` command:\n",
"\n",
"** NOTE! It is a bit weird that some of the information is truncated (including the position info???)**"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 10, 'site': 10, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}\n"
]
}
],
"source": [
"print(ts.mutation(10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this toy example, the simulated dataset is quite small, so it's no big deal to access them all at once. However, if they aren't all needed at once, you can also access them sequentially using the `variants()` iterator. This can save a lot of memory. Note that other information is also recorded in `variants()`, including position, alleles, site indices and so on."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'site': {'id': 0, 'position': 0.18288280116394162, 'ancestral_state': '0', 'mutations': [{'id': 0, 'site': 0, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 1, 0, 0, 0], dtype=uint8), 'position': 0.18288280116394162, 'index': 0}\n",
"{'site': {'id': 1, 'position': 0.592431970871985, 'ancestral_state': '0', 'mutations': [{'id': 1, 'site': 1, 'node': 8, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([1, 1, 0, 0, 0, 0], dtype=uint8), 'position': 0.592431970871985, 'index': 1}\n",
"{'site': {'id': 2, 'position': 0.8171439440980768, 'ancestral_state': '0', 'mutations': [{'id': 2, 'site': 2, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 1, 0, 0, 0, 0], dtype=uint8), 'position': 0.8171439440980768, 'index': 2}\n",
"{'site': {'id': 3, 'position': 2.2212454839609563, 'ancestral_state': '0', 'mutations': [{'id': 3, 'site': 3, 'node': 10, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([1, 1, 0, 1, 1, 1], dtype=uint8), 'position': 2.2212454839609563, 'index': 3}\n",
"{'site': {'id': 4, 'position': 3.1551563390530646, 'ancestral_state': '0', 'mutations': [{'id': 4, 'site': 4, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 1, 0, 0, 0], dtype=uint8), 'position': 3.1551563390530646, 'index': 4}\n",
"{'site': {'id': 5, 'position': 4.461345006711781, 'ancestral_state': '0', 'mutations': [{'id': 5, 'site': 5, 'node': 10, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([1, 1, 0, 1, 1, 1], dtype=uint8), 'position': 4.461345006711781, 'index': 5}\n",
"{'site': {'id': 6, 'position': 4.562516381453547, 'ancestral_state': '0', 'mutations': [{'id': 6, 'site': 6, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 1, 0, 0, 0, 0], dtype=uint8), 'position': 4.562516381453547, 'index': 6}\n",
"{'site': {'id': 7, 'position': 5.930655167903751, 'ancestral_state': '0', 'mutations': [{'id': 7, 'site': 7, 'node': 9, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 0, 1, 1, 1], dtype=uint8), 'position': 5.930655167903751, 'index': 7}\n",
"{'site': {'id': 8, 'position': 6.865009246394038, 'ancestral_state': '0', 'mutations': [{'id': 8, 'site': 8, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 1, 0, 0, 0], dtype=uint8), 'position': 6.865009246394038, 'index': 8}\n",
"{'site': {'id': 9, 'position': 7.501443123910576, 'ancestral_state': '0', 'mutations': [{'id': 9, 'site': 9, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 1, 0, 0, 0], dtype=uint8), 'position': 7.501443123910576, 'index': 9}\n",
"{'site': {'id': 10, 'position': 7.616809090278551, 'ancestral_state': '0', 'mutations': [{'id': 10, 'site': 10, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 1, 0, 0, 0, 0], dtype=uint8), 'position': 7.616809090278551, 'index': 10}\n",
"{'site': {'id': 11, 'position': 7.783892354927957, 'ancestral_state': '0', 'mutations': [{'id': 11, 'site': 11, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([1, 0, 0, 0, 0, 0], dtype=uint8), 'position': 7.783892354927957, 'index': 11}\n",
"{'site': {'id': 12, 'position': 8.346256734803319, 'ancestral_state': '0', 'mutations': [{'id': 12, 'site': 12, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 1, 0, 0, 0], dtype=uint8), 'position': 8.346256734803319, 'index': 12}\n",
"{'site': {'id': 13, 'position': 9.888610874768347, 'ancestral_state': '0', 'mutations': [{'id': 13, 'site': 13, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}, 'alleles': ('0', '1'), 'genotypes': array([0, 0, 1, 0, 0, 0], dtype=uint8), 'position': 9.888610874768347, 'index': 13}\n"
]
}
],
"source": [
"for var in ts.variants():\n",
" print(var)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A similsr thing: the ```sites()``` iterator."
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 0, 'position': 0.18288280116394162, 'ancestral_state': '0', 'mutations': [{'id': 0, 'site': 0, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 1, 'position': 0.592431970871985, 'ancestral_state': '0', 'mutations': [{'id': 1, 'site': 1, 'node': 8, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 2, 'position': 0.8171439440980768, 'ancestral_state': '0', 'mutations': [{'id': 2, 'site': 2, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 3, 'position': 2.2212454839609563, 'ancestral_state': '0', 'mutations': [{'id': 3, 'site': 3, 'node': 10, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 4, 'position': 3.1551563390530646, 'ancestral_state': '0', 'mutations': [{'id': 4, 'site': 4, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 5, 'position': 4.461345006711781, 'ancestral_state': '0', 'mutations': [{'id': 5, 'site': 5, 'node': 10, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 6, 'position': 4.562516381453547, 'ancestral_state': '0', 'mutations': [{'id': 6, 'site': 6, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 7, 'position': 5.930655167903751, 'ancestral_state': '0', 'mutations': [{'id': 7, 'site': 7, 'node': 9, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 8, 'position': 6.865009246394038, 'ancestral_state': '0', 'mutations': [{'id': 8, 'site': 8, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 9, 'position': 7.501443123910576, 'ancestral_state': '0', 'mutations': [{'id': 9, 'site': 9, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 10, 'position': 7.616809090278551, 'ancestral_state': '0', 'mutations': [{'id': 10, 'site': 10, 'node': 1, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 11, 'position': 7.783892354927957, 'ancestral_state': '0', 'mutations': [{'id': 11, 'site': 11, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 12, 'position': 8.346256734803319, 'ancestral_state': '0', 'mutations': [{'id': 12, 'site': 12, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 13, 'position': 9.888610874768347, 'ancestral_state': '0', 'mutations': [{'id': 13, 'site': 13, 'node': 2, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n"
]
}
],
"source": [
"for site in ts.sites():\n",
" print(site)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Info overload! Here are just the genotypes, printed sequentially:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0 0 1 0 0 0]\n",
"[1 1 0 0 0 0]\n",
"[0 1 0 0 0 0]\n",
"[1 1 0 1 1 1]\n",
"[0 0 1 0 0 0]\n",
"[1 1 0 1 1 1]\n",
"[0 1 0 0 0 0]\n",
"[0 0 0 1 1 1]\n",
"[0 0 1 0 0 0]\n",
"[0 0 1 0 0 0]\n",
"[0 1 0 0 0 0]\n",
"[1 0 0 0 0 0]\n",
"[0 0 1 0 0 0]\n",
"[0 0 1 0 0 0]\n"
]
}
],
"source": [
"for var in ts.variants():\n",
" print(var.genotypes)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that `variants()` accesses each *site* sequentially. If you instead wish to see each simulated *sequence* sequentially, use `haplotypes()`:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"01010100000100\n",
"01110110001000\n",
"10001000110011\n",
"00010101000000\n",
"00010101000000\n",
"00010101000000\n"
]
}
],
"source": [
"for hap in ts.haplotypes():\n",
" print(hap)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is perhaps natural to think of each of these sequences as belonging to a particular individual. By default, msprime simulations do not assume this, so you will see nothing here at the moment. But we will revisit this later!"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"for ind in ts.individuals():\n",
" print(ind)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.num_individuals"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It may be useful to consider ways to summarise the diversity of this simulated sample. One way to do this is via *pairwise diversity*, the average number of mutations per genome that differ between a randomly chosen pair of samples."
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5.133333333333334"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.pairwise_diversity()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You might also want to calculate this measure for particular subsamples, such as those from particular populations. To do this, simplify specify a list of the desired samples as an argument.\n",
"\n",
"We can see that there is much more diversity within the samples from population 0 compared with our samples from population 1. This is confirmed by the pairwise diversity calculation:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8.666666666666666"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.pairwise_diversity(samples=[0,1,2])"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.pairwise_diversity(samples=[3,4,5])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If the simulated history includes divergences, you will have distinct populations represented by some of the samples. (In fact, we specified this directly with the ```population_configurations``` input to ```msprime.simulate```). Each population is stored in an iterator, ```populations()```:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 0, 'metadata': b''}\n",
"{'id': 1, 'metadata': b''}\n"
]
}
],
"source": [
"for pop in ts.populations():\n",
" print(pop)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also access the data corresponding to each population individually (though this isn't very useful at present)."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'id': 1, 'metadata': b''}"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.population(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To see which samples (and nodes) belong to a given population, specify the population id as an argument into ```samples()```:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([3, 4, 5], dtype=int32)"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts.samples(population=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some kind of inscrutable, but perhaps useful information about the software itself, is found in `provenances()`. It would be useful to see what happens once SLIM is also used to generate some data... perhaps this adds to the provenance tables? Investigate later."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 0, 'timestamp': '2018-10-03T09:30:07.151037', 'record': '{\"schema_version\": \"1.0.0\", \"software\": {\"name\": \"msprime\", \"version\": \"0.6.1\"}, \"parameters\": {\"command\": \"simulate\", \"random_seed\": 1, \"TODO\": \"add other simulation parameters\"}, \"environment\": {\"libraries\": {\"gsl\": {\"version\": \"2.2\"}, \"kastore\": {\"version\": \"0.1.0\"}}, \"os\": {\"system\": \"Darwin\", \"node\": \"6200D-132482-M.local\", \"release\": \"17.7.0\", \"version\": \"Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-4570.71.2~1/RELEASE_X86_64\", \"machine\": \"x86_64\"}, \"python\": {\"implementation\": \"CPython\", \"version\": \"3.6.6\"}}}'}\n"
]
}
],
"source": [
"for prov in ts.provenances():\n",
" print(prov)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Simplifying sequences"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Say we wanted to see the history of a subsample of our sample. The ```simplify()``` command allows us to do this, taking the samples of interest as an argument."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"ts0 = ts.simplify(samples=[1,3,5])"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 5 \n",
"┏━┻┓ \n",
"┃ 4 \n",
"┃ ┏┻┓ \n",
"0 1 2 \n",
"\n",
" 5 \n",
"┏━┻┓ \n",
"┃ 3 \n",
"┃ ┏┻┓ \n",
"1 0 2 \n",
"\n"
]
}
],
"source": [
"for tree in ts0.trees():\n",
" print(tree.draw(format=\"unicode\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the sample nodes have been relabelled: 1-->0, 3-->1, 5-->2. The internal nodes have also changed: 9-->4, 7-->3, 10-->5.\n",
"\n",
"To see this mapping, we can specify the argument ```map_nodes=True```. This returns a tuple. The first element of the tuple is the simplified TreeSequence; the second is an array showing this mapping from old nodes to new. Any of the original nodes that are not in the new sequence are represented by -1. "
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[-1 0 -1 1 -1 2 -1 3 -1 4 5 -1]\n"
]
}
],
"source": [
"ts1 = ts.simplify(samples=[1,3,5], map_nodes=True)\n",
"\n",
"print(ts1[1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that in removing some samples from the original tree, some sites that were originally segregating may now become non-segregating:"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'id': 0, 'position': 0.592431970871985, 'ancestral_state': '0', 'mutations': [{'id': 0, 'site': 0, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 1, 'position': 0.8171439440980768, 'ancestral_state': '0', 'mutations': [{'id': 1, 'site': 1, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 2, 'position': 2.2212454839609563, 'ancestral_state': '0', 'mutations': [{'id': 2, 'site': 2, 'node': 5, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 3, 'position': 4.461345006711781, 'ancestral_state': '0', 'mutations': [{'id': 3, 'site': 3, 'node': 5, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 4, 'position': 4.562516381453547, 'ancestral_state': '0', 'mutations': [{'id': 4, 'site': 4, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 5, 'position': 5.930655167903751, 'ancestral_state': '0', 'mutations': [{'id': 5, 'site': 5, 'node': 4, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n",
"{'id': 6, 'position': 7.616809090278551, 'ancestral_state': '0', 'mutations': [{'id': 6, 'site': 6, 'node': 0, 'derived_state': '1', 'parent': -1, 'metadata': b''}], 'metadata': b''}\n"
]
}
],
"source": [
"for site in ts0.sites():\n",
" print(site)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If this is not desired, you can use the ```reduce_to_site_topology=True``` option. "
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 4 \n",
"┏━┻┓ \n",
"┃ 3 \n",
"┃ ┏┻┓ \n",
"1 0 2 \n",
"\n",
"[0 1 0]\n",
"[1 0 0]\n",
"[1 0 0]\n",
"[1 0 1]\n",
"[0 1 0]\n",
"[1 0 1]\n",
"[1 0 0]\n",
"[0 0 1]\n",
"[0 1 0]\n",
"[0 1 0]\n",
"[1 0 0]\n",
"[0 1 0]\n",
"[0 1 0]\n"
]
}
],
"source": [
"ts2 = ts.simplify(samples=[1,2,3], reduce_to_site_topology=True)\n",
"\n",
"for tree in ts2.trees():\n",
" print(tree.draw(format=\"unicode\"))\n",
"\n",
"for var in ts2.variants():\n",
" print(var.genotypes)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for site in ts"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment