{
"info": {
"author": "Ad115",
"author_email": "a.garcia230395@gmail.com",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Scientific/Engineering :: Bio-Informatics",
"Topic :: Scientific/Engineering :: Medical Science Apps."
],
"description": "\nPhylogeny\n=========\n\n.. image:: https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg\n :target: https://saythanks.io/to/Ad115\n\nAn exploration on phylogenetic reconstruction algorithms.\n\nIn biological evolution one deals with entities that evolve in time.\nUsually these entities can be represented by strings and the evolution\nof these entities corresponds to changes in the corresponding string. For\nexample: \n\n- An organism may be represented by it's DNA sequence, \n- or by a list of characteristics it has \n- A protein can be represented by it's nucleotide sequence, \n- or by it's sequence of aminoacids.\n\nAlthough the current package was developed with the above examples in\nmind, one can think of other similar cases when it would be useful.\n\nThe algorithms are based, in part, by the ones found in the books:\n\n- **Algorithms on Strings, Trees, and Sequences.** by Dan Gusfield\n- **Computational Phylogenetics. An introduction to designing methods\n for phylogeny estimation.** by Tandy Warnow\n\nMeta\n====\n\nAuthor: `Ad115 `__ -\n`Github `__ \u2013 a.garcia230395@gmail.com\n\nDistributed under the MIT license. See LICENSE for more information.\n\nContributing\n============\n\n- Check for open issues or open a fresh issue to start a discussion\n around a feature idea or a bug.\n- Fork the repository on GitHub to start making your changes to a\n feature branch, derived from the master branch.\n- Write a test which shows that the bug was fixed or that the feature\n works as expected.\n- Send a pull request and bug the maintainer until it gets merged and\n published.\n\nTutorial\n========\n\nInstalation\n-----------\n\nYou can install the package from PyPI::\n\n $ pip install phylogeny\n\n\nTrees, sequences and distance matrices\n--------------------------------------\n\nThe main objects we consider are sequences, trees and matrices.\n\nAs mentioned before, the entities, represented as sequences, evolve\nforming trees. At every point of the evolutive process, we can have\ndefine a 'distance matrix', whose entries are the distance between\nsequences (a measure of their dissimilarity).\n\nIn the phylogeny reconstruction problem, we generally start with a set\nof sequences that evolved from a common ancestor, or their pairwise\ndistance matrix, and the task is to infer, with the help of certain\nmodel assumptions, the tree that generated the evolutionary process.\n\nThe Cavender-Farris-Neyman model\n--------------------------------\n\nGiven the nature of the reconstruction problem, an evolution model is\nthe guiding hand behind the inference process. The resulting tree\nchanges depending on the assumptions of the model.\n\nA good model to study reconstruction algorithms is the\nCavender-Farris-Neymann (CFN) model, that consists of a random tree with\nprobabilities *p(e)* associated to every edge *e* of the tree. Under the CFN\nmodel, every character of the sequence or 'trait' evolves down the tree\nchanging state on every edge according to the edge probability.\n\nThe library contains an implementation of the CFN stochastic tree model\nfor generating sequences from an ancestor.\n\n.. code-block:: python\n\n >>> from phylogeny.models import CFN_Tree\n\n # Create a new random tree with 5 leaves.\n >>> cfn = CFN_Tree(leaves=5)\n >>> print(cfn)\n\n Node: 0, substitution probability: 0\n Node: 1, substitution probability: 0.35099470913056274\n Node: 2, substitution probability: 0.12569731001404477\n Node: 3, substitution probability: 0.4370228186219944\n Node: 4, substitution probability: 0.36030277887942846\n Node: 5, substitution probability: 0.4905304532735053\n Node: 6, substitution probability: 0.04564697536250617\n Node: 7, substitution probability: 0.4178421652970328\n Node: 8, substitution probability: 0.2728144976941049\n\n /-3\n /1|\n | \\-4\n -0|\n | /-7\n | /5|\n \\2| \\-8\n |\n \\-6\n\n # Evolve 5 traits through the tree\n >>> sequences = cfn.evolve_traits([1,1,1,1,1])\n >>> print(sequences)\n\n {3: [0, 0, 1, 1, 0], 4: [1, 1, 1, 1, 1], 7: [1, 1, 1, 1, 1], 8: [1, 0, 0, 1, 1], 6: [1, 1, 1, 1, 1]}\n\n >>> cfn.distance_matrix()\n\n DistanceMatrix([[0. , 1.7, 4.7, 4.2, 1.8],\n [1.7, 0. , 4.3, 3.8, 1.4],\n [4.7, 4.3, 0. , 1.3, 2.9],\n [4.2, 3.8, 1.3, 0. , 2.4],\n [1.8, 1.4, 2.9, 2.4, 0. ]], names=(3, 4, 7, 8, 6))\n\n\n\nThe clocklike evolution scenario\n--------------------------------\n\nThe most simple case of evolution is the one in which the evolution is\nclocklike, that is, that all branches have the same length (the mutation\nrate is constant over time). In this case, at a certain time, the tree\ngenerated has the property that the distance from the root to each leaf\nis the same.\n\nIf one has an ultrametric distance matrix (which represents clocklike\nevolution), then there are several algorithms to handle the\nreconstruction, 2 of which are implemented in the library:\n\n.. code-block:: python\n\n >>> from phylogeny import DistanceMatrix\n\n # An ultrametric matrix\n >>> ultrametric = DistanceMatrix(\n [[0, 8, 8, 5, 3],\n [8, 0, 3, 8, 8],\n [8, 3, 0, 8, 8],\n [5, 8, 8, 0, 5],\n [3, 8, 8, 5, 0] ],\n names=['A', 'B', 'C', 'D', 'E']\n )\n\n\n\n.. code-block:: python\n\n >>> from phylogeny.reconstruction import infer_clocklike_tree1\n\n >>> t = infer_clocklike_tree1(ultrametric)\n >>> print(t)\n\n /-B\n /-|\n | \\-C\n --|\n | /-A\n | /-|\n \\-| \\-E\n |\n \\-D\n\n\n\n.. code-block:: python\n\n >>> from phylogeny.reconstruction import infer_clocklike_tree2\n\n >>> t = infer_clocklike_tree2(ultrametric)\n >>> print(t)\n\n /-D\n /-|\n | | /-A\n | \\-|\n --| \\-E\n |\n | /-B\n \\-|\n \\-C\n\n\nClocklike reconstruction on the CFN model\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNow we can try to apply the clocklike assumption to a CFN model.\n\n.. code-block:: python\n\n # Create a new random tree with 5 leaves.\n >>> cfn = CFN_Tree(leaves=5)\n >>> cfn.show()\n\n.. image:: https://github.com/Ad115/Phylogeny/raw/master/assets/cfn_tree.png\n\n.. code-block:: python\n\n # Evolve traits through the tree\n >>> sequences = cfn.evolve_traits([1]*10_000)\n\n # Get the distance matrix\n >>> distances = DistanceMatrix.from_sequences(sequences)\n\n # Infer the tree\n >>> t = infer_clocklike_tree1(distances)\n >>> print(t)\n\n /-8\n --|\n | /-5\n \\-|\n | /-7\n \\-|\n | /-3\n \\-|\n \\-4\n\n\nWe can see that the different branch lengths from the root to each leaf\nconfuses the algorithm and we get a tree that is not correct. (The\nreconstruction thus depends mostly on branch length, not on the topology\nof the original tree)\n\nClocklike reconstruction for biological evolution\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNow we test the hypothesis on a simulation of biological microevolution.\n\n.. code-block:: python\n\n # Download from PyPI:\n # pip install cellsystem\n >>> from cellsystem import *\n\n # The cell system will simulate cell growth\n # while tracking the steps in that process.\n >>> system = CellSystem(init_genome='A'*70)\n\n # Initialize the first cell\n # in the middle of the grid\n >>> system.seed()\n\n\n # Take 20 steps forward in time\n >>> system.run(steps=5)\n\n # Stop logging the steps to the screen\n >>> system.log['printer'].silence()\n >>> system.run(steps=15)\n\n::\n\n New cell 0 added @ (50, 50)\n Cell no. 0 migrating from site (50, 50) (father None)\n \tNew site: (51, 49)\n Cell no. 0 migrating from site (51, 49) (father None)\n \tNew site: (51, 48)\n Cell no. 0 dividing @ (51, 48)\n \tNew cells: 1 @ (52, 48) and 2 @ (51, 48)\n Cell no. 1 mutating @ site (52, 48) (father None)\n \tInitial mutations: []\n \tInitial genome: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n \tFinal mutations: [(65, 'G')]\n \tFinal genome: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAA\n\n\n.. code-block:: python\n\n # Look at the real ancestry tree\n >>> t = system.log.ancestry(prune_death=True)\n >>> print(t)\n\n /-9\n /-|\n | \\-10\n --|\n | /-7\n \\-|\n \\-8\n\n\n # Fetch the evolved DNA sequences\n >>> cell_sequences = {cell.index:cell.genome for cell in system['cells'].alive_cells}\n\n # Get the distance matrix\n >>> distances = DistanceMatrix.from_sequences(cell_sequences)\n\n # Inferr a tree under the clocklike assumption\n >>> t = infer_clocklike_tree1(distances)\n >>> print(t)\n\n /-10\n --|\n | /-9\n \\-|\n | /-7\n \\-|\n \\-8\n\n\nWe can see it works better for this data, although it is not quite\nthere.\n\nThe reconstruction problem when evolution is not clocklike\n----------------------------------------------------------\n\nThe reconstruction problem when evolution is not clocklike is so hard\nthat one can not even be sure of where the root of the tree goes!! So,\nin the following, the trees will be fundamentally unrooted, that is, if\ntwo trees differ only in the placement of the root, then we can say they\nare equal.\n\nThe four point condition\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nIt must be noted that for every tree there is a distance matrix but not\nany matrix correspond to a tree, the matrices that do are called\n'additive'. A way to check if a matrix is additive is by checking the\n**Four Point Condition**.\n\nTo explain the four point condition let's say we have the following\nunrooted tree:\n\n::\n\n 1 -\\ /- 3\n >--<\n 2 -/ \\- 4\n\nLet the distance between leaves *a* and *b* be *D(a, b)*. Consider the\nthree following pairwise sums:\n\n- *D(1, 2) + D(3, 4)*\n- *D(1, 3) + D(2, 4)*\n- *D(1, 4) + D(2, 3)*\n\nThe smallest of these sums has to be *D(1, 2) + D(3, 4)*, since it covers all\nthe edges of the tree connecting the four leaves, EXCEPT for the ones on\nthe path separating 1 and 2 from 3 and 4. Furthermore, the two larger of\nthe three pairwise sums have to be identical, since they cover the same\nset of edges.\n\nThe **Four Point Condition** is the statement that the two largest\nvalues of the three pairwise distance sums are the same.\n\nThe library contains a check for additivity based on the four point\ncondition:\n\n.. code-block:: python\n\n # Let's take first a matrix that *is* additive\n # -- We take the matrix representation of a known tree.\n >>> distances = cfn.distance_matrix()\n >>> distances\n\n DistanceMatrix([[0. , 0.5, 3.1, 1.5, 1.6],\n [0.5, 0. , 3.4, 1.7, 1.8],\n [3.1, 3.4, 0. , 2.4, 2.5],\n [1.5, 1.7, 2.4, 0. , 0.5],\n [1.6, 1.8, 2.5, 0.5, 0. ]], names=(3, 4, 5, 7, 8))\n\n\n >>> print(\"Distance matrix is additive: \", distances.is_additive())\n\n >>> distances[2,3] += 1\n >>> print(\"Altered matrix is additive: \", distances.is_additive())\n\n Distance matrix is additive: True\n Altered matrix is additive: False\n\n\nThe four point method\n~~~~~~~~~~~~~~~~~~~~~\n\nThe four point method is based on the four point condition to\nreconstruct a tree from a 4x4 distance matrix. We calculate the three\npairwise sums from the four point condition, we determine which of the\nthree pairwise sums is the smallest, and use that one to define the\nsplit for the four leaves into two sets of two leaves each (remember\nthat if *D(1,2)+D(3,4)* is the smallest sum, then the induced tree must\nbe, in Newick notation, *((1,2),(3,4))*.)\n\n.. code-block:: python\n\n # A test matrix to test the four-point method\n # L1 -\\ /- L2\n # >--<\n # L3 -/ \\- L4\n >>> additive = DistanceMatrix([[0, 3, 6, 7],\n [3, 0, 7, 6],\n [6, 7, 0, 11],\n [7, 6, 11, 0]], names=['L1', 'L2', 'L3', 'L4'])\n\n.. code-block:: python\n\n >>> from phylogeny.reconstruction import four_point_method\n\n >>> tree = four_point_method(additive, names=additive.names)\n >>> print(f\"The associated tree is: {tree}\")\n\n The associated tree is: \n /-L1\n /-|\n | \\-L3\n --|\n | /-L2\n \\-|\n \\-L4\n\n\nThe all quartets method\n~~~~~~~~~~~~~~~~~~~~~~~\n\nThe all quartets method results from the repeated application of the\nfour points method and is useful to reconstruct larger trees.\n\nGiven an *n\u00d7n* additive matrix *M* with *n \u2265 5* associated to a binary tree *T*\nwith positive branch lengths, we can construct *T* using a two-step\ntechnique that we now describe.\n\nIn Step 1, we compute a quartet tree on every four leaves by applying\nthe Four Point Method to each 4\u00d74 submatrix of *M*.\n\nIn Step 2, we assemble the quartet trees into a tree on the full set of\nleaves. Step 1 is straightforward. The technique we use in Step 2 is\ncalled the **All Quartets Method**.\n\n.. code-block:: python\n\n # We start with a known tree\n >>> cfn = CFN_Tree(leaves=5)\n >>> print(cfn)\n\n Node: 0, substitution probability: 0\n Node: 1, substitution probability: 0.4465340963982276\n Node: 2, substitution probability: 0.1674607139638471\n Node: 3, substitution probability: 0.17137831979024587\n Node: 4, substitution probability: 0.3491805016323804\n Node: 5, substitution probability: 0.12428938378084825\n Node: 6, substitution probability: 0.1830304764268481\n Node: 7, substitution probability: 0.3684792177646947\n Node: 8, substitution probability: 0.3426407225165353\n\n /-1\n -0|\n | /-3\n \\2|\n | /-5\n \\4|\n | /-7\n \\6|\n \\-8\n\n\n.. code-block:: python\n\n from phylogeny.reconstruction import all_quartets_method\n\n # Now we infer it from it's distance matrix\n # using the all quartets method\n >>> t = all_quartets_method(cfn.distance_matrix())\n >>> print(t)\n\n /-5\n /-|\n | | /-1\n | \\-|\n --| \\-3\n |\n | /-7\n \\-|\n \\-8\n\n\nLooks good! Now, let's test how it performs with the simulated\nbiological sequences\n\n.. code-block:: python\n\n >>> cell_sequences\n\n {7: 'AAAAAAAAAAGAAAAAAAATAAAAAAAAATATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\n 8: 'AAAAAAAAAAGAAAAAAAATAAAAAAAAATATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\n 9: 'AAAAAAAAAAGAAAAAAAATAAAAAAAAATATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',\n 10: 'AAAAAAAAAAGAAAAAAAATAAAAAAAAATATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'}\n\n\n >>> m = DistanceMatrix.from_sequences(cell_sequences) \n >>> t = all_quartets_method(m)\n >>> print(t)\n\n /-7\n /-|\n | \\-8\n --|\n | /-9\n \\-|\n \\-10\n\n\n.. code-block:: python\n\n # Compare with the real ancestry tree\n >>> t = system.log.ancestry(prune_death=True)\n >>> print(t)\n\n /-9\n /-|\n | \\-10\n --|\n | /-7\n \\-|\n \\-8\n\n\nLooks good too!! If you liked it, please contribute by adding more\nmodels, more algorithms, or improving the existing codebase!\n\nIf you want to learn more about the algorithms, check the source files or\nin the reference books.\n\n\n",
"description_content_type": "",
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/Ad115/Phylogeny",
"keywords": "phylogeny reconstruction inference evolution",
"license": "",
"maintainer": "",
"maintainer_email": "",
"name": "phylogeny",
"package_url": "https://pypi.org/project/phylogeny/",
"platform": "",
"project_url": "https://pypi.org/project/phylogeny/",
"project_urls": {
"Author": "https://agargar.wordpress.com/",
"Bug Reports": "https://github.com/Ad115/Phylogeny/issues",
"Homepage": "https://github.com/Ad115/Phylogeny",
"Say Thanks!": "https://saythanks.io/to/Ad115",
"Source": "https://github.com/Ad115/Phylogeny/"
},
"release_url": "https://pypi.org/project/phylogeny/0.1.1/",
"requires_dist": [
"numpy",
"networkx",
"jupyter; extra == 'dev'",
"cellsystem; extra == 'dev'",
"ete3",
"matplotlib"
],
"requires_python": "",
"summary": "An exploration of algorithms for phylogeny reconstruction.",
"version": "0.1.1"
},
"last_serial": 4224040,
"releases": {
"0.0.1": [
{
"comment_text": "",
"digests": {
"md5": "2f5d410f2cce88cd7f9b139d83d08162",
"sha256": "1b831b2122c5e7aaa6f98b95d85fa280a3fff2118a2ff2336a48ae95c188723d"
},
"downloads": -1,
"filename": "phylogeny-0.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2f5d410f2cce88cd7f9b139d83d08162",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17265,
"upload_time": "2018-08-30T05:17:34",
"url": "https://files.pythonhosted.org/packages/30/d0/e6555fbede90f59e737e6f13bab2cdd6179e3f874fb967bd126ac89b07d7/phylogeny-0.0.1-py3-none-any.whl"
}
],
"0.0.2": [
{
"comment_text": "",
"digests": {
"md5": "8bedf67267fa15003ec9a9bf5323d630",
"sha256": "7affb7394422f40e7ff85b2ebbc4e1df57024de66c1f8c89084b170b995be4e8"
},
"downloads": -1,
"filename": "phylogeny-0.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8bedf67267fa15003ec9a9bf5323d630",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17273,
"upload_time": "2018-08-30T05:51:14",
"url": "https://files.pythonhosted.org/packages/92/5a/0321da2ba773597294c816f1e161359d0c897d07e54f0b52fc004063e0a2/phylogeny-0.0.2-py3-none-any.whl"
}
],
"0.0.3": [
{
"comment_text": "",
"digests": {
"md5": "d2f5b846685809c982d7353380b41179",
"sha256": "5ea9aa4c4e1671168876b32dc066cc095bba328b09e8c80b12b8ba3dfc3c99a6"
},
"downloads": -1,
"filename": "phylogeny-0.0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d2f5b846685809c982d7353380b41179",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17285,
"upload_time": "2018-08-30T05:56:48",
"url": "https://files.pythonhosted.org/packages/7b/1f/9d8d3a7bb2de519b1a856fa14c2bb0fce2ccaeda365573a14bf81c30b316/phylogeny-0.0.3-py3-none-any.whl"
}
],
"0.0.4": [
{
"comment_text": "",
"digests": {
"md5": "98b1ed9fc69ab528cd8539bc4bd5154e",
"sha256": "1470370430c49c621674cd32b560ea348dc496065c03c26553c804c904a33b7f"
},
"downloads": -1,
"filename": "phylogeny-0.0.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "98b1ed9fc69ab528cd8539bc4bd5154e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17310,
"upload_time": "2018-08-30T05:59:43",
"url": "https://files.pythonhosted.org/packages/c6/08/fa8e30a9b55dc962a841aebba9da000e9f5245818d68b97dcfc88a27683e/phylogeny-0.0.4-py3-none-any.whl"
}
],
"0.0.5": [
{
"comment_text": "",
"digests": {
"md5": "f9bfd8ffc0b992477bfeeddd258693e1",
"sha256": "d66e49922c7c2bf81923a45f695c3f9ed98460bcd5a0d0e75b8f39837a597748"
},
"downloads": -1,
"filename": "phylogeny-0.0.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f9bfd8ffc0b992477bfeeddd258693e1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17295,
"upload_time": "2018-08-30T06:03:08",
"url": "https://files.pythonhosted.org/packages/b2/47/62e180da4e5bad24ceabd5806932d465f17cf19facc9a9feeb27a79dd893/phylogeny-0.0.5-py3-none-any.whl"
}
],
"0.0.6": [
{
"comment_text": "",
"digests": {
"md5": "d4cc605c467ea32fe4032d21003b7064",
"sha256": "c28810a1ddbbb06092b72ad136b917e5fb34d00758ea391563ffb0c98b0bca15"
},
"downloads": -1,
"filename": "phylogeny-0.0.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d4cc605c467ea32fe4032d21003b7064",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17397,
"upload_time": "2018-08-30T06:07:56",
"url": "https://files.pythonhosted.org/packages/7c/7d/9b45964efd8d8cbe4b9b2fea609296f9432e81e9efbb8d10f98b6666aa4d/phylogeny-0.0.6-py3-none-any.whl"
}
],
"0.0.7": [
{
"comment_text": "",
"digests": {
"md5": "0c6accb78602b408dda35d3238a2e8d5",
"sha256": "440ea920d1ef75e31fc41a28f0a4f1ba1cbad936b443af9840fe95b423eaa747"
},
"downloads": -1,
"filename": "phylogeny-0.0.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0c6accb78602b408dda35d3238a2e8d5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 26312,
"upload_time": "2018-08-30T08:12:26",
"url": "https://files.pythonhosted.org/packages/a7/09/744c4e449887e3e610afc4543796267b91659cf5a0fb2a1a8c0817483ad2/phylogeny-0.0.7-py3-none-any.whl"
}
],
"0.0.8": [
{
"comment_text": "",
"digests": {
"md5": "86964445b62e1ab34f5a48e840d4fc97",
"sha256": "0efa26860dcc058ddd0fd513b535b7b61529f43af5ddec0b4ad44a26a219132e"
},
"downloads": -1,
"filename": "phylogeny-0.0.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "86964445b62e1ab34f5a48e840d4fc97",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 26318,
"upload_time": "2018-08-30T08:27:52",
"url": "https://files.pythonhosted.org/packages/c8/b3/2c64c89cfb86d8c28a4cf1c7035fee16f1e2f554879dc36d47572df7160c/phylogeny-0.0.8-py3-none-any.whl"
}
],
"0.1.0": [
{
"comment_text": "",
"digests": {
"md5": "ed2182563efc0759ae961843d4b2d735",
"sha256": "79fc54a8fcfbf6260f131f3f94a300499f88dac4e812d69642cf2a430fa060c8"
},
"downloads": -1,
"filename": "phylogeny-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ed2182563efc0759ae961843d4b2d735",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 30536,
"upload_time": "2018-08-30T20:38:33",
"url": "https://files.pythonhosted.org/packages/dc/dc/0a26ffbe49d3401354fd754e3a95f6512320707311f9c887e99257ab45f2/phylogeny-0.1.0-py3-none-any.whl"
}
],
"0.1.1": [
{
"comment_text": "",
"digests": {
"md5": "71b34cb3cc4b674a42ac4fc4202e3949",
"sha256": "4769678e96b4aaa10ed8d2ce93f49ddd4374ef5b3ff4b3708d19124b9e3337b5"
},
"downloads": -1,
"filename": "phylogeny-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "71b34cb3cc4b674a42ac4fc4202e3949",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 30534,
"upload_time": "2018-08-30T20:42:26",
"url": "https://files.pythonhosted.org/packages/78/b1/4b4d2ba07d449e919c07e6fd983980eb928c36e4b4e8e39660bff9d10351/phylogeny-0.1.1-py3-none-any.whl"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "71b34cb3cc4b674a42ac4fc4202e3949",
"sha256": "4769678e96b4aaa10ed8d2ce93f49ddd4374ef5b3ff4b3708d19124b9e3337b5"
},
"downloads": -1,
"filename": "phylogeny-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "71b34cb3cc4b674a42ac4fc4202e3949",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 30534,
"upload_time": "2018-08-30T20:42:26",
"url": "https://files.pythonhosted.org/packages/78/b1/4b4d2ba07d449e919c07e6fd983980eb928c36e4b4e8e39660bff9d10351/phylogeny-0.1.1-py3-none-any.whl"
}
]
}