phykit 2.1.34__tar.gz → 2.1.37__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.
Files changed (112) hide show
  1. {phykit-2.1.34 → phykit-2.1.37}/PKG-INFO +1 -1
  2. {phykit-2.1.34 → phykit-2.1.37}/phykit/cli_registry.py +2 -0
  3. {phykit-2.1.34 → phykit-2.1.37}/phykit/phykit.py +138 -15
  4. {phykit-2.1.34 → phykit-2.1.37}/phykit/service_factories.py +1 -0
  5. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/ancestral_reconstruction.py +701 -1
  6. phykit-2.1.37/phykit/services/tree/spectral_discordance.py +643 -0
  7. phykit-2.1.37/phykit/version.py +1 -0
  8. {phykit-2.1.34 → phykit-2.1.37}/phykit.egg-info/PKG-INFO +1 -1
  9. {phykit-2.1.34 → phykit-2.1.37}/phykit.egg-info/SOURCES.txt +1 -0
  10. {phykit-2.1.34 → phykit-2.1.37}/phykit.egg-info/entry_points.txt +8 -0
  11. {phykit-2.1.34 → phykit-2.1.37}/setup.py +8 -0
  12. phykit-2.1.34/phykit/version.py +0 -1
  13. {phykit-2.1.34 → phykit-2.1.37}/LICENSE.md +0 -0
  14. {phykit-2.1.34 → phykit-2.1.37}/README.md +0 -0
  15. {phykit-2.1.34 → phykit-2.1.37}/phykit/__init__.py +0 -0
  16. {phykit-2.1.34 → phykit-2.1.37}/phykit/__main__.py +0 -0
  17. {phykit-2.1.34 → phykit-2.1.37}/phykit/errors.py +0 -0
  18. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/__init__.py +0 -0
  19. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/boolean_argument_parsing.py +0 -0
  20. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/caching.py +0 -0
  21. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/files.py +0 -0
  22. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/json_output.py +0 -0
  23. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/parallel.py +0 -0
  24. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/stats_summary.py +0 -0
  25. {phykit-2.1.34 → phykit-2.1.37}/phykit/helpers/streaming.py +0 -0
  26. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/__init__.py +0 -0
  27. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/__init__.py +0 -0
  28. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/alignment_entropy.py +0 -0
  29. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/alignment_length.py +0 -0
  30. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/alignment_length_no_gaps.py +0 -0
  31. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/alignment_outlier_taxa.py +0 -0
  32. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/alignment_recoding.py +0 -0
  33. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/base.py +0 -0
  34. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/column_score.py +0 -0
  35. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/composition_per_taxon.py +0 -0
  36. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/compositional_bias_per_site.py +0 -0
  37. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/create_concatenation_matrix.py +0 -0
  38. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/dna_threader.py +0 -0
  39. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/evolutionary_rate_per_site.py +0 -0
  40. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/faidx.py +0 -0
  41. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/gc_content.py +0 -0
  42. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/mask_alignment.py +0 -0
  43. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/occupancy_per_taxon.py +0 -0
  44. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/pairwise_identity.py +0 -0
  45. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/parsimony_informative_sites.py +0 -0
  46. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/plot_alignment_qc.py +0 -0
  47. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/rcv.py +0 -0
  48. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/rcvt.py +0 -0
  49. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/rename_fasta_entries.py +0 -0
  50. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/sum_of_pairs_score.py +0 -0
  51. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/alignment/variable_sites.py +0 -0
  52. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/base.py +0 -0
  53. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/__init__.py +0 -0
  54. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/base.py +0 -0
  55. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/bipartition_support_stats.py +0 -0
  56. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/branch_length_multiplier.py +0 -0
  57. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/collapse_branches.py +0 -0
  58. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/concordance_asr.py +0 -0
  59. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/consensus_network.py +0 -0
  60. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/consensus_tree.py +0 -0
  61. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/cont_map.py +0 -0
  62. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/cophylo.py +0 -0
  63. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/covarying_evolutionary_rates.py +0 -0
  64. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/density_map.py +0 -0
  65. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/discordance_asymmetry.py +0 -0
  66. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/dvmc.py +0 -0
  67. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/evo_tempo_map.py +0 -0
  68. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/evolutionary_rate.py +0 -0
  69. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/fit_continuous.py +0 -0
  70. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/hidden_paralogy_check.py +0 -0
  71. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/internal_branch_stats.py +0 -0
  72. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/internode_labeler.py +0 -0
  73. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/last_common_ancestor_subtree.py +0 -0
  74. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/lb_score.py +0 -0
  75. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/ltt.py +0 -0
  76. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/monophyly_check.py +0 -0
  77. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/nearest_neighbor_interchange.py +0 -0
  78. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/network_signal.py +0 -0
  79. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/ou_shift_detection.py +0 -0
  80. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/ouwie.py +0 -0
  81. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/patristic_distances.py +0 -0
  82. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/phenogram.py +0 -0
  83. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/phylogenetic_glm.py +0 -0
  84. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/phylogenetic_ordination.py +0 -0
  85. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/phylogenetic_regression.py +0 -0
  86. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/phylogenetic_signal.py +0 -0
  87. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/phylomorphospace.py +0 -0
  88. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/polytomy_test.py +0 -0
  89. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/print_tree.py +0 -0
  90. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/prune_tree.py +0 -0
  91. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/quartet_network.py +0 -0
  92. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/rate_heterogeneity.py +0 -0
  93. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/relative_rate_test.py +0 -0
  94. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/rename_tree_tips.py +0 -0
  95. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/rf_distance.py +0 -0
  96. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/root_tree.py +0 -0
  97. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/saturation.py +0 -0
  98. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/spurious_sequence.py +0 -0
  99. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/stochastic_character_map.py +0 -0
  100. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/terminal_branch_stats.py +0 -0
  101. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/threshold_model.py +0 -0
  102. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/tip_labels.py +0 -0
  103. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/tip_to_tip_distance.py +0 -0
  104. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/tip_to_tip_node_distance.py +0 -0
  105. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/total_tree_length.py +0 -0
  106. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/treeness.py +0 -0
  107. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/treeness_over_rcv.py +0 -0
  108. {phykit-2.1.34 → phykit-2.1.37}/phykit/services/tree/vcv_utils.py +0 -0
  109. {phykit-2.1.34 → phykit-2.1.37}/phykit.egg-info/dependency_links.txt +0 -0
  110. {phykit-2.1.34 → phykit-2.1.37}/phykit.egg-info/requires.txt +0 -0
  111. {phykit-2.1.34 → phykit-2.1.37}/phykit.egg-info/top_level.txt +0 -0
  112. {phykit-2.1.34 → phykit-2.1.37}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: phykit
