API Reference

Drawing functions

demesdraw.size_history(graph, ax=None, colours=None, log_time=False, log_size=False, title=None, inf_ratio=0.1, inf_label=False, invert_x=False, annotate_epochs=False, num_points=100)[source]

Plot population size as a function of time for each deme in the graph.

Parameters:
  • graph (demes.Graph) – The demes graph to plot.

  • ax (Optional[matplotlib.axes.Axes]) – The matplotlib axes onto which the figure will be drawn. If None, an empty axes will be created for the figure.

  • colours (Optional[dict or str]) – A mapping from deme name to matplotlib colour. Alternately, colours may be a named colour that will be used for all demes.

  • log_time (bool) – If True, use a log-10 scale for the time axis. If False (default), a linear scale will be used.

  • log_size (bool) – If True, use a log-10 scale for the size axis. If False (default), a linear scale will be used.

  • title (Optional[str]) – The title of the figure.

  • inf_ratio (float) – The proportion of the time axis that will be used for the time interval which stretches towards infinity.

  • inf_label (bool) – Write “inf” by the arrow that points towards infinity.

  • invert_x (bool) – If True, the horizontal axis will have infinity on the left and zero on the right, and the vertical axis will be drawn on the right. If False (default), the horizontal axis will have zero on the left and infinity on the right, and the vertical axis will be drawn on the left.

  • annotate_epochs (bool) – If True, annotate the figure with epoch indices over the relevant parts of the lines. This may be useful as a pedagogical tool. If False (default), do not annotate the epochs.

  • num_points (int) –

Returns:

The matplotlib axes onto which the figure was drawn.

Return type:

Axes

demesdraw.tubes(graph, ax=None, colours=None, log_time=False, title=None, inf_ratio=0.2, positions=None, num_lines_per_migration=10, seed=None, max_time=None, labels='xticks-mid', fill=True, scale_bar=False)[source]

Plot a demes-as-tubes schematic of the graph and the demes’ relationships.

Each deme is depicted as a tube, where the tube’s width is proportional to the deme’s size at any given time. Horizontal lines with arrows indicate either:

  • an ancestor/descendant relation (thick solid lines, open arrow heads),

  • an admixture pulse (dashed lines, closed arrow heads),

  • or a period of continuous migration (thin solid lines, closed arrow heads).

Lines are drawn in the colour of the ancestor or source deme, and arrows point from ancestor to descendant or from source to dest. For each period of continuous migration, multiple thin lines are drawn. The time for each migration line is sampled uniformly at random from the migration’s time interval (or log-uniformly for a log-scaled time axis). Symmetric migrations have lines in both directions.

If positions are not specified, the positions will be chosen automatically such that line crossings are minimised and related demes are close together. If the automatically chosen positions are unexpected, please open an issue at https://github.com/grahamgower/demesdraw/issues/.

Parameters:
  • graph (demes.Graph) – The demes graph to plot.

  • ax (Optional[matplotlib.axes.Axes]) – The matplotlib axes onto which the figure will be drawn. If None, an empty axes will be created for the figure.

  • colours (Optional[dict or str]) – A mapping from deme name to matplotlib colour. Alternately, colours may be a named colour that will be used for all demes.

  • log_time (bool) – If True, use a log-10 scale for the time axis. If False (default), a linear scale will be used.

  • title (Optional[str]) – The title of the figure.

  • inf_ratio (float) – The proportion of the time axis that will be used for the time interval which stretches towards infinity.

  • positions (Optional[Mapping[str, float]]) – A dictionary mapping deme names to horizontal coordinates (the mid point of the deme’s tube). Note that the width of a deme is the deme’s (max) size, so the positions should allow sufficient space to avoid overlapping.

  • num_lines_per_migration (int) – The number of lines to draw per migration. For symmetric migrations, this number of lines will be drawn in each direction.

  • seed (Optional[int]) – Seed for the random number generator. The generator is used to sample times for migration lines.

  • max_time (Optional[float]) – The maximum time value shown in the figure. If demographic events (e.g. size changes, migrations, common ancestor events) occur before this time, those events will not be visible. If no demographic events occur before this time, the root demes will be drawn so they extend to the given time.

  • labels (str or None) –

    A string indicating where the deme names should be drawn, or None. The options are:

    • ”xticks”: for extant demes, labels are written under the x-axis as matplotlib xticklabels. Labels are not written for extinct demes.

    • ”legend”: labels for colour patches are written in a legend.

    • ”mid”: labels are written in the middle of each deme’s tube.

    • ”xticks-legend”: for extant demes, labels are written under the x-axis as matplotlib xticklabels. For extinct demes, labels for colour patches are written in a legend.

    • ”xticks-mid” (default): for extant demes, labels are written under the x-axis as matplotlib xticklabels. For extinct demes, labels are written in the middle of each deme’s tube.

    • None: no labels are written.

  • fill (bool) – If True, the inside of the tubes will be painted. If False, only the outline of the tubes will be drawn.

  • scale_bar (bool) – If True, draw a scale bar that indicates population size. If False (default), no scale bar will be shown.

