Coder Social home page Coder Social logo

demesdraw's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

demesdraw's Issues

`tubes(..., log_time=True)` can produce numpy RuntimeWarning: overflow encountered in power

$ python -Werror -m demesdraw tubes model_B.yaml --log-time
Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/grg/.local/lib/python3.9/site-packages/demesdraw/__main__.py", line 117, in <module>
    cli()
  File "/home/grg/.local/lib/python3.9/site-packages/demesdraw/__main__.py", line 113, in cli
    args.func(args)
  File "/home/grg/.local/lib/python3.9/site-packages/demesdraw/__main__.py", line 72, in __call__
    demesdraw.tubes(graph, ax=ax, log_time=args.log_time, title=args.title)
  File "/home/grg/.local/lib/python3.9/site-packages/demesdraw/tubes.py", line 506, in tubes
    ax.add_patch(arr)
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/axes/_base.py", line 2358, in add_patch
    self._update_patch_limits(p)
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/axes/_base.py", line 2376, in _update_patch_limits
    p = patch.get_path()
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/patches.py", line 4443, in get_path
    return self.get_transform().inverted().transform_path(_path)
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/transforms.py", line 1608, in transform_path
    return self.transform_path_affine(self.transform_path_non_affine(path))
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/transforms.py", line 2438, in transform_path_non_affine
    return self._b.transform_path_non_affine(
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/transforms.py", line 1628, in transform_path_non_affine
    x = self.transform_non_affine(path.vertices)
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/transforms.py", line 2245, in transform_non_affine
    y_points = y.transform_non_affine(points[:, 1])
  File "/home/grg/.local/lib/python3.9/site-packages/matplotlib/scale.py", line 254, in transform_non_affine
    return ma.power(self.base, a)
  File "/home/grg/.local/lib/python3.9/site-packages/numpy/ma/core.py", line 6849, in power
    result = np.where(m, fa, umath.power(fa, fb)).view(basetype)
RuntimeWarning: overflow encountered in power
Exception ignored in: <_io.FileIO name='model_B.yaml' mode='rb' closefd=True>
ResourceWarning: unclosed file <_io.TextIOWrapper name='model_B.yaml' mode='r' encoding='UTF-8'>

Handling deme colors

Might be nice to be able to specify colors for demes in the same way we specify their positions, with a dictionary mapping deme to color. Gives the user more control of colors rather than a color map, maybe?

add tests

Not sure what the best practice is for testing programs with visual output. Manual inspection seems fairly tedious. But we could easily have tests that verify there are no unexpected failures in the various code paths.

Use in pyodide/ jupyterlite

At the moment demesdraw uses four packages that require compiling. This makes it hard to use in jupyterlite:

# within a jupyterlite session
import micropip
await micropip.install('demesdraw', keep_going=True)
ValueError                                Traceback (most recent call last)
Cell In[10], line 17
     14 import tskit
     15 #import tsinfer
     16 #import tsdate
---> 17 await micropip.install('demesdraw', keep_going=True)

File /lib/python3.11/site-packages/micropip/_micropip.py:580, in install(requirements, keep_going, deps, credentials, pre)
    578 if transaction.failed:
    579     failed_requirements = ", ".join([f"'{req}'" for req in transaction.failed])
--> 580     raise ValueError(
    581         f"Can't find a pure Python 3 wheel for: {failed_requirements}\n"
    582         f"See: {FAQ_URLS['cant_find_wheel']}\n"
    583     )
    585 wheel_promises = []
    586 # Install built-in packages

ValueError: Can't find a pure Python 3 wheel for: 'ecos>=2', 'fastcache', 'cvxcanon>=0.0.22', 'scs>=1.1.3'
See: https://pyodide.org/en/stable/usage/faq.html#micropip-can-t-find-a-pure-python-wheel

Is there any way of making these packages optional?

Error for some random seeds

In a CI run of a jupyterbook using demesdraw, I just got this, whereas it was working fine with exactly the same code previously (which itself is weird, as a seed is provided in the code below - is the numpy being seeded correctly?)

 17 ax = demesdraw.tubes(graph, ax=ax, positions=positions, seed=1)
 18 plt.show(ax.figure)


/opt/hostedtoolcache/Python/3.8.10/x64/lib/python3.8/site-packages/demesdraw/tubes.py in tubes(graph, ax, colours, log_time, title, inf_ratio, positions, num_lines_per_migration, seed, optimisation_rounds, labels, fill)

559         if isinstance(migration, demes.AsymmetricMigration):
560             for _ in range(num_lines_per_migration):
561                 t = random_migration_time(migration, log_time)
562                 migration_line(migration.source, migration.dest, t, **migration_kwargs)
563         else:

/opt/hostedtoolcache/Python/3.8.10/x64/lib/python3.8/site-packages/demesdraw/tubes.py in random_migration_time(migration, log_scale)

551             )
552         else:
--> 553             t = rng.uniform(start_time, migration.end_time)
554         return t
555 


_generator.pyx in numpy.random._generator.Generator.uniform()
_common.pyx in numpy.random._common.cont()
_common.pyx in numpy.random._common.check_constraint()
ValueError: high - low < 0

clean up log-scale parameters

  • Remove log_w from schematic(). It's not at all useful.
  • Rename log_x and log_y to be log_time and log_size. These are more descriptive, and more future proof if we ever add a "rotate figure 90 degrees" option.

Is there a way to make .tube() more tree-like?

Hello!

I have recently begun using demesdraw and have really enjoyed it! I was wondering if there is a way to make the output of .tube() to appear more tree-like. For example here are the two demes graphs for a three-taxon tree which is a subset of the larger four-taxon tree.

Three-taxon tree:

