phykit 2.1.35__tar.gz → 2.1.38__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.35 → phykit-2.1.38}/PKG-INFO +1 -1
- {phykit-2.1.35 → phykit-2.1.38}/phykit/cli_registry.py +2 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/phykit.py +119 -10
- {phykit-2.1.35 → phykit-2.1.38}/phykit/service_factories.py +1 -0
- phykit-2.1.38/phykit/services/tree/spectral_discordance.py +643 -0
- phykit-2.1.38/phykit/version.py +1 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit.egg-info/PKG-INFO +1 -1
- {phykit-2.1.35 → phykit-2.1.38}/phykit.egg-info/SOURCES.txt +1 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit.egg-info/entry_points.txt +8 -0
- {phykit-2.1.35 → phykit-2.1.38}/setup.py +8 -0
- phykit-2.1.35/phykit/version.py +0 -1
- {phykit-2.1.35 → phykit-2.1.38}/LICENSE.md +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/README.md +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/__init__.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/__main__.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/errors.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/__init__.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/boolean_argument_parsing.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/caching.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/files.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/json_output.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/parallel.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/stats_summary.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/helpers/streaming.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/__init__.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/__init__.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/alignment_entropy.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/alignment_length.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/alignment_length_no_gaps.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/alignment_outlier_taxa.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/alignment_recoding.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/base.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/column_score.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/composition_per_taxon.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/compositional_bias_per_site.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/create_concatenation_matrix.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/dna_threader.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/evolutionary_rate_per_site.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/faidx.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/gc_content.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/mask_alignment.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/occupancy_per_taxon.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/pairwise_identity.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/parsimony_informative_sites.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/plot_alignment_qc.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/rcv.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/rcvt.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/rename_fasta_entries.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/sum_of_pairs_score.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/alignment/variable_sites.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/base.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/__init__.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/ancestral_reconstruction.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/base.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/bipartition_support_stats.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/branch_length_multiplier.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/collapse_branches.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/concordance_asr.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/consensus_network.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/consensus_tree.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/cont_map.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/cophylo.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/covarying_evolutionary_rates.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/density_map.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/discordance_asymmetry.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/dvmc.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/evo_tempo_map.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/evolutionary_rate.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/fit_continuous.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/hidden_paralogy_check.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/internal_branch_stats.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/internode_labeler.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/last_common_ancestor_subtree.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/lb_score.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/ltt.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/monophyly_check.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/nearest_neighbor_interchange.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/network_signal.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/ou_shift_detection.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/ouwie.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/patristic_distances.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/phenogram.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/phylogenetic_glm.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/phylogenetic_ordination.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/phylogenetic_regression.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/phylogenetic_signal.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/phylomorphospace.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/polytomy_test.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/print_tree.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/prune_tree.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/quartet_network.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/rate_heterogeneity.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/relative_rate_test.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/rename_tree_tips.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/rf_distance.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/root_tree.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/saturation.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/spurious_sequence.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/stochastic_character_map.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/terminal_branch_stats.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/threshold_model.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/tip_labels.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/tip_to_tip_distance.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/tip_to_tip_node_distance.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/total_tree_length.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/treeness.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/treeness_over_rcv.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit/services/tree/vcv_utils.py +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit.egg-info/dependency_links.txt +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit.egg-info/requires.txt +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/phykit.egg-info/top_level.txt +0 -0
- {phykit-2.1.35 → phykit-2.1.38}/setup.cfg +0 -0
|
@@ -157,6 +157,8 @@ ALIAS_TO_HANDLER: Dict[str, str] = {
|
|
|
157
157
|
"etm": "evo_tempo_map",
|
|
158
158
|
"disc_asym": "discordance_asymmetry",
|
|
159
159
|
"da": "discordance_asymmetry",
|
|
160
|
+
"spec_disc": "spectral_discordance",
|
|
161
|
+
"sd": "spectral_discordance",
|
|
160
162
|
# Helper aliases
|
|
161
163
|
"create_concat": "create_concatenation_matrix",
|
|
162
164
|
"cc": "create_concatenation_matrix",
|
|
@@ -277,7 +277,10 @@ class Phykit:
|
|
|
277
277
|
treeness (alias: tness)
|
|
278
278
|
- reports treeness or stemminess, a measure of signal-to-
|
|
279
279
|
noise ratio in a phylogeny
|
|
280
|
-
|
|
280
|
+
spectral_discordance (alias: spec_disc; sd)
|
|
281
|
+
- PCA + spectral clustering of gene tree space via
|
|
282
|
+
bipartition decomposition
|
|
283
|
+
|
|
281
284
|
Alignment- and tree-based commands
|
|
282
285
|
==================================
|
|
283
286
|
saturation (alias: sat)
|
|
@@ -288,9 +291,13 @@ class Phykit:
|
|
|
288
291
|
"""
|
|
289
292
|
),
|
|
290
293
|
)
|
|
291
|
-
parser.add_argument("command", help=SUPPRESS)
|
|
294
|
+
parser.add_argument("command", nargs="?", default=None, help=SUPPRESS)
|
|
292
295
|
args = parser.parse_args(sys.argv[1:2])
|
|
293
296
|
|
|
297
|
+
if args.command is None:
|
|
298
|
+
parser.print_help()
|
|
299
|
+
sys.exit(0)
|
|
300
|
+
|
|
294
301
|
# if command is part of the possible commands (i.e., the long form
|
|
295
302
|
# commands, run). Otherwise, assume it is an alias and look to the
|
|
296
303
|
# run_alias function
|
|
@@ -302,7 +309,8 @@ class Phykit:
|
|
|
302
309
|
except SystemExit:
|
|
303
310
|
# Re-raise SystemExit as-is to preserve exit code
|
|
304
311
|
raise
|
|
305
|
-
except NameError:
|
|
312
|
+
except NameError as e:
|
|
313
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
306
314
|
sys.exit(2)
|
|
307
315
|
|
|
308
316
|
## Aliases
|
|
@@ -491,7 +499,7 @@ class Phykit:
|
|
|
491
499
|
Aliases:
|
|
492
500
|
alignment_recoding, aln_recoding, recode
|
|
493
501
|
Command line interfaces:
|
|
494
|
-
|
|
502
|
+
pk_alignment_recoding, pk_aln_recoding, pk_recode
|
|
495
503
|
|
|
496
504
|
Usage:
|
|
497
505
|
phykit alignment_recoding <fasta> -c/--code <code> [--json]
|
|
@@ -1203,7 +1211,7 @@ class Phykit:
|
|
|
1203
1211
|
f"""\
|
|
1204
1212
|
{help_header}
|
|
1205
1213
|
|
|
1206
|
-
Calculate the number and percentage of
|
|
1214
|
+
Calculate the number and percentage of parsimony
|
|
1207
1215
|
informative sites in an alignment.
|
|
1208
1216
|
|
|
1209
1217
|
The number of parsimony informative sites in an alignment
|
|
@@ -1850,13 +1858,13 @@ class Phykit:
|
|
|
1850
1858
|
|
|
1851
1859
|
Options
|
|
1852
1860
|
=====================================================
|
|
1853
|
-
<tree_file_zero> first argument after
|
|
1861
|
+
<tree_file_zero> first argument after
|
|
1854
1862
|
function name should be
|
|
1855
|
-
|
|
1863
|
+
a tree file
|
|
1856
1864
|
|
|
1857
|
-
<tree_file_one>
|
|
1865
|
+
<tree_file_one> second argument after
|
|
1858
1866
|
function name should be
|
|
1859
|
-
|
|
1867
|
+
a tree file
|
|
1860
1868
|
|
|
1861
1869
|
-r/--reference a tree to correct branch
|
|
1862
1870
|
lengths by in the two input
|
|
@@ -4511,7 +4519,7 @@ class Phykit:
|
|
|
4511
4519
|
a tree file
|
|
4512
4520
|
|
|
4513
4521
|
-v/--verbose optional argument to print
|
|
4514
|
-
all
|
|
4522
|
+
all terminal branch lengths
|
|
4515
4523
|
|
|
4516
4524
|
--json optional argument to output
|
|
4517
4525
|
results as JSON
|
|
@@ -5000,6 +5008,95 @@ class Phykit:
|
|
|
5000
5008
|
_add_json_argument(parser)
|
|
5001
5009
|
_run_service(parser, argv, DiscordanceAsymmetry)
|
|
5002
5010
|
|
|
5011
|
+
@staticmethod
|
|
5012
|
+
def spectral_discordance(argv):
|
|
5013
|
+
parser = _new_parser(
|
|
5014
|
+
description=textwrap.dedent(
|
|
5015
|
+
f"""\
|
|
5016
|
+
{help_header}
|
|
5017
|
+
|
|
5018
|
+
Spectral discordance decomposition — decompose gene tree
|
|
5019
|
+
space via PCA on a bipartition presence/absence (or
|
|
5020
|
+
branch-length) matrix, with spectral clustering and
|
|
5021
|
+
automatic cluster detection via the eigengap heuristic.
|
|
5022
|
+
|
|
5023
|
+
Each gene tree is encoded as a vector over the union of
|
|
5024
|
+
all bipartitions observed across gene trees. PCA reveals
|
|
5025
|
+
the axes of topological variation, with loading vectors
|
|
5026
|
+
identifying which bipartitions drive each PC. Spectral
|
|
5027
|
+
clustering groups genes sharing similar topologies.
|
|
5028
|
+
|
|
5029
|
+
Two metrics are available:
|
|
5030
|
+
- nrf (default): binary presence/absence (normalized RF)
|
|
5031
|
+
- wrf: branch-length weighted
|
|
5032
|
+
|
|
5033
|
+
Aliases:
|
|
5034
|
+
spectral_discordance, spec_disc, sd
|
|
5035
|
+
Command line interfaces:
|
|
5036
|
+
pk_spectral_discordance, pk_spec_disc, pk_sd
|
|
5037
|
+
|
|
5038
|
+
Usage:
|
|
5039
|
+
phykit spectral_discordance -g <gene_trees> [-t <tree>] [--metric nrf|wrf] [--clusters K] [--n-pcs N] [--top-loadings N] [--plot <prefix>] [--json]
|
|
5040
|
+
|
|
5041
|
+
Options
|
|
5042
|
+
=====================================================
|
|
5043
|
+
-g/--gene-trees file of gene trees (one
|
|
5044
|
+
Newick per line, or file
|
|
5045
|
+
of filenames)
|
|
5046
|
+
|
|
5047
|
+
-t/--tree species tree (optional; flags
|
|
5048
|
+
species-tree bipartitions in
|
|
5049
|
+
loading output)
|
|
5050
|
+
|
|
5051
|
+
--metric distance metric: nrf or wrf
|
|
5052
|
+
(default: nrf)
|
|
5053
|
+
|
|
5054
|
+
--clusters override auto-detected K
|
|
5055
|
+
|
|
5056
|
+
--n-pcs number of PCs to report
|
|
5057
|
+
(default: min(10, G-1))
|
|
5058
|
+
|
|
5059
|
+
--top-loadings top bipartitions per PC
|
|
5060
|
+
(default: 5)
|
|
5061
|
+
|
|
5062
|
+
--plot output prefix for plots
|
|
5063
|
+
(generates _scatter.png and
|
|
5064
|
+
_eigengap.png)
|
|
5065
|
+
|
|
5066
|
+
--json output results as JSON
|
|
5067
|
+
"""
|
|
5068
|
+
),
|
|
5069
|
+
)
|
|
5070
|
+
parser.add_argument(
|
|
5071
|
+
"-g", "--gene-trees", type=str, required=True, help=SUPPRESS, metavar=""
|
|
5072
|
+
)
|
|
5073
|
+
parser.add_argument(
|
|
5074
|
+
"-t", "--tree", type=str, required=False, default=None,
|
|
5075
|
+
help=SUPPRESS, metavar=""
|
|
5076
|
+
)
|
|
5077
|
+
parser.add_argument(
|
|
5078
|
+
"--metric", type=str, required=False, default="nrf",
|
|
5079
|
+
choices=["nrf", "wrf"], help=SUPPRESS, metavar=""
|
|
5080
|
+
)
|
|
5081
|
+
parser.add_argument(
|
|
5082
|
+
"--clusters", type=int, required=False, default=None,
|
|
5083
|
+
help=SUPPRESS, metavar=""
|
|
5084
|
+
)
|
|
5085
|
+
parser.add_argument(
|
|
5086
|
+
"--n-pcs", type=int, required=False, default=None,
|
|
5087
|
+
help=SUPPRESS, metavar=""
|
|
5088
|
+
)
|
|
5089
|
+
parser.add_argument(
|
|
5090
|
+
"--top-loadings", type=int, required=False, default=5,
|
|
5091
|
+
help=SUPPRESS, metavar=""
|
|
5092
|
+
)
|
|
5093
|
+
parser.add_argument(
|
|
5094
|
+
"--plot", type=str, required=False, default=None,
|
|
5095
|
+
help=SUPPRESS, metavar=""
|
|
5096
|
+
)
|
|
5097
|
+
_add_json_argument(parser)
|
|
5098
|
+
_run_service(parser, argv, SpectralDiscordance)
|
|
5099
|
+
|
|
5003
5100
|
### Helper commands
|
|
5004
5101
|
@staticmethod
|
|
5005
5102
|
def create_concatenation_matrix(argv):
|
|
@@ -5453,3 +5550,15 @@ def create_concatenation_matrix(argv=None):
|
|
|
5453
5550
|
|
|
5454
5551
|
def thread_dna(argv=None):
|
|
5455
5552
|
Phykit.thread_dna(sys.argv[1:])
|
|
5553
|
+
|
|
5554
|
+
|
|
5555
|
+
def evo_tempo_map(argv=None):
|
|
5556
|
+
Phykit.evo_tempo_map(sys.argv[1:])
|
|
5557
|
+
|
|
5558
|
+
|
|
5559
|
+
def discordance_asymmetry(argv=None):
|
|
5560
|
+
Phykit.discordance_asymmetry(sys.argv[1:])
|
|
5561
|
+
|
|
5562
|
+
|
|
5563
|
+
def spectral_discordance(argv=None):
|
|
5564
|
+
Phykit.spectral_discordance(sys.argv[1:])
|
|
@@ -98,6 +98,7 @@ Treeness = _LazyServiceFactory("phykit.services.tree.treeness", "Treeness")
|
|
|
98
98
|
TreenessOverRCV = _LazyServiceFactory("phykit.services.tree.treeness_over_rcv", "TreenessOverRCV")
|
|
99
99
|
EvoTempoMap = _LazyServiceFactory("phykit.services.tree.evo_tempo_map", "EvoTempoMap")
|
|
100
100
|
DiscordanceAsymmetry = _LazyServiceFactory("phykit.services.tree.discordance_asymmetry", "DiscordanceAsymmetry")
|
|
101
|
+
SpectralDiscordance = _LazyServiceFactory("phykit.services.tree.spectral_discordance", "SpectralDiscordance")
|
|
101
102
|
|
|
102
103
|
SERVICE_FACTORIES: Dict[str, _LazyServiceFactory] = {
|
|
103
104
|
name: value
|