Returns:

The matplotlib axes onto which the figure was drawn.

Return type:

Axes

Utility functions

demesdraw.utils.get_fig_axes(aspect=None, scale=None, **kwargs)[source]

Get a matplotlib figure and axes.

The default width and height of a matplotlib figure is 6.4 x 4.8 inches. To create axes on a figure with other sizes, the figsize argument can be passed to matplotlib.pyplot.subplots(). The get_fig_axes() function creates an axes on a figure with an alternative parameterisation that is useful for screen display of vector images.

An aspect parameter sets the aspect ratio, and a scale parameter multiplies the figure size. Increasing the scale will have the effect of decreasing the size of objects in the figure (including fonts), and increasing the amount of space between objects.

Parameters:
  • aspect (Optional[float]) – The aspect ratio (height/width) of the figure. This value will be passed to matplotlib.figure.figaspect() to obtain the figure’s width and height dimensions. If not specified, 9/16 will be used.

  • scale (Optional[float]) – Multiply the figure width and height by this value. If not specified, 1.0 will be used.

  • kwargs – Further keyword args will be passed directly to matplotlib.pyplot.subplots().

Returns:

A 2-tuple containing the matplotlib figure and axes, as returned by matplotlib.pyplot.subplots().

Return type:

tuple[matplotlib.figure.Figure, matplotlib.axes.Axes]

demesdraw.utils.size_max(graph)[source]

Get the maximum deme size in the graph.

Parameters:

graph (demes.Graph) – The graph.

Returns:

The maximum deme size.

Return type:

float

demesdraw.utils.size_min(graph)[source]

Get the minimum deme size in the graph.

Parameters:

graph (demes.Graph) – The graph.

Returns:

The minimum deme size.

Return type:

float

demesdraw.utils.log_size_heuristic(graph)[source]

Decide whether or not to use log scale for sizes.

Parameters:

graph (demes.Graph) – The graph.

Returns:

True if log scale should be used or False otherwise.

Return type:

bool

demesdraw.utils.log_time_heuristic(graph)[source]

Decide whether or not to use log scale for times.

Parameters:

graph (demes.Graph) – The graph.

Returns:

True if log scale should be used or False otherwise.

Return type:

bool

demesdraw.utils.separation_heuristic(graph)[source]

Find a reasonable separation distance for deme positions.

Parameters:

graph (demes.Graph) – The graph.

Returns:

The separation distance.

Return type:

float

demesdraw.utils.minimal_crossing_positions(graph, *, sep, unique_interactions, maxiter=1000000, seed=1234)[source]

Find an ordering of demes that minimises lines crossing demes.

Lines may be for ancestry, pulses, or migrations. Finding the optimal ordering is hard, but counting how many lines cross for any given ordering is simple, and can be calculated for multiple candidate orderings using vectorised numpy operations. So a naive algorithm is used to search for a good ordering:

  • if \(n!\) <= maxiter, where n is the number of demes in the graph, then all possible orderings may be evaluated,

  • otherwise up to maxiter random orderings are evaluated.

If a proposed ordering produces zero line crossings, the algorithm terminates early. Furthermore, if no ordering is superior to the order that demes were specified in the model (i.e. the order in graph.demes), then the model’s order will be used.

Parameters:
  • graph (Graph) – Graph for which positions should be obtained.

  • sep (float) – The separation distance between demes.

  • maxiter (int) – Maximum number of orderings to search through.

  • seed (int) – Seed for the random number generator.

  • unique_interactions (bool) –

Returns:

A dictionary mapping deme names to positions.

Return type:

Dict[str, float]

demesdraw.utils.optimise_positions(graph, *, positions, sep, unique_interactions)[source]

Optimise the given positions into a tree-like layout.

The objective is to minimise the distances:
  • from each parent deme to the mean position of its children,

  • and between interacting demes (where interactions are either migrations or pulses).

Subject to the constraints that contemporaneous demes:
  • are ordered like in the input positions,

  • and have a minimum separation distance sep.

Parameters:
  • graph (Graph) – Graph for which positions should be optimised.

  • positions (Mapping[str, float]) – A dictionary mapping deme names to positions.

  • sep (float) – The minimum separation distance between contemporary demes.

  • unique_interactions (bool) –

Returns:

A dictionary mapping deme names to positions.

Return type:

Dict[str, float]