description: IUA
time_units: generations
demes:
- name: P123
  epochs:
  - {end_time: 2400000.0, start_size: 1000000.0}
- name: P12
  ancestors: [P123]
  epochs:
  - {end_time: 1200000.0, start_size: 1000000.0}
- name: P3
  ancestors: [P123]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
- name: P2
  ancestors: [P12]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
- name: P1
  ancestors: [P12]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
pulses:
- {source: P3, dest: P2, time: 200000.0, proportion: 0.1}

Four-taxon tree:

description: Introgression from P3 to P2 with an introgression proportion of 0.1 at
  time 200000.0
time_units: generations
demes:
- name: P1234
  epochs:
  - {end_time: 16000000.0, start_size: 1000000.0}
- name: P123
  ancestors: [P1234]
  epochs:
  - {end_time: 2400000.0, start_size: 1000000.0}
- name: P4
  ancestors: [P1234]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
- name: P12
  ancestors: [P123]
  epochs:
  - {end_time: 1200000.0, start_size: 1000000.0}
- name: P3
  ancestors: [P123]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
- name: P2
  ancestors: [P12]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
- name: P1
  ancestors: [P12]
  epochs:
  - {end_time: 0.0, start_size: 1000000.0}
pulses:
- {source: P3, dest: P2, time: 200000.0, proportion: 0.1}

I then plot both graphs with the following code:

# Load graphs.
three_taxon = demes.load('./data/demes_yamls/three_taxon_tree_graph_f_01.yaml')
four_taxon = demes.load('./data/demes_yamls/four_taxon_tree_graph_f_01.yaml')
# Visualize the graphs.
fig, ax = plt.subplots(figsize=(12,9))
demesdraw.tubes(three_taxon, ax=ax, title='Three-Taxon Tree', seed=42)
plt.show()
fig, ax = plt.subplots(figsize=(12,9))
demesdraw.tubes(four_taxon, ax=ax, title='Four-Taxon Tree', seed=42)
plt.show()

Which outputs:
three_taxon_tree_f_01
four_taxon_tree_f_01

I find the three-taxon tree visualization very appealing and would like to view the four-taxon tree in that "tree-like" manner as well. I know the documentation says that demesdraw focus at the moment is to create example for the demes documentation, but was wondering if there is functionality to make the .tube() more tree-like?

Thanks!
-Dave

Support of python 3.6

Hi @grahamgower,

I noticed that since new version of demesdraw v0.1.1 Python3.6 is no longer supported. Maybe it is possible to include it back? Some of my projects still use version 3.6 and I would like to use demesdraw there.

Color shading tracks lineage probabilities through demography

msprime's demography debugger has some methods for computing within and between population coalescence rates as well as probability of finding (e.g. https://github.com/tskit-dev/msprime/blob/main/msprime/demography.py#L2816). Colors and shading of each deme could be set to match the probability that a lineage that starts in a given deme at a given sampling time is in each other deme. I think this would be a really awesome way to visualize the movement and mixing of lineages and ancestry through a deme graph.

If a single deme is specified, the alpha for the color for each deme over time is just the probability that the sampled lineage exists in that deme. If two (or more) are specified, you could imagine shading by the probability that two lineages find themselves in the same deme at a given time. Another possibility is to just overlaying colors so that they bleed into each other, and then at the top of the deme graph in the root population, it would end up being black or brown, or however it turns out by mixing the colors.

I'd be happy to try integrating this type of method here, though I don't know if we'd want to make msprime a dependency of demesdraw. This is a type of visualization that I've been dreaming about for a while now, and I think it would be super useful for people thinking about how lineages mix in complex multipopulation models.

CLI?

At the moment the following is available:

python -m demesdraw.size_history ...
# and
python -m demesdraw.schematic ...

The CLI is currently half baked. I'm in two minds here... We could either (1) do something minimal for folks to quickly look at their demes graph, and customisation must be done through the python API; or alternately (2) do everything the API does, and possibly more (like multi panel figures).

And possibly the CLI should instead be driven like:

python -m demesdraw ...

Maybe with subcommands.

Error coming from matplotlib

While attempting to upload a drawing script in the demes paper, I get this with demes 0.3.0:

python3 drawfig.py
Traceback (most recent call last):
  File "drawfig.py", line 16, in <module>
    ax = demesdraw.tubes(graph, ax=ax, positions=positions, seed=1, inf_ratio=0.4)
  File "/home/kevin/venvs/demes_paper/lib/python3.8/site-packages/demesdraw/tubes.py", line 293, in tubes
    ax.add_patch(path_patch)
AttributeError: 'tuple' object has no attribute 'add_patch'

The script is this one:

#!/usr/bin/env python3
import demes
import demesdraw

def size_max(graph):
    return max(
        max(epoch.start_size, epoch.end_size)
        for deme in graph.demes
        for epoch in deme.epochs
    )

graph = demes.load("models/IM.yaml")
w = 0.8 * size_max(graph)
positions = dict(A=0, X=-w, Y=w)
ax = demesdraw.utils.get_fig_axes(aspect=1)
ax = demesdraw.tubes(graph, ax=ax, positions=positions, seed=1, inf_ratio=0.4) # The offending line.
ax.figure.savefig(
    "fig/IM.pdf",
    # Save with a transparent background.
    transparent=True,
)

conda package

Its not so much work to create conda-forge package.

Replace cvxpy

This package is very useful, but it is also a big dependency that causes portability headaches (e.g. #186). We use it for constrained optimisation here. I'd like to revisit scipy.optimize for this to investigate alternatives---their docs have been improved recently so I think this might be doable.

add some CI

Got some tests now, just need to run them when pull requests are opened. (And then open some pull requests).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.