3
- Version: 2.1.34
3
+ Version: 2.1.37
4
4
  Home-page: https://github.com/jlsteenwyk/phykit
5
5
  Author: Jacob L. Steenwyk
6
6
  Author-email: jlsteenwyk@gmail.com
@@ -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)
@@ -1474,19 +1477,24 @@ class Phykit:
1474
1477
  f"""\
1475
1478
  {help_header}
1476
1479
 
1477
- Estimate ancestral states for continuous traits using
1478
- maximum likelihood, analogous to R's phytools::fastAnc()
1479
- and ape::ace(type="ML"). Optionally produce a contMap
1480
- plot showing continuous trait values mapped onto the
1481
- phylogeny.
1480
+ Estimate ancestral states using maximum likelihood.
1482
1481
 
1483
- Two methods are available:
1484
- - fast (default): Felsenstein's pruning/contrasts shortcut,
1485
- O(n) time
1482
+ Supports two trait types:
1483
+ - continuous (default): Brownian Motion model, analogous
1484
+ to R's phytools::fastAnc() and ape::ace(type="ML").
1485
+ Optionally produce a contMap plot.
1486
+ - discrete: Mk model with marginal posterior probabilities
1487
+ at each internal node, analogous to ape::ace(type="discrete").
1488
+ Optionally produce a pie-chart phylogeny plot.
1489
+
1490
+ Continuous methods (--type continuous):
1491
+ - fast (default): Felsenstein's pruning/contrasts, O(n)
1486
1492
  - ml: full VCV-based ML with exact conditional CIs, O(n^3)
1487
1493
 
1488
- Both methods produce identical point estimates; ml gives
1489
- exact conditional confidence intervals.
1494
+ Discrete models (--type discrete):
1495
+ - ER (default): equal rates
1496
+ - SYM: symmetric rates
1497
+ - ARD: all rates different
1490
1498
 
1491
1499
  Input trait data can be either:
1492
1500
  (1) A two-column file (taxon<tab>value) when -c is omitted
@@ -1499,7 +1507,7 @@ class Phykit:
1499
1507
  pk_ancestral_state_reconstruction, pk_asr, pk_anc_recon
1500
1508
 
1501
1509
  Usage:
1502
- phykit ancestral_state_reconstruction -t <tree> -d <trait_data> [-c <trait>] [-m <method>] [--ci] [--plot <output>] [--json]
1510
+ phykit ancestral_state_reconstruction -t <tree> -d <trait_data> [-c <trait>] [--type <type>] [-m <method>] [--model <model>] [--ci] [--plot <output>] [--json]
1503
1511
 
1504
1512
  Options
1505
1513
  =====================================================
@@ -1511,13 +1519,19 @@ class Phykit:
1511
1519
  -c/--trait trait column name (required
1512
1520
  for multi-trait files)
1513
1521
 
1522
+ --type trait type: continuous or
1523
+ discrete (default: continuous)
1524
+
1514
1525
  -m/--method method to use: fast or ml
1515
- (default: fast)
1526
+ (continuous only; default: fast)
1527
+
1528
+ --model Mk model: ER, SYM, or ARD
1529
+ (discrete only; default: ER)
1516
1530
 
1517
1531
  --ci include 95% confidence
1518
- intervals
1532
+ intervals (continuous only)
1519
1533
 
1520
- --plot output path for contMap plot
1534
+ --plot output path for plot
1521
1535
 
1522
1536
  --json output results as JSON
1523
1537
  """
