IO

This module provides the baltic input and output functions.

Notes

This version of baltic (v1.0 (Cedar)) contains many API changes from previous versions, and is not backwards-compatible. If you find pieces of documentation that refer to the old API, please let us know and we will try to update them with the next update.

Attributes

loggerlogging.Logger

Default logger which will be passed to other baltic functions.

baltic.io.load_JSON(jsonObject, treeType, jsonTranslation=None, sort=True, stats=True)

Load a baltic tree from an Auspice-style JSON source.

Parameters

jsonObjectstr or dict

Local path, Nextstrain URL, or already loaded JSON object. A string containing nextstrain.org is fetched over the network with requests; any other string is treated as a local path.

treeType{‘divergence’, ‘time’}

Interpretation of branch lengths in the parsed tree.

jsonTranslationdict, optional

Mapping from baltic attribute names to JSON keys or callables.

sortbool, default=True

If True, sort branches after parsing.

statsbool, default=True

If True, print tree statistics after parsing via baltic.tree.Tree.treeStats().

Returns

tuple[baltic.tree.Tree, dict]

Parsed tree and the JSON’s meta block. A top-level root_sequence key, if present, is folded into the returned metadata.

Raises

AssertionError

If treeType is neither "divergence" nor "time".

Examples

>>> import baltic as bt
>>> auspice = {
...     "meta": {"colorings": []},
...     "tree": {
...         "name": "root",
...         "node_attrs": {"div": 0.0},
...         "children": [
...             {"name": "A", "node_attrs": {"div": 1.0}},
...             {"name": "B", "node_attrs": {"div": 1.2}},
...         ],
...     },
... }
>>> ll, meta = bt.io.load_JSON(auspice, treeType="divergence", stats=False)
>>> sorted(tip.name for tip in ll.get_external())
['A', 'B']
>>> meta["colorings"]
[]
baltic.io.load_newick(treePath, treeType, tipRegex='\\|([0-9\\-]+)$', dateFmt='%Y-%m-%d', variableDate=True, absoluteTime=False, sortBranches=True, setNodes=False)

Load a tree from a Newick file or file-like object.

