phykit 2.1.73__tar.gz → 2.1.74__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {phykit-2.1.73 → phykit-2.1.74}/PKG-INFO +1 -1
- {phykit-2.1.73 → phykit-2.1.74}/phykit/phykit.py +7 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/ancestral_reconstruction.py +21 -13
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/concordance_asr.py +10 -6
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/cont_map.py +10 -6
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/density_map.py +10 -6
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/discordance_asymmetry.py +49 -33
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phenogram.py +8 -6
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/rate_heterogeneity.py +10 -6
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/stochastic_character_map.py +10 -6
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/trait_rate_map.py +12 -8
- phykit-2.1.74/phykit/version.py +1 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit.egg-info/PKG-INFO +1 -1
- phykit-2.1.73/phykit/version.py +0 -1
- {phykit-2.1.73 → phykit-2.1.74}/LICENSE.md +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/README.md +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/__init__.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/__main__.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/cli_registry.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/errors.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/__init__.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/boolean_argument_parsing.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/caching.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/circular_layout.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/color_annotations.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/discrete_models.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/files.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/json_output.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/parallel.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/parsimony_utils.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/plot_config.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/quartet_utils.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/stats_summary.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/helpers/streaming.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/service_factories.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/__init__.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/__init__.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/alignment_entropy.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/alignment_length.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/alignment_length_no_gaps.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/alignment_outlier_taxa.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/alignment_recoding.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/alignment_subsample.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/base.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/column_score.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/composition_per_taxon.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/compositional_bias_per_site.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/create_concatenation_matrix.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/dfoil.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/dna_threader.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/dstatistic.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/evolutionary_rate_per_site.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/faidx.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/gc_content.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/identity_matrix.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/mask_alignment.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/occupancy_per_taxon.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/pairwise_identity.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/parsimony_informative_sites.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/phylo_gwas.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/plot_alignment_qc.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/rcv.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/rcvt.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/rename_fasta_entries.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/sum_of_pairs_score.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/alignment/variable_sites.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/base.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/__init__.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/base.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/bipartition_support_stats.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/branch_length_multiplier.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/character_map.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/collapse_branches.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/consensus_network.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/consensus_tree.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/cophylo.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/covarying_evolutionary_rates.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/dvmc.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/evo_tempo_map.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/evolutionary_rate.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/fit_continuous.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/fit_discrete.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/hidden_paralogy_check.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/independent_contrasts.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/internal_branch_stats.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/internode_labeler.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/kf_distance.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/last_common_ancestor_subtree.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/lb_score.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/ltt.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/monophyly_check.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/nearest_neighbor_interchange.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/network_signal.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/ou_shift_detection.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/ouwie.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/parsimony_score.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/patristic_distances.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylo_heatmap.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylo_impute.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylo_logistic.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylogenetic_glm.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylogenetic_ordination.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylogenetic_regression.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylogenetic_signal.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/phylomorphospace.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/polytomy_test.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/print_tree.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/prune_tree.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/quartet_network.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/quartet_pie.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/relative_rate_test.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/rename_tree_tips.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/rf_distance.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/root_tree.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/saturation.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/spectral_discordance.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/spurious_sequence.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/terminal_branch_stats.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/threshold_model.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/tip_labels.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/tip_to_tip_distance.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/tip_to_tip_node_distance.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/total_tree_length.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/trait_correlation.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/tree_space.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/treeness.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/treeness_over_rcv.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit/services/tree/vcv_utils.py +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit.egg-info/SOURCES.txt +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit.egg-info/dependency_links.txt +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit.egg-info/entry_points.txt +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit.egg-info/requires.txt +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/phykit.egg-info/top_level.txt +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/setup.cfg +0 -0
- {phykit-2.1.73 → phykit-2.1.74}/setup.py +0 -0
|
@@ -7598,6 +7598,9 @@ class Phykit:
|
|
|
7598
7598
|
|
|
7599
7599
|
-v/--verbose print per-branch details
|
|
7600
7600
|
|
|
7601
|
+
--annotate show gCF values on the
|
|
7602
|
+
plot near each branch
|
|
7603
|
+
|
|
7601
7604
|
--fig-width figure width in inches
|
|
7602
7605
|
(auto-scaled if omitted)
|
|
7603
7606
|
|
|
@@ -7662,6 +7665,10 @@ class Phykit:
|
|
|
7662
7665
|
parser.add_argument(
|
|
7663
7666
|
"-v", "--verbose", action="store_true", required=False, help=SUPPRESS
|
|
7664
7667
|
)
|
|
7668
|
+
parser.add_argument(
|
|
7669
|
+
"--annotate", action="store_true", required=False, default=False,
|
|
7670
|
+
help=SUPPRESS,
|
|
7671
|
+
)
|
|
7665
7672
|
add_plot_arguments(parser)
|
|
7666
7673
|
_add_json_argument(parser)
|
|
7667
7674
|
_run_service(parser, argv, DiscordanceAsymmetry)
|
|
@@ -939,7 +939,9 @@ class AncestralReconstruction(Tree):
|
|
|
939
939
|
|
|
940
940
|
# Tip labels
|
|
941
941
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
942
|
-
|
|
942
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
943
|
+
if label_fontsize > 0:
|
|
944
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03)
|
|
943
945
|
|
|
944
946
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
945
947
|
if self.plot_config.color_file:
|
|
@@ -1012,11 +1014,13 @@ class AncestralReconstruction(Tree):
|
|
|
1012
1014
|
# Tip labels
|
|
1013
1015
|
max_x = max(node_x.values()) if node_x else 0
|
|
1014
1016
|
offset = max_x * 0.02
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1017
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
1018
|
+
if label_fontsize > 0:
|
|
1019
|
+
for tip in tips:
|
|
1020
|
+
ax.text(
|
|
1021
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
1022
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
1023
|
+
)
|
|
1020
1024
|
|
|
1021
1025
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
1022
1026
|
if self.plot_config.color_file:
|
|
@@ -1655,7 +1659,9 @@ class AncestralReconstruction(Tree):
|
|
|
1655
1659
|
start_angle += sweep
|
|
1656
1660
|
|
|
1657
1661
|
# Tip labels
|
|
1658
|
-
|
|
1662
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
1663
|
+
if label_fontsize > 0:
|
|
1664
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03)
|
|
1659
1665
|
|
|
1660
1666
|
# Apply color annotations
|
|
1661
1667
|
if self.plot_config.color_file:
|
|
@@ -1750,12 +1756,14 @@ class AncestralReconstruction(Tree):
|
|
|
1750
1756
|
# Tip labels with state color
|
|
1751
1757
|
max_x_val = max(node_x.values()) if node_x else 0
|
|
1752
1758
|
offset = max_x_val * 0.02
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
1760
|
+
if label_fontsize > 0:
|
|
1761
|
+
for tip in tips:
|
|
1762
|
+
color = state_colors.get(tip_states.get(tip.name, ""), "black")
|
|
1763
|
+
ax.text(
|
|
1764
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
1765
|
+
tip.name, va="center", fontsize=label_fontsize, color=color,
|
|
1766
|
+
)
|
|
1759
1767
|
|
|
1760
1768
|
# Apply color annotations
|
|
1761
1769
|
if self.plot_config.color_file:
|
|
@@ -844,7 +844,9 @@ class ConcordanceAsr(Tree):
|
|
|
844
844
|
|
|
845
845
|
# Tip labels
|
|
846
846
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
847
|
-
|
|
847
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
848
|
+
if label_fontsize > 0:
|
|
849
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03)
|
|
848
850
|
|
|
849
851
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
850
852
|
if self.plot_config.color_file:
|
|
@@ -915,11 +917,13 @@ class ConcordanceAsr(Tree):
|
|
|
915
917
|
# Tip labels
|
|
916
918
|
max_x = max(node_x.values()) if node_x else 0
|
|
917
919
|
offset = max_x * 0.02
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
920
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
921
|
+
if label_fontsize > 0:
|
|
922
|
+
for tip in tips:
|
|
923
|
+
ax.text(
|
|
924
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
925
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
926
|
+
)
|
|
923
927
|
|
|
924
928
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
925
929
|
if self.plot_config.color_file:
|
|
@@ -522,7 +522,9 @@ class ContMap(Tree):
|
|
|
522
522
|
|
|
523
523
|
# Tip labels
|
|
524
524
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
525
|
-
|
|
525
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
526
|
+
if label_fontsize > 0:
|
|
527
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03)
|
|
526
528
|
|
|
527
529
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
528
530
|
if self.plot_config.color_file:
|
|
@@ -592,11 +594,13 @@ class ContMap(Tree):
|
|
|
592
594
|
# Tip labels
|
|
593
595
|
max_x = max(node_x.values()) if node_x else 0
|
|
594
596
|
offset = max_x * 0.02
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
597
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
598
|
+
if label_fontsize > 0:
|
|
599
|
+
for tip in tips:
|
|
600
|
+
ax.text(
|
|
601
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
602
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
603
|
+
)
|
|
600
604
|
|
|
601
605
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
602
606
|
if self.plot_config.color_file:
|
|
@@ -347,7 +347,9 @@ class DensityMap(Tree):
|
|
|
347
347
|
|
|
348
348
|
# Tip labels
|
|
349
349
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
350
|
-
|
|
350
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
351
|
+
if label_fontsize > 0:
|
|
352
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03)
|
|
351
353
|
|
|
352
354
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
353
355
|
if self.plot_config.color_file:
|
|
@@ -453,11 +455,13 @@ class DensityMap(Tree):
|
|
|
453
455
|
# Tip labels
|
|
454
456
|
max_x = max(node_x.values()) if node_x else 0
|
|
455
457
|
offset = max_x * 0.02
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
458
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
459
|
+
if label_fontsize > 0:
|
|
460
|
+
for tip in tips:
|
|
461
|
+
ax.text(
|
|
462
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
463
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
464
|
+
)
|
|
461
465
|
|
|
462
466
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
463
467
|
if self.plot_config.color_file:
|
|
@@ -33,6 +33,7 @@ class DiscordanceAsymmetry(Tree):
|
|
|
33
33
|
super().__init__(tree_file_path=parsed["tree_file_path"])
|
|
34
34
|
self.gene_trees_path = parsed["gene_trees_path"]
|
|
35
35
|
self.verbose = parsed["verbose"]
|
|
36
|
+
self.annotate = parsed["annotate"]
|
|
36
37
|
self.json_output = parsed["json_output"]
|
|
37
38
|
self.plot_output = parsed["plot_output"]
|
|
38
39
|
self.plot_config = parsed["plot_config"]
|
|
@@ -42,6 +43,7 @@ class DiscordanceAsymmetry(Tree):
|
|
|
42
43
|
tree_file_path=args.tree,
|
|
43
44
|
gene_trees_path=args.gene_trees,
|
|
44
45
|
verbose=getattr(args, "verbose", False),
|
|
46
|
+
annotate=getattr(args, "annotate", False),
|
|
45
47
|
json_output=getattr(args, "json", False),
|
|
46
48
|
plot_output=getattr(args, "plot_output", None),
|
|
47
49
|
plot_config=PlotConfig.from_args(args),
|
|
@@ -314,7 +316,9 @@ class DiscordanceAsymmetry(Tree):
|
|
|
314
316
|
|
|
315
317
|
# Tip labels
|
|
316
318
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
317
|
-
|
|
319
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
320
|
+
if label_fontsize > 0:
|
|
321
|
+
draw_circular_tip_labels(ax, species_tree, coords, fontsize=label_fontsize, offset=max_x * 0.02)
|
|
318
322
|
|
|
319
323
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
320
324
|
if self.plot_config.color_file:
|
|
@@ -345,23 +349,28 @@ class DiscordanceAsymmetry(Tree):
|
|
|
345
349
|
|
|
346
350
|
total = entry["n_concordant"] + entry["n_alt1"] + entry["n_alt2"]
|
|
347
351
|
gcf = entry["n_concordant"] / total if total > 0 else 1.0
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
352
|
+
|
|
353
|
+
if self.annotate:
|
|
354
|
+
ax.annotate(
|
|
355
|
+
f"{gcf:.2f}",
|
|
356
|
+
(cx, cy),
|
|
357
|
+
textcoords="offset points",
|
|
358
|
+
xytext=(5, 5),
|
|
359
|
+
fontsize=max(4, 7 - n_tips * 0.01),
|
|
360
|
+
)
|
|
355
361
|
|
|
356
362
|
if (entry["fdr_p"] is not None and entry["fdr_p"] < 0.05
|
|
357
363
|
and entry["favored_alt"] is not None):
|
|
358
364
|
ax.scatter(cx, cy, s=100, c="red", marker="*", zorder=5)
|
|
359
365
|
|
|
360
|
-
# Colorbar
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
366
|
+
# Colorbar (hide if legend-position is none)
|
|
367
|
+
legend_loc = config.legend_position or "upper right"
|
|
368
|
+
if legend_loc != "none":
|
|
369
|
+
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
|
|
370
|
+
sm.set_array([])
|
|
371
|
+
cbar = fig.colorbar(sm, ax=ax, pad=0.15)
|
|
372
|
+
cbar_fontsize = config.axis_fontsize if config.axis_fontsize else 10
|
|
373
|
+
cbar.set_label("Asymmetry ratio", fontsize=cbar_fontsize)
|
|
365
374
|
|
|
366
375
|
if config.show_title:
|
|
367
376
|
ax.set_title(config.title or "Discordance Asymmetry", fontsize=config.title_fontsize)
|
|
@@ -409,16 +418,18 @@ class DiscordanceAsymmetry(Tree):
|
|
|
409
418
|
x = node_x.get(id(clade), 0)
|
|
410
419
|
y = node_y.get(id(clade), 0)
|
|
411
420
|
|
|
412
|
-
# Show gCF value
|
|
421
|
+
# Show gCF value (only if --annotate)
|
|
413
422
|
total = entry["n_concordant"] + entry["n_alt1"] + entry["n_alt2"]
|
|
414
423
|
gcf = entry["n_concordant"] / total if total > 0 else 1.0
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
(
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
424
|
+
|
|
425
|
+
if self.annotate:
|
|
426
|
+
ax.annotate(
|
|
427
|
+
f"{gcf:.2f}",
|
|
428
|
+
(x, y),
|
|
429
|
+
textcoords="offset points",
|
|
430
|
+
xytext=(5, 5),
|
|
431
|
+
fontsize=max(4, 7 - n_tips * 0.01),
|
|
432
|
+
)
|
|
422
433
|
|
|
423
434
|
# Mark significant branches (FDR < 0.05)
|
|
424
435
|
if (entry["fdr_p"] is not None and entry["fdr_p"] < 0.05
|
|
@@ -426,13 +437,15 @@ class DiscordanceAsymmetry(Tree):
|
|
|
426
437
|
ax.scatter(x, y, s=100, c="red", marker="*", zorder=5)
|
|
427
438
|
|
|
428
439
|
# Tip labels
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
440
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
441
|
+
if label_fontsize > 0:
|
|
442
|
+
max_x = max(node_x.values()) if node_x else 0
|
|
443
|
+
offset = max_x * 0.02
|
|
444
|
+
for tip in tips:
|
|
445
|
+
ax.text(
|
|
446
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
447
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
448
|
+
)
|
|
436
449
|
|
|
437
450
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
438
451
|
if self.plot_config.color_file:
|
|
@@ -450,11 +463,14 @@ class DiscordanceAsymmetry(Tree):
|
|
|
450
463
|
if color_legend:
|
|
451
464
|
ax.legend(handles=color_legend, loc="upper right", fontsize=8, frameon=True)
|
|
452
465
|
|
|
453
|
-
# Colorbar
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
466
|
+
# Colorbar (hide if legend-position is none)
|
|
467
|
+
legend_loc = config.legend_position or "upper right"
|
|
468
|
+
if legend_loc != "none":
|
|
469
|
+
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
|
|
470
|
+
sm.set_array([])
|
|
471
|
+
cbar = fig.colorbar(sm, ax=ax, pad=0.15)
|
|
472
|
+
cbar_fontsize = config.axis_fontsize if config.axis_fontsize else 10
|
|
473
|
+
cbar.set_label("Asymmetry ratio", fontsize=cbar_fontsize)
|
|
458
474
|
|
|
459
475
|
ax.set_xlabel("Branch length (subs/site)")
|
|
460
476
|
ax.set_yticks([])
|
|
@@ -487,12 +487,14 @@ class Phenogram(Tree):
|
|
|
487
487
|
# Label tips with taxon names (offset to the right)
|
|
488
488
|
max_x = max(node_x.values()) if node_x else 0
|
|
489
489
|
offset = max_x * 0.02
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
490
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
491
|
+
if label_fontsize > 0:
|
|
492
|
+
for tip in tips:
|
|
493
|
+
if id(tip) in node_x and tip.name in trait_values:
|
|
494
|
+
ax.text(
|
|
495
|
+
node_x[id(tip)] + offset, trait_values[tip.name],
|
|
496
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
497
|
+
)
|
|
496
498
|
|
|
497
499
|
ax.set_xlabel("Distance from root")
|
|
498
500
|
ax.set_ylabel("Trait value")
|
|
@@ -759,7 +759,9 @@ class RateHeterogeneity(Tree):
|
|
|
759
759
|
|
|
760
760
|
# Tip labels
|
|
761
761
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
762
|
-
|
|
762
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
763
|
+
if label_fontsize > 0:
|
|
764
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.02)
|
|
763
765
|
|
|
764
766
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
765
767
|
if self.plot_config.color_file:
|
|
@@ -825,11 +827,13 @@ class RateHeterogeneity(Tree):
|
|
|
825
827
|
|
|
826
828
|
max_x = max(node_x.values()) if node_x else 0
|
|
827
829
|
offset = max_x * 0.02
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
830
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
831
|
+
if label_fontsize > 0:
|
|
832
|
+
for tip in tips:
|
|
833
|
+
ax.text(
|
|
834
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
835
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
836
|
+
)
|
|
833
837
|
|
|
834
838
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
835
839
|
if self.plot_config.color_file:
|
|
@@ -600,7 +600,9 @@ class StochasticCharacterMap(Tree):
|
|
|
600
600
|
|
|
601
601
|
# Tip labels
|
|
602
602
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
603
|
-
|
|
603
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
604
|
+
if label_fontsize > 0:
|
|
605
|
+
draw_circular_tip_labels(ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03)
|
|
604
606
|
|
|
605
607
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
606
608
|
if self.plot_config.color_file:
|
|
@@ -677,11 +679,13 @@ class StochasticCharacterMap(Tree):
|
|
|
677
679
|
# Tip labels
|
|
678
680
|
max_x = max(node_x.values()) if node_x else 0
|
|
679
681
|
offset = max_x * 0.02
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
682
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
683
|
+
if label_fontsize > 0:
|
|
684
|
+
for tip in tips:
|
|
685
|
+
ax.text(
|
|
686
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
687
|
+
tip.name, va="center", fontsize=label_fontsize
|
|
688
|
+
)
|
|
685
689
|
|
|
686
690
|
# Apply color annotations (range + label only; branches are trait-colored)
|
|
687
691
|
if self.plot_config.color_file:
|
|
@@ -544,9 +544,11 @@ class TraitRateMap(Tree):
|
|
|
544
544
|
|
|
545
545
|
# Tip labels
|
|
546
546
|
max_x = max(node_x.values()) if node_x else 1.0
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
547
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
548
|
+
if label_fontsize > 0:
|
|
549
|
+
draw_circular_tip_labels(
|
|
550
|
+
ax, tree, coords, fontsize=label_fontsize, offset=max_x * 0.03
|
|
551
|
+
)
|
|
550
552
|
|
|
551
553
|
# Color annotations
|
|
552
554
|
if self.plot_config.color_file:
|
|
@@ -611,11 +613,13 @@ class TraitRateMap(Tree):
|
|
|
611
613
|
# Tip labels
|
|
612
614
|
max_x = max(node_x.values()) if node_x else 0
|
|
613
615
|
offset = max_x * 0.02
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
616
|
+
label_fontsize = config.ylabel_fontsize if config.ylabel_fontsize is not None else 9
|
|
617
|
+
if label_fontsize > 0:
|
|
618
|
+
for tip in tips:
|
|
619
|
+
ax.text(
|
|
620
|
+
node_x[id(tip)] + offset, node_y[id(tip)],
|
|
621
|
+
tip.name, va="center", fontsize=label_fontsize,
|
|
622
|
+
)
|
|
619
623
|
|
|
620
624
|
# Color annotations
|
|
621
625
|
if self.plot_config.color_file:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.1.74"
|
phykit-2.1.73/phykit/version.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.1.73"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|