triplet#
Triplet module.
This module provides classes for representing and working with triplets, which are
rooted trees on 3 taxa. A triplet can either be resolved (with a single trivial 1|2
split a|bc, where a is a child of the root and b, c form a cherry under an
internal node) or unresolved (a star tree where the root has three direct leaf
children). The public API (Triplet, TripletProfile, TripletProfileSet) is re-exported
here; the implementation is split across the base, tprofile, and tprofileset
submodules.
Main Classes#
Triplet base module.
This module provides the Triplet class for representing triplets (3-taxon rooted trees). A triplet can be resolved (single trivial 1|2 split, where the singleton side is a direct child of the root and the 2-element side forms a cherry below an internal node) or unresolved (star tree, where the root has three direct leaf children).
- class phylozoo.core.triplet.base.Triplet(split: Split | frozenset[str] | set[str])[source]#
Bases:
objectImmutable triplet datatype representing a rooted tree on 3 taxa.
A triplet can either have a single trivial 1|2 split representing a resolved rooted tree (the singleton side is a direct child of the root and the 2-element side forms a cherry under an internal node), or be a star tree (represented by a set of 3 taxa) where the root has three direct leaf children.
- Parameters:
split (Split | frozenset[str] | set[str]) – Either a trivial 1|2 split on 3 taxa, or a set/frozenset of exactly 3 taxon labels for a star tree.
- Raises:
PhyloZooValueError – If not exactly 3 taxa, or if split is not trivial (not 1|2).
Examples
>>> from phylozoo.core.split.base import Split >>> triplet = Triplet(Split({1}, {2, 3})) >>> triplet.taxa frozenset({1, 2, 3}) >>> triplet.is_resolved() True >>> star_triplet = Triplet({1, 2, 3}) >>> star_triplet.is_star() True
- __repr__() str[source]#
Return string representation of the triplet.
- Returns:
String representation.
- Return type:
- __setattr__(name: str, value: object) None[source]#
Prevent modification of attributes after initialization.
- Raises:
AttributeError – If attempting to modify any attribute after initialization.
- __str__() str[source]#
Return human-readable string representation of the triplet.
For resolved triplets, displays as “Triplet(a | b c)” where
ais the outgroup andb, care the cherry leaves. For unresolved (star) triplets, displays as “Triplet(a b c)”.- Returns:
Human-readable string representation.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> triplet = Triplet(Split({1}, {2, 3})) >>> str(triplet) 'Triplet(1 | 2 3)' >>> star_triplet = Triplet({1, 2, 3}) >>> str(star_triplet) 'Triplet(1 2 3)'
- property cherry: frozenset[str] | None#
Get the cherry of the triplet (2-element side of the split).
For a resolved triplet
a|{b,c}, returnsfrozenset({b, c})– the two taxa that share an internal parent below the root. For a star tree there is no cherry andNoneis returned.
- copy() Triplet[source]#
Create a copy of the triplet.
- Returns:
A new Triplet instance with the same taxa and split.
- Return type:
- is_resolved() bool[source]#
Check if the triplet is resolved (has a trivial split).
- Returns:
True if the triplet has a split (is resolved), False if it’s a star tree.
- Return type:
- is_star() bool[source]#
Check if the triplet is a star tree (no split).
- Returns:
True if the triplet is a star tree, False if it’s resolved.
- Return type:
- property outgroup: frozenset[str] | None#
Get the outgroup of the triplet (singleton side of the split).
For a resolved triplet
a|{b,c}, returnsfrozenset({a})– the single taxon that is a direct child of the root. For a star tree there is no outgroup andNoneis returned.
- property split: Split | None#
Get the split of the triplet.
- Returns:
The split representing the topology, or None for star tree.
- Return type:
Split | None
- to_network() DirectedPhyNetwork[source]#
Convert the triplet to a DirectedPhyNetwork.
For a resolved triplet
a|{b,c}, creates a rooted binary tree with a root node (with the outgroupaas one child and an internal node as the other child) and an internal node whose two children are the cherry leavesbandc. For a star tree, creates a rooted tree with all three taxa as direct children of the root.- Returns:
A directed phylogenetic network representing the rooted triplet topology.
- Return type:
Triplet profile module.
A triplet profile groups multiple triplets on the same 3-taxon set, each with an associated weight representing the relative importance or frequency of each triplet topology. This module provides the TripletProfile class; total weight is always 1.0.
- class phylozoo.core.triplet.tprofile.TripletProfile(triplets: dict[Triplet, float] | Mapping[Triplet, float] | list[Triplet] | list[tuple[Triplet, float]])[source]#
Bases:
objectImmutable profile for triplets on the same 3-taxon set.
A TripletProfile groups multiple triplets that share the same 3 taxa, each with an associated weight. The weights always sum to 1.0 (within a small tolerance), so the profile represents a probability distribution over triplet topologies.
If no weights are provided (list of triplets), each triplet is assigned equal weight 1/k, where k is the number of triplets.
If weights are provided (dict or list of (triplet, weight) tuples), they must sum to 1.0 (within tolerance); they are not scaled.
- Parameters:
triplets (dict[Triplet, float] | Mapping[Triplet, float] | list[Triplet] | list[tuple[Triplet, float]]) –
Input triplets. Can be:
A dictionary mapping triplets to weights (must sum to 1.0)
A list of triplets (each assigned weight 1/k)
A list of (triplet, weight) tuples (weights must sum to 1.0)
Taxa are automatically extracted from the triplets.
- Raises:
PhyloZooValueError – If triplets is empty, if triplets have different taxa, if any weight is non-positive, or if provided weights do not sum to 1.0.
Examples
>>> from phylozoo.core.split.base import Split >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({2}, {1, 3}))
>>> # From dictionary with weights (already sum to 1.0) >>> profile = TripletProfile({t1: 0.8, t2: 0.2}) >>> profile.taxa frozenset({1, 2, 3}) >>> profile.get_weight(t1) 0.8
>>> # From list of triplets (equal weight 1/k each) >>> profile2 = TripletProfile([t1, t2]) >>> profile2.get_weight(t1) 0.5 >>> profile2.get_weight(t2) 0.5
- __iter__() Iterator[Triplet][source]#
Return an iterator over the triplets.
- Returns:
Iterator over triplets.
- Return type:
Iterator[Triplet]
- __len__() int[source]#
Return the number of triplets in the profile.
- Returns:
Number of triplets.
- Return type:
- __repr__() str[source]#
Return string representation of the profile.
- Returns:
String representation.
- Return type:
- __setattr__(name: str, value: object) None[source]#
Prevent modification of attributes after initialization.
- Raises:
AttributeError – If attempting to modify any attribute after initialization.
- __str__() str[source]#
Return human-readable string representation of the triplet profile.
Displays one line per triplet, showing the triplet (using its __str__ method) and its weight.
- Returns:
Human-readable string representation.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({2}, {1, 3})) >>> profile = TripletProfile({t1: 0.8, t2: 0.2}) >>> str(profile) 'TripletProfile({\n Triplet(1 | 2 3): 0.8,\n Triplet(2 | 1 3): 0.2\n})'
- is_resolved() bool[source]#
Check if the profile is resolved.
A profile is resolved if all its triplets are resolved. A triplet is resolved if it has a trivial split (i.e., it’s not a star tree).
- Returns:
True if all triplets are resolved (profile is resolved), False otherwise.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({2}, {1, 3})) >>> profile = TripletProfile([t1, t2]) >>> profile.is_resolved() True >>> t3 = Triplet({1, 2, 3}) # Star tree >>> profile2 = TripletProfile([t1, t3]) >>> profile2.is_resolved() False
- is_trivial() bool[source]#
Check if the profile is trivial (contains exactly one triplet).
A trivial profile is essentially a single triplet, meaning it represents a single topology rather than a distribution over multiple topologies.
- Returns:
True if the profile contains exactly one triplet, False otherwise.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> t1 = Triplet(Split({1}, {2, 3})) >>> profile = TripletProfile([t1]) >>> profile.is_trivial() True >>> t2 = Triplet(Split({2}, {1, 3})) >>> profile2 = TripletProfile({t1: 0.8, t2: 0.2}) >>> profile2.is_trivial() False
- property split: Split | None#
Get the split if the profile has a single triplet.
Returns the split of the triplet if the profile contains exactly one triplet. If that triplet is a star tree, returns None. If the profile has multiple triplets, returns None (since there would be multiple splits).
The result is cached after first computation.
- Returns:
The split of the single triplet, or None if multiple triplets or star tree.
- Return type:
Split | None
Triplet profile set module.
A triplet profile set is a collection of triplet profiles covering multiple three-taxon sets. This module provides the TripletProfileSet class.
- class phylozoo.core.triplet.tprofileset.TripletProfileSet(profiles: list[TripletProfile | Triplet | tuple[TripletProfile, float]] | None = None, taxa: frozenset[str] | None = None)[source]#
Bases:
objectImmutable collection of triplet profiles with two-level weights.
A TripletProfileSet groups triplets by their 3-taxon sets into profiles. Each profile has a weight (profile weight), and each triplet within a profile also has a weight (triplet weight).
This allows representing uncertainty or multiple hypotheses about triplet topologies for the same set of 3 taxa, with different weights assigned to each hypothesis.
- Parameters:
profiles (list[TripletProfile | Triplet | tuple[TripletProfile, float]] | None, optional) –
List of TripletProfile objects, Triplet objects, or tuples with profile weights.
If TripletProfile: used directly (optionally with a profile-weight tuple).
If Triplet: automatically grouped by taxa into profiles. For each 3-taxon set, all triplets on that set are collected into a
TripletProfilewith equal weights \(1/k\) (where \(k\) is the number of triplets for that taxa set). Each resulting profile in the set receives default profile weight 1.0.If tuple: (profile, weight) where weight is the profile weight.
Passing triplets together with explicit weights (e.g.
(Triplet, weight)) is not supported. To use non-uniform triplet weights within a profile, construct aTripletProfileexplicitly and pass that (optionally with a profile weight).By default None.
taxa (frozenset[str] | None, optional) – Total set of taxa. If provided, must be a superset of all taxa in the profiles. Allows specifying taxa for which no profile exists. By default None (computed from profiles).
- Raises:
PhyloZooValueError – If any profile would be empty, if any weight is non-positive, if profiles/triplets are mixed incorrectly, or if provided taxa is not a superset of profile taxa.
Examples
>>> from phylozoo.core.split.base import Split >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({2}, {1, 3})) >>> t3 = Triplet(Split({4}, {5, 6}))
>>> # From triplets (grouped into profiles, equal weights per profile) >>> profileset = TripletProfileSet(profiles=[t1, t2, t3]) >>> len(profileset) 2 >>> profileset.get_profile_weight(frozenset({1, 2, 3})) 1.0
>>> # From TripletProfile objects (better control) >>> profile1 = TripletProfile({t1: 0.8, t2: 0.2}) >>> profile2 = TripletProfile([t3]) >>> profileset2 = TripletProfileSet(profiles=[(profile1, 2.0), (profile2, 1.5)]) >>> profileset2.get_profile_weight(frozenset({1, 2, 3})) 2.0
- __contains__(taxa: frozenset[str]) bool[source]#
Check if a profile exists for the given 3-taxon set.
- __iter__() Iterator[tuple[TripletProfile, float]][source]#
Return an iterator over (profile, profile_weight) pairs.
- Returns:
Iterator over (profile, weight) tuples.
- Return type:
Iterator[tuple[TripletProfile, float]]
- __repr__() str[source]#
Return string representation of the profile set that can be used to initialize it.
- Returns:
String representation that can be used to recreate the object.
- Return type:
- __str__() str[source]#
Return human-readable string representation of the triplet profile set.
Displays one line per profile, showing the profile (using its __str__ method) and its profile weight. Aligns with TripletProfile’s __str__ format.
- Returns:
Human-readable string representation.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({2}, {1, 3})) >>> profile1 = TripletProfile({t1: 0.8, t2: 0.2}) >>> profileset = TripletProfileSet(profiles=[(profile1, 1.0)]) >>> str(profileset) 'TripletProfileSet({\n TripletProfile({...}) [weight: 1.0]\n})'
- get_profile(taxa: frozenset[str]) TripletProfile | None[source]#
Get the profile for a 3-taxon set.
- Parameters:
- Returns:
The profile for the taxa, or None if not found.
- Return type:
TripletProfile | None
- get_profile_weight(taxa: frozenset[str]) float | None[source]#
Get the profile weight for a 3-taxon set.
- has_profile(taxa: frozenset[str]) bool[source]#
Check if a profile exists for the given 3-taxon set.
- property is_all_resolved: bool#
Check if all profiles in the set are resolved.
A profile is resolved if all its triplets are resolved (i.e., not star trees). This property returns True only if every profile in the set is resolved.
- Returns:
True if all profiles are resolved, False otherwise.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> from phylozoo.core.triplet.base import Triplet >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({4}, {5, 6})) >>> profileset = TripletProfileSet(profiles=[t1, t2]) >>> profileset.is_all_resolved True >>> star = Triplet({1, 2, 3}) >>> profileset2 = TripletProfileSet(profiles=[t2, star]) >>> profileset2.is_all_resolved False
- property is_dense: bool#
Check if the triplet profile set is dense.
A dense triplet profile set has a profile for every possible combination of 3 taxa from the total set of taxa.
- Returns:
True if the profile set is dense (has C(n, 3) profiles where n is the number of taxa), False otherwise.
- Return type:
- property max_profile_len: int#
Get the maximum number of triplets in any profile.
- Returns:
The largest number of triplets in any profile in the set. Returns 0 if the set is empty.
- Return type:
Examples
>>> from phylozoo.core.split.base import Split >>> from phylozoo.core.triplet.base import Triplet >>> t1 = Triplet(Split({1}, {2, 3})) >>> t2 = Triplet(Split({2}, {1, 3})) >>> t3 = Triplet(Split({3}, {1, 2})) >>> profileset = TripletProfileSet(profiles=[t1, t2, t3]) >>> profileset.max_profile_len 3