The first ( on a line marks the start of a tree string. Every such line is parsed, but only the last one is kept, so a file holding several trees silently yields only the final tree.

A path is opened and closed here; a file-like object is read but left open for the caller to close.

Parameters

treePathstr or file-like

Path to a Newick file or an open handle containing tree text.

treeType{‘divergence’, ‘time’}

Interpretation of branch lengths in the parsed tree.

tipRegexstr, default=r”|([0-9-]+)$”

Regular expression used to extract tip dates from leaf names. Only consulted when absoluteTime is True.

dateFmtstr, default=”%Y-%m-%d”

Date format used to parse the value captured by tipRegex. Only consulted when absoluteTime is True.

variableDatebool, default=True

Whether partially specified tip dates should be interpreted as date ranges.

absoluteTimebool, default=False

If True, assign absolute times from the tip labels via process_tip_dates(). Note this defaults to False here but True in load_nexus().

sortBranchesbool, default=True

If True, sort branches after parsing.

setNodesbool, default=False

If True, propagate absolute times to internal nodes when date information is available. Only consulted when absoluteTime is True.

Returns

baltic.tree.Tree

Parsed tree object, already traversed.

Raises

AssertionError

If no line contained a ( and so no tree string was found. (The message mentions a regular expression, but this loader does not use one to find the tree.)

Examples

>>> import io
>>> import baltic as bt
>>> handle = io.StringIO("((A:1.0,B:1.5):0.5,C:2.0);")
>>> ll = bt.io.load_newick(handle, treeType="divergence")
>>> len(ll.get_external())
3
baltic.io.load_nexus(treePath, treeType, tipRegex='\\|([0-9\\-]+)$', dateFmt='%Y-%m-%d', treestringRegex='tree [A-Za-z\\_]+([0-9]+)', variableDate=True, absoluteTime=True, sortBranches=True, setNodes=True)

Load a tree from a Nexus file or file-like object.

Every line matching treestringRegex is parsed, but only the last tree is kept. To iterate over the trees in a BEAST posterior file, use baltic.samogitia.posterior_tree_iterator() instead.

Tips are renamed from their Nexus numbers using the Translate block, and the mapping is kept on the tree as tipMap.

Note

Tips whose names end in _ancestor_taxon, produced by travel-aware phylogeographic analyses, are removed after parsing and the tree rebuilt with baltic.tree.Tree.reduce_tree(), which leaves a multitype tree. A warning is logged when this happens. In practice this only completes with absoluteTime=False, because such tip names put the date before the suffix and so fail tipRegex, which raises in process_tip_dates() first.

A path is opened and closed here; a file-like object is read but left open for the caller to close.

Parameters

treePathstr or file-like

Path to a Nexus file or an open handle containing Nexus content.

treeType{‘divergence’, ‘time’}

Interpretation of branch lengths in the parsed tree.

tipRegexstr, default=r”|([0-9-]+)$”

Regular expression used to extract tip dates from translated tip names. Every tip must match it when absoluteTime is True.

dateFmtstr, default=”%Y-%m-%d”

Date format used to parse the value captured by tipRegex.

treestringRegexstr, default=r”tree [A-Za-z_]+([0-9]+)”

Regular expression used to identify the tree line in the Nexus file.

variableDatebool, default=True

Whether partially specified tip dates should be interpreted as date ranges.

absoluteTimebool, default=True

If True, assign absolute times from the tip labels via process_tip_dates(). Note this defaults to True here but False in load_newick().

sortBranchesbool, default=True

If True, sort branches after parsing.

setNodesbool, default=True

Intended to propagate absolute times to internal nodes.

Warning

This argument currently has no effect: it is accepted but not passed on to process_tip_dates(), which applies its own default of True. Call process_tip_dates() directly if you need setNodes=False.

Returns

baltic.tree.Tree

Parsed tree object, already traversed.

Raises

AssertionError

If no line matched treestringRegex.

KeyError

Via process_tip_dates(), if any tip name fails tipRegex while absoluteTime is True.

Examples

>>> import io
>>> import baltic as bt
>>> nexus = io.StringIO(
...     "#NEXUS\n"
...     "Begin trees;\n"
...     "Translate\n"
...     "    1 A|2020-01-01,\n"
...     "    2 B|2020-02-01;\n"
...     "tree TREE1 = [&R] (1:0.1,2:0.2);\n"
...     "End;\n"
... )
>>> ll = bt.io.load_nexus(nexus, treeType="time")
>>> sorted(tip.name for tip in ll.get_external())
['A|2020-01-01', 'B|2020-02-01']
baltic.io.process_tip_dates(tree, tipRegex, dateFmt, variableDate, setNodes=True)

Extract sampling dates from tip labels and assign absolute times.

Called by load_newick() and load_nexus() when absoluteTime is set. Only dates that resolve to an exact day contribute to the tree’s time calibration; partially specified dates still get an uncertainty range through baltic.tree.Tree._assign_date_uncertainty().

Warning

Every tip must match tipRegex. A tip that does not is logged as a warning but is not skipped: the function goes on to index it and raises KeyError with just the tip name. Undated tips therefore need absoluteTime=False at load time rather than being tolerated here.

Parameters

treebaltic.tree.Tree

Tree whose external branches should be inspected.

tipRegexstr

Regular expression used to capture the date token from each tip name.

dateFmtstr

Date format used to parse the captured token.

variableDatebool

Whether partially specified dates should be interpreted with uncertainty ranges.

setNodesbool, default=True

If True, assign absolute times to internal nodes as well as tips, by calibrating the whole tree against the most recent exact tip date. If False, only tips receive an absoluteTime, taken from their own parsed date.

Returns

None

The tree’s branches are modified in place.

Raises

AssertionError

If no tip name yielded a date, with a message naming the regex and format that were tried.

KeyError

If some, but not all, tip names matched tipRegex (see the warning above).

Examples

>>> import baltic as bt
>>> ll = bt.make_tree("((A|2020-01-01:0.1,B|2020-02-01:0.2):0.3,C|2020-03-01:0.4);", treeType="divergence")
>>> ll.sort_branches()
>>> bt.io.process_tip_dates(ll, tipRegex=r"\|([0-9\-]+)$", dateFmt="%Y-%m-%d", variableDate=True, setNodes=False)
>>> all(tip.absoluteTime is not None for tip in ll.get_external())
True