@@ -1533,10 +1547,18 @@ class Phykit:
1533
1547
  "-c", "--trait", type=str, required=False, default=None,
1534
1548
  help=SUPPRESS, metavar=""
1535
1549
  )
1550
+ parser.add_argument(
1551
+ "--type", type=str, required=False, default="continuous",
1552
+ choices=["continuous", "discrete"], help=SUPPRESS, metavar=""
1553
+ )
1536
1554
  parser.add_argument(
1537
1555
  "-m", "--method", type=str, required=False, default="fast",
1538
1556
  choices=["fast", "ml"], help=SUPPRESS, metavar=""
1539
1557
  )
1558
+ parser.add_argument(
1559
+ "--model", type=str, required=False, default="ER",
1560
+ choices=["ER", "SYM", "ARD"], help=SUPPRESS, metavar=""
1561
+ )
1540
1562
  parser.add_argument(
1541
1563
  "--ci", action="store_true", required=False, help=SUPPRESS
1542
1564
  )
@@ -4981,6 +5003,95 @@ class Phykit:
4981
5003
  _add_json_argument(parser)
4982
5004
  _run_service(parser, argv, DiscordanceAsymmetry)
4983
5005
 
5006
+ @staticmethod
5007
+ def spectral_discordance(argv):
5008
+ parser = _new_parser(
5009
+ description=textwrap.dedent(
5010
+ f"""\
5011
+ {help_header}
5012
+
5013
+ Spectral discordance decomposition — decompose gene tree
5014
+ space via PCA on a bipartition presence/absence (or
5015
+ branch-length) matrix, with spectral clustering and
5016
+ automatic cluster detection via the eigengap heuristic.
5017
+
5018
+ Each gene tree is encoded as a vector over the union of
5019
+ all bipartitions observed across gene trees. PCA reveals
5020
+ the axes of topological variation, with loading vectors
5021
+ identifying which bipartitions drive each PC. Spectral
5022
+ clustering groups genes sharing similar topologies.
5023
+
5024
+ Two metrics are available:
5025
+ - nrf (default): binary presence/absence (normalized RF)
5026
+ - wrf: branch-length weighted
5027
+
5028
+ Aliases:
5029
+ spectral_discordance, spec_disc, sd
5030
+ Command line interfaces:
5031
+ pk_spectral_discordance, pk_spec_disc, pk_sd
5032
+
5033
+ Usage:
5034
+ phykit spectral_discordance -g <gene_trees> [-t <tree>] [--metric nrf|wrf] [--clusters K] [--n-pcs N] [--top-loadings N] [--plot <prefix>] [--json]
5035
+
5036
+ Options
5037
+ =====================================================
5038
+ -g/--gene-trees file of gene trees (one
5039
+ Newick per line, or file
5040
+ of filenames)
5041
+
5042
+ -t/--tree species tree (optional; flags
5043
+ species-tree bipartitions in
5044
+ loading output)
5045
+
5046
+ --metric distance metric: nrf or wrf
5047
+ (default: nrf)
5048
+
5049
+ --clusters override auto-detected K
5050
+
5051
+ --n-pcs number of PCs to report
5052
+ (default: min(10, G-1))
5053
+
5054
+ --top-loadings top bipartitions per PC
5055
+ (default: 5)
5056
+
5057
+ --plot output prefix for plots
5058
+ (generates _scatter.png and
5059
+ _eigengap.png)
5060
+
5061
+ --json output results as JSON
5062
+ """
5063
+ ),
5064
+ )
5065
+ parser.add_argument(
5066
+ "-g", "--gene-trees", type=str, required=True, help=SUPPRESS, metavar=""
5067
+ )
5068
+ parser.add_argument(
5069
+ "-t", "--tree", type=str, required=False, default=None,
5070
+ help=SUPPRESS, metavar=""
5071
+ )
5072
+ parser.add_argument(
5073
+ "--metric", type=str, required=False, default="nrf",
5074
+ choices=["nrf", "wrf"], help=SUPPRESS, metavar=""
5075
+ )
5076
+ parser.add_argument(
5077
+ "--clusters", type=int, required=False, default=None,
5078
+ help=SUPPRESS, metavar=""
5079
+ )
5080
+ parser.add_argument(
5081
+ "--n-pcs", type=int, required=False, default=None,
5082
+ help=SUPPRESS, metavar=""
5083
+ )
5084
+ parser.add_argument(
5085
+ "--top-loadings", type=int, required=False, default=5,
5086
+ help=SUPPRESS, metavar=""
5087
+ )
5088
+ parser.add_argument(
5089
+ "--plot", type=str, required=False, default=None,
5090
+ help=SUPPRESS, metavar=""
5091
+ )
5092
+ _add_json_argument(parser)
5093
+ _run_service(parser, argv, SpectralDiscordance)
5094
+
4984
5095
  ### Helper commands
4985
5096
  @staticmethod
4986
5097
  def create_concatenation_matrix(argv):
@@ -5434,3 +5545,15 @@ def create_concatenation_matrix(argv=None):
5434
5545
 
5435
5546
  def thread_dna(argv=None):
5436
5547
  Phykit.thread_dna(sys.argv[1:])
5548
+
5549
+
5550
+ def evo_tempo_map(argv=None):
5551
+ Phykit.evo_tempo_map(sys.argv[1:])
5552
+
5553
+
5554
+ def discordance_asymmetry(argv=None):
5555
+ Phykit.discordance_asymmetry(sys.argv[1:])
5556
+
5557
+
5558
+ def spectral_discordance(argv=None):
5559
+ 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