phasepred 1.0.0__tar.gz → 1.0.2__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 (152) hide show
  1. phasepred-1.0.2/CHANGELOG.md +40 -0
  2. {phasepred-1.0.0 → phasepred-1.0.2}/MANIFEST.in +2 -1
  3. {phasepred-1.0.0/src/phasepred.egg-info → phasepred-1.0.2}/PKG-INFO +19 -14
  4. {phasepred-1.0.0 → phasepred-1.0.2}/README-pypi.md +18 -13
  5. {phasepred-1.0.0 → phasepred-1.0.2}/README.md +43 -10
  6. {phasepred-1.0.0 → phasepred-1.0.2}/pyproject.toml +1 -1
  7. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/__init__.py +1 -1
  8. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/cli.py +33 -3
  9. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/DeepCoil/README.md +7 -7
  10. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/DeepCoil/manifest.toml +1 -1
  11. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PScore/README.md +4 -3
  12. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PScore/install.sh +1 -1
  13. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PScore/manifest.toml +1 -1
  14. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PScore/run +38 -1
  15. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/features.py +9 -1
  16. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/predictor.py +4 -3
  17. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/tool_features.py +5 -2
  18. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/tools.py +84 -68
  19. {phasepred-1.0.0 → phasepred-1.0.2/src/phasepred.egg-info}/PKG-INFO +19 -14
  20. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred.egg-info/SOURCES.txt +1 -0
  21. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_check_tools_table.py +6 -2
  22. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_cli.py +14 -0
  23. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_features.py +28 -0
  24. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_tool_contract_drift.py +77 -0
  25. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_v2022.py +46 -1
  26. {phasepred-1.0.0 → phasepred-1.0.2}/LICENSE +0 -0
  27. {phasepred-1.0.0 → phasepred-1.0.2}/NOTICE +0 -0
  28. {phasepred-1.0.0 → phasepred-1.0.2}/environment.yml +0 -0
  29. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/CHANGELOG.md +0 -0
  30. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/README.md +0 -0
  31. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/pyproject.toml +0 -0
  32. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/scripts/_s4_numeric.py +0 -0
  33. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/scripts/bootstrap_web_benchmark.py +0 -0
  34. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/scripts/eval_routes.py +0 -0
  35. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/scripts/reproduce_distilled.py +0 -0
  36. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/__init__.py +0 -0
  37. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/_distill.py +0 -0
  38. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/cli.py +0 -0
  39. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/scoring.py +0 -0
  40. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/surrogate.py +0 -0
  41. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/weights/catgranule_distilled_weights.json +0 -0
  42. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/weights/catgranule_paper_weights.json +0 -0
  43. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/weights/catgranule_v1_weights.json +0 -0
  44. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/weights/distilled_xgb_model.ubj +0 -0
  45. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/src/catgranule/weights.py +0 -0
  46. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/tests/fixtures/P35637.fasta +0 -0
  47. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/tests/fixtures/Q08211.fasta +0 -0
  48. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/tests/test_catgranule_cli.py +0 -0
  49. {phasepred-1.0.0 → phasepred-1.0.2}/packages/catgranule/tests/test_scoring.py +0 -0
  50. {phasepred-1.0.0 → phasepred-1.0.2}/scripts/check_no_proprietary.py +0 -0
  51. {phasepred-1.0.0 → phasepred-1.0.2}/scripts/train_phasepred.py +0 -0
  52. {phasepred-1.0.0 → phasepred-1.0.2}/scripts/validate_phasepred.py +0 -0
  53. {phasepred-1.0.0 → phasepred-1.0.2}/setup.cfg +0 -0
  54. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/deepphase/LICENSE +0 -0
  55. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/deepphase/NOTICE +0 -0
  56. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/deepphase/deepphase_scores.tsv +0 -0
  57. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_0.joblib +0 -0
  58. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_1.joblib +0 -0
  59. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_2.joblib +0 -0
  60. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_3.joblib +0 -0
  61. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_4.joblib +0 -0
  62. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_5.joblib +0 -0
  63. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_6.joblib +0 -0
  64. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_7.joblib +0 -0
  65. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_8.joblib +0 -0
  66. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/8f_model_9.joblib +0 -0
  67. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/PdPS/manifest.json +0 -0
  68. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_0.joblib +0 -0
  69. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_1.joblib +0 -0
  70. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_2.joblib +0 -0
  71. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_3.joblib +0 -0
  72. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_4.joblib +0 -0
  73. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_5.joblib +0 -0
  74. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_6.joblib +0 -0
  75. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_7.joblib +0 -0
  76. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_8.joblib +0 -0
  77. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/8f_model_9.joblib +0 -0
  78. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/SaPS/manifest.json +0 -0
  79. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_0.joblib +0 -0
  80. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_1.joblib +0 -0
  81. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_2.joblib +0 -0
  82. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_3.joblib +0 -0
  83. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_4.joblib +0 -0
  84. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_5.joblib +0 -0
  85. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_6.joblib +0 -0
  86. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_7.joblib +0 -0
  87. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_8.joblib +0 -0
  88. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/8f_model_9.joblib +0 -0
  89. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hPdPS/manifest.json +0 -0
  90. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_0.joblib +0 -0
  91. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_1.joblib +0 -0
  92. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_2.joblib +0 -0
  93. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_3.joblib +0 -0
  94. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_4.joblib +0 -0
  95. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_5.joblib +0 -0
  96. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_6.joblib +0 -0
  97. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_7.joblib +0 -0
  98. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_8.joblib +0 -0
  99. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/8f_model_9.joblib +0 -0
  100. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/models/hSaPS/manifest.json +0 -0
  101. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/DeepCoil/install.sh +0 -0
  102. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/DeepCoil/run +0 -0
  103. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/ESpritz/README.md +0 -0
  104. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/ESpritz/install.sh +0 -0
  105. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/ESpritz/manifest.toml +0 -0
  106. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/ESpritz/run +0 -0
  107. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/LocalCIDER/README.md +0 -0
  108. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/LocalCIDER/install.sh +0 -0
  109. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/LocalCIDER/manifest.toml +0 -0
  110. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/LocalCIDER/run +0 -0
  111. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PLAAC/README.md +0 -0
  112. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PLAAC/install.sh +0 -0
  113. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PLAAC/manifest.toml +0 -0
  114. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PLAAC/plaac-master/web/bin/plaac.jar +0 -0
  115. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PLAAC/run +0 -0
  116. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PScore/SourceCodeS2/README.txt +0 -0
  117. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/PScore/SourceCodeS2/elife_phase_separation_predictor.py +0 -0
  118. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/README.md +0 -0
  119. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/SEG/README.md +0 -0
  120. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/SEG/install.sh +0 -0
  121. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/SEG/manifest.toml +0 -0
  122. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/SEG/run +0 -0
  123. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data/tools/SEG/seg +0 -0
  124. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/data.py +0 -0
  125. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/espritz.py +0 -0
  126. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/legacy_features.py +0 -0
  127. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/models.py +0 -0
  128. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/paper.py +0 -0
  129. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/sequences.py +0 -0
  130. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/tool_paths.py +0 -0
  131. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/training.py +0 -0
  132. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/training_data.py +0 -0
  133. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/updated_data.py +0 -0
  134. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred/validation.py +0 -0
  135. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred.egg-info/dependency_links.txt +0 -0
  136. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred.egg-info/entry_points.txt +0 -0
  137. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred.egg-info/requires.txt +0 -0
  138. {phasepred-1.0.0 → phasepred-1.0.2}/src/phasepred.egg-info/top_level.txt +0 -0
  139. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_cwd.py +0 -0
  140. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_data_resolution.py +0 -0
  141. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_demo_scripts.py +0 -0
  142. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_golden_fixtures.py +0 -0
  143. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_models.py +0 -0
  144. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_paper.py +0 -0
  145. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_sequences.py +0 -0
  146. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_train_phasepred.py +0 -0
  147. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_training.py +0 -0
  148. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_training_data.py +0 -0
  149. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_training_data_integrity.py +0 -0
  150. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_training_data_real.py +0 -0
  151. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_validation.py +0 -0
  152. {phasepred-1.0.0 → phasepred-1.0.2}/tests/test_version_consistency.py +0 -0
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ ## [1.0.2] - 2026-09-28
4
+
5
+ Patch release for the 1.0.1 installation feedback. Model artifacts and
6
+ training data are unchanged.
7
+
8
+ ### Fixed
9
+
10
+ - Use `python3` in the Ubuntu venv examples.
11
+ - Document DeepCoil's user-data installation path and show it in missing-tool
12
+ guidance; keep the legacy checkout environment as a fallback.
13
+ - Show the PScore install command when `check-tools` reports it missing.
14
+ - Let the checkout PScore runner find DBS in the installed user-data copy and
15
+ accept relative FASTA and output paths when invoked on its own.
16
+
17
+ ## [1.0.1] - 2026-09-28
18
+
19
+ Patch release based on installation and prediction feedback. Model artifacts
20
+ and training data are unchanged.
21
+
22
+ ### Fixed
23
+
24
+ - PScore's `install.sh --check` now checks the installed user-data copy instead
25
+ of mistakenly checking for DBS files in the repository.
26
+ - PhaSePred sends DeepCoil smaller sequence groups to reduce peak memory use
27
+ during batch prediction. A failed group reports a warning without discarding
28
+ successful groups; sequences shorter than 20 residues get a specific warning.
29
+ - FCR remains available for sequences containing selenocysteine (`U`) even
30
+ when the Hydropathy scale cannot score that residue.
31
+
32
+ ### Improved
33
+
34
+ - `predict` identifies proteins with missing features before the model imputes
35
+ those values and calculates a score.
36
+ - The READMEs clarify that `features-from-fasta` computes four features and
37
+ that individual tool checks can be silent on success.
38
+
39
+ The local catGRANULE scale has no value for `U`, so catGRANULE remains missing
40
+ for such sequences and is imputed during prediction.
@@ -20,6 +20,7 @@
20
20
  # pixi.toml/pixi.lock, and the CI workflow. pip installs the package from the
21
21
  # index; the repository remains the route for training on the paper data.
22
22
  include environment.yml
23
+ include CHANGELOG.md
23
24
  include NOTICE
24
25
  include README-pypi.md
25
26
  recursive-include scripts *.py *.sh *.md
@@ -31,4 +32,4 @@ recursive-include packages/catgranule/src *.py *.json *.ubj
31
32
  recursive-include packages/catgranule/tests *.py *.fasta
32
33
  recursive-include packages/catgranule/scripts *.py
33
34
 
34
- global-exclude *.py[cod]
35
+ global-exclude *.py[cod]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: phasepred
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: Paper-faithful re-implementation of the PhaSePred phase-separation predictor (Chen et al. 2022, PNAS).
5
5
  Author: Tingting Li Lab, Department of Biochemistry and Molecular Biology, School of Basic Medical Sciences, Peking University
6
6
  License-Expression: MIT
@@ -48,7 +48,24 @@ Implementation of [Chen et al. 2022 *PNAS*](https://doi.org/10.1073/pnas.2115369
48
48
  pip install phasepred
49
49
  ```
50
50
 
51
- Requires Python >= 3.12.
51
+ Requires Python >= 3.12. The models and the DeepPhase table ship inside the
52
+ package.
53
+
54
+ Four feature components cannot be redistributed and need a one-time install from
55
+ the repository:
56
+
57
+ ```bash
58
+ git clone https://github.com/notwhiteblank/PhaSePred.git && cd PhaSePred
59
+ bash tools/PScore/install.sh
60
+ bash tools/ESpritz/install.sh
61
+ bash tools/DeepCoil/install.sh
62
+ bash tools/PhosphoSitePlus/install.sh # only needed for hSaPS / hPdPS
63
+ ```
64
+
65
+ The installers put their data under `~/.local/share/phasepred/`, where the
66
+ package finds it automatically. `phasepred check-tools` prints a status row per
67
+ component, and for every missing one the exact command that installs it. A
68
+ complete install reports `9 OK`.
52
69
 
53
70
  ## Use
54
71
 
@@ -65,18 +82,6 @@ Input can also be UniProt accessions:
65
82
  phasepred predict --ids "P35637,Q9Y2W1" --mode SaPS --output scores.csv
66
83
  ```
67
84
 
68
- ## Feature tools
69
-
70
- Five of the nine feature components ship with the package and work immediately.
71
- The rest need a one-time install:
72
-
73
- ```bash
74
- phasepred check-tools
75
- ```
76
-
77
- This prints a status row per component, and for every missing one the exact
78
- command that installs it.
79
-
80
85
  ## More
81
86
 
82
87
  Source, training data, retraining and AUC validation against the paper:
@@ -9,7 +9,24 @@ Implementation of [Chen et al. 2022 *PNAS*](https://doi.org/10.1073/pnas.2115369
9
9
  pip install phasepred
10
10
  ```
11
11
 
12
- Requires Python >= 3.12.
12
+ Requires Python >= 3.12. The models and the DeepPhase table ship inside the
13
+ package.
14
+
15
+ Four feature components cannot be redistributed and need a one-time install from
16
+ the repository:
17
+
18
+ ```bash
19
+ git clone https://github.com/notwhiteblank/PhaSePred.git && cd PhaSePred
20
+ bash tools/PScore/install.sh
21
+ bash tools/ESpritz/install.sh
22
+ bash tools/DeepCoil/install.sh
23
+ bash tools/PhosphoSitePlus/install.sh # only needed for hSaPS / hPdPS
24
+ ```
25
+
26
+ The installers put their data under `~/.local/share/phasepred/`, where the
27
+ package finds it automatically. `phasepred check-tools` prints a status row per
28
+ component, and for every missing one the exact command that installs it. A
29
+ complete install reports `9 OK`.
13
30
 
14
31
  ## Use
15
32
 
@@ -26,18 +43,6 @@ Input can also be UniProt accessions:
26
43
  phasepred predict --ids "P35637,Q9Y2W1" --mode SaPS --output scores.csv
27
44
  ```
28
45
 
29
- ## Feature tools
30
-
31
- Five of the nine feature components ship with the package and work immediately.
32
- The rest need a one-time install:
33
-
34
- ```bash
35
- phasepred check-tools
36
- ```
37
-
38
- This prints a status row per component, and for every missing one the exact
39
- command that installs it.
40
-
41
46
  ## More
42
47
 
43
48
  Source, training data, retraining and AUC validation against the paper:
@@ -40,16 +40,24 @@ The ten features, of which the 8-feature modes use all but the last two:
40
40
 
41
41
  ### Install
42
42
 
43
- The package needs Python `>=3.12`. Pick one of four routes:
43
+ Python `>=3.12`. Clone the repository and install:
44
44
 
45
45
  ```bash
46
- pixi install # pixi
47
- uv venv --python 3.12 && uv pip install . # uv
48
- conda env create -f environment.yml && conda activate phasepred # conda
49
- python -m venv .venv && .venv/bin/pip install -e . -e packages/catgranule # plain venv
46
+ git clone https://github.com/notwhiteblank/PhaSePred.git && cd PhaSePred
47
+ pixi install
50
48
  ```
51
49
 
52
- Install the external tools separately:
50
+ `uv`, `conda` and a plain venv work just as well:
51
+
52
+ ```bash
53
+ uv venv --python 3.12 && uv pip install .
54
+ conda env create -f environment.yml && conda activate phasepred
55
+ python3 -m venv .venv && .venv/bin/pip install -e . -e packages/catgranule
56
+ ```
57
+
58
+ Then install the external feature tools. Each installer is idempotent and puts
59
+ its data under `~/.local/share/phasepred/`, where the package finds it
60
+ automatically:
53
61
 
54
62
  ```bash
55
63
  bash tools/SEG/install.sh
@@ -61,14 +69,21 @@ bash tools/LocalCIDER/install.sh
61
69
  bash tools/PhosphoSitePlus/install.sh # only needed for hSaPS / hPdPS
62
70
  ```
63
71
 
64
- Then check:
72
+ `check-tools` confirms the result; a complete install reports `9 OK`:
65
73
 
66
74
  ```bash
67
- phasepred check-tools # table, with an install hint on every MISSING row
75
+ phasepred check-tools # status table, with an install hint per missing component
68
76
  phasepred check-tools --strict # exits 1 when a required tool is missing; use this in scripts and CI
69
77
  ```
70
78
 
71
- `SEG`, `PLAAC`, `LocalCIDER`, `catGRANULE` and `DeepPhase` ship with the package and work immediately. `PScore`, `ESpritz`, `DeepCoil` and `PhosphoSitePlus` need the installers above.
79
+ The models and the DeepPhase table ship inside the package, so nothing else is
80
+ needed to predict. `SEG`, `PLAAC`, `LocalCIDER` and `catGRANULE` also ship with
81
+ it; the installers above cover the four components that cannot be redistributed.
82
+
83
+ Installing from PyPI instead (`pip install phasepred`) gives you the same
84
+ package. The tool installers live in `tools/`, which is part of the repository
85
+ rather than the wheel, so clone it to run them — after that everything resolves
86
+ the same way.
72
87
 
73
88
  ### Run
74
89
 
@@ -93,7 +108,25 @@ phasepred predict --fasta my.fasta --ids "P35637" --mode SaPS --output scores.cs
93
108
  phasepred features-from-fasta --input my.fasta --output features.csv
94
109
  ```
95
110
 
96
- The output CSV carries the numeric value of every feature alongside `score`.
111
+ The `predict` output CSV carries every model feature alongside `score`. If a
112
+ feature is unavailable for a protein, `predict` lists the missing columns on
113
+ stderr and the model imputes them before scoring. A score with missing features
114
+ should be interpreted with that limitation. For example, selenocysteine (`U`)
115
+ has no value in the local catGRANULE scale, so that feature stays empty; FCR
116
+ is still computed from the charged residues in the original sequence.
117
+
118
+ `features-from-fasta` is a smaller four-feature command: Hydropathy, FCR,
119
+ ESpritz IDR fraction, and SEG LCR fraction. Use `predict` when the complete
120
+ model feature table is needed.
121
+
122
+ DeepCoil predictions are sent in bounded groups (at most four proteins and
123
+ normally 4,000 residues per call; a single longer protein stays intact) to
124
+ reduce peak memory use. A failed group emits a
125
+ warning and its DeepCoil values are imputed. If the operating system still
126
+ kills a group for memory, split the FASTA into smaller files or increase the
127
+ available memory. Sequences shorter than 20 residues are skipped with a
128
+ specific warning. `phasepred check-tools` is the consolidated status display;
129
+ individual `run --check` commands may be silent when they succeed.
97
130
 
98
131
  ## Reproduction
99
132
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "phasepred"
3
- version = "1.0.0"
3
+ version = "1.0.2"
4
4
  description = "Paper-faithful re-implementation of the PhaSePred phase-separation predictor (Chen et al. 2022, PNAS)."
5
5
  readme = { file = "README-pypi.md", content-type = "text/markdown" }
6
6
  license = "MIT"
@@ -1,3 +1,3 @@
1
1
  """PhaSePred reconstruction package."""
2
2
 
3
- __version__ = "1.0.0"
3
+ __version__ = "1.0.2"
@@ -18,7 +18,7 @@ from sklearn.metrics import average_precision_score, roc_auc_score
18
18
 
19
19
  from phasepred import __version__ as _phasepred_version
20
20
  from phasepred import data
21
- from phasepred.features import FeatureSchemaError, compute_native_features
21
+ from phasepred.features import FeatureSchemaError, compute_fcr, compute_native_features
22
22
  from phasepred.legacy_features import (
23
23
  compute_lcr_features,
24
24
  compute_phosphosite_frequencies,
@@ -143,10 +143,23 @@ def features_from_fasta(
143
143
  idr_rows = _compute_espritz_idr_fraction(records)
144
144
  lcr_rows = _compute_lcr_fraction(records)
145
145
  for record in records:
146
+ try:
147
+ native = compute_native_features(record.sequence)
148
+ except FeatureSchemaError as exc:
149
+ native = {
150
+ "length": float(len(record.sequence)),
151
+ "Hydropathy": float("nan"),
152
+ "FCR": compute_fcr(record.sequence),
153
+ }
154
+ typer.echo(
155
+ f"WARNING: {record.accession}: Hydropathy unavailable ({exc}); "
156
+ "FCR was computed from the original sequence.",
157
+ err=True,
158
+ )
146
159
  row = {
147
160
  "UniprotEntry": record.accession,
148
161
  "sequence": record.sequence,
149
- **compute_native_features(record.sequence),
162
+ **native,
150
163
  }
151
164
  row["espritz-idr-fraction"] = idr_rows.get(record.accession, float("nan"))
152
165
  row["lcr-fraction"] = lcr_rows.get(record.accession, float("nan"))
@@ -593,6 +606,24 @@ def predict(
593
606
  typer.echo(f"Computing features for {len(records)} protein(s), mode={mode}...")
594
607
  feature_df = compute_all_features(records, include_human=is_human)
595
608
 
609
+ columns = HUMAN_FEATURE_COLUMNS if is_human else BASE_FEATURE_COLUMNS
610
+ missing_by_row = feature_df[list(columns)].isna()
611
+ affected = missing_by_row.any(axis=1)
612
+ if affected.any():
613
+ typer.echo(
614
+ f"WARNING: {int(affected.sum())}/{len(feature_df)} protein(s) have missing "
615
+ "features; the model will impute them before scoring.",
616
+ err=True,
617
+ )
618
+ for index in feature_df.index[affected][:8]:
619
+ absent = [column for column in columns if missing_by_row.loc[index, column]]
620
+ typer.echo(
621
+ f" {feature_df.loc[index, 'UniprotEntry']}: {', '.join(absent)}",
622
+ err=True,
623
+ )
624
+ if affected.sum() > 8:
625
+ typer.echo(f" ... and {int(affected.sum()) - 8} more", err=True)
626
+
596
627
  # Load model(s)
597
628
  model_path_or_dir = chosen_models_dir / f"{mode}.joblib"
598
629
  if model_path_or_dir.exists():
@@ -632,7 +663,6 @@ def predict(
632
663
  )
633
664
 
634
665
  # Predict
635
- columns = HUMAN_FEATURE_COLUMNS if is_human else BASE_FEATURE_COLUMNS
636
666
  predictions = predict_scores(models, feature_df, list(columns))
637
667
 
638
668
  # Merge features for informative output
@@ -27,8 +27,10 @@ tools/DeepCoil/
27
27
  └── README.md this file
28
28
  ```
29
29
 
30
- No entity is vendored — the tool lives in an isolated Python 3.8 conda env
31
- at `.external_envs/deepcoil` (gitignored).
30
+ No entity is vendored — the tool lives in an isolated Python 3.8 conda env.
31
+ New installations use `~/.local/share/phasepred/envs/deepcoil` by default,
32
+ or `$XDG_DATA_HOME/phasepred/envs/deepcoil` / `$PHASEPRED_DATA_ROOT/envs/deepcoil`
33
+ when set. Existing `.external_envs/deepcoil` environments remain supported.
32
34
 
33
35
  ## Install
34
36
 
@@ -38,14 +40,12 @@ bash tools/DeepCoil/install.sh --check # verify env/bin/deepcoil present
38
40
  ```
39
41
 
40
42
  Overrides: `DEEPCOIL_ENV_PREFIX=/path/to/env DEEPCOIL_PYTHON_VERSION=3.8
41
- DEEPCOIL_VERSION=2.0.2`. The env prefix declared in
42
- `manifest.toml` `[runtime]` is `.external_envs/deepcoil`; the manifest
43
- `env_prefix` and the wrapper's `DEEPCOIL_ENV_PREFIX` override agree.
43
+ DEEPCOIL_VERSION=2.0.2`. The `manifest.toml` `[runtime]` prefix names the
44
+ legacy checkout fallback; the installer and runner prefer the user data root.
44
45
 
45
46
  ## Usage
46
47
 
47
48
  ```bash
48
- DEEPCOIL_ENV_PREFIX="$PWD/.external_envs/deepcoil" \
49
49
  tools/DeepCoil/run -i in.fasta -out_path /tmp/dc_out -n_cpu 4
50
50
  tools/DeepCoil/run --check
51
51
  ```
@@ -58,4 +58,4 @@ DeepCoil sanitizes output filenames (alnum + `_`). Writes
58
58
  ## Attribution
59
59
 
60
60
  Reference the DeepCoil meta-server page / Ludwiczak et al. (2019) when
61
- publishing scores produced by this tool.
61
+ publishing scores produced by this tool.
@@ -15,4 +15,4 @@ description = "Writes per-accession '<safe_id>.out' tab-separated files (aa, cc,
15
15
 
16
16
  [install]
17
17
  command = "bash tools/DeepCoil/install.sh"
18
- hint = "DeepCoil has no upstream license (not redistributable). Build the isolated Python 3.8 conda env with deepcoil==2.0.2: bash tools/DeepCoil/install.sh (env at .external_envs/deepcoil; override with DEEPCOIL_ENV_PREFIX)."
18
+ hint = "DeepCoil has no upstream license (not redistributable). Install the isolated Python 3.8 env with deepcoil==2.0.2: bash tools/DeepCoil/install.sh (default: ~/.local/share/phasepred/envs/deepcoil; override with DEEPCOIL_ENV_PREFIX)."
@@ -43,8 +43,9 @@ bash tools/PScore/install.sh --check # verify predictor + DBS present
43
43
 
44
44
  ## Usage
45
45
 
46
- Run from anywhere; the wrapper `cd`s into `SourceCodeS2/` because the
47
- predictor reads `DBS/` relative to its own location:
46
+ Run from anywhere with relative or absolute FASTA and output paths. The wrapper
47
+ uses the installed user-data `SourceCodeS2/DBS/` when the checkout has no DBS,
48
+ then changes into `SourceCodeS2/` as required by the predictor:
48
49
 
49
50
  ```bash
50
51
  tools/PScore/run input.fasta -output pscore.tsv -overwrite -mute
@@ -62,4 +63,4 @@ Standard output: one `PScore: <value> >ACC` line per scored accession
62
63
 
63
64
  Carry the reference above and the CC-BY 4.0 notice. The archived
64
65
  `SourceCodeS2/README.txt` documents the original authors. Data derived from
65
- the upstream `DBS/` must be attributed to Vernon et al. (2018).
66
+ the upstream `DBS/` must be attributed to Vernon et al. (2018).
@@ -85,7 +85,7 @@ policy="$(manifest_get sha256_policy)"
85
85
  if [[ "$mode" == "check" ]]; then
86
86
  if available_in "$target"; then
87
87
  echo "PScore: ok ($target)"
88
- exec "$pkg_dir/run" --check
88
+ exec "$target/run" --check
89
89
  fi
90
90
  if available_in "$pkg_dir"; then
91
91
  echo "PScore: ok ($pkg_dir, vendored checkout)"
@@ -28,4 +28,4 @@ description = "One 'PScore: <value> >ACC' line per scored accession (via stdou
28
28
 
29
29
  [install]
30
30
  command = "bash tools/PScore/install.sh"
31
- hint = "PScore code is vendored (CC-BY 4.0, eLife 31486). Data (DBS) is gitignored: bash tools/PScore/install.sh --check verifies script + DBS."
31
+ hint = "PScore is unavailable. Install its code and DBS with: bash tools/PScore/install.sh (then verify: bash tools/PScore/install.sh --check)."
@@ -12,6 +12,27 @@ pkg_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
  src_dir="$pkg_dir/SourceCodeS2"
13
13
  script="$src_dir/elife_phase_separation_predictor.py"
14
14
 
15
+ # The installer writes DBS into the user data root, not the checkout. A
16
+ # checkout runner can use that complete installation when its local DBS is
17
+ # absent. An installed runner continues to use its adjacent SourceCodeS2.
18
+ if [[ ! -d "$src_dir/DBS" ]]; then
19
+ data_root=""
20
+ if [[ -n "${PHASEPRED_DATA_ROOT:-}" ]]; then
21
+ data_root="$PHASEPRED_DATA_ROOT"
22
+ elif [[ -n "${XDG_DATA_HOME:-}" ]]; then
23
+ data_root="$XDG_DATA_HOME/phasepred"
24
+ elif [[ -n "${HOME:-}" ]]; then
25
+ data_root="$HOME/.local/share/phasepred"
26
+ fi
27
+ if [[ -n "$data_root" ]]; then
28
+ installed_src="$data_root/pscore/SourceCodeS2"
29
+ if [[ -f "$installed_src/elife_phase_separation_predictor.py" && -d "$installed_src/DBS" ]]; then
30
+ src_dir="$(cd "$installed_src" && pwd -P)"
31
+ script="$src_dir/elife_phase_separation_predictor.py"
32
+ fi
33
+ fi
34
+ fi
35
+
15
36
  if [[ "${1:-}" == "--check" ]]; then
16
37
  if [[ ! -f "$script" ]]; then
17
38
  echo "PScore predictor script missing: $script" >&2
@@ -38,6 +59,10 @@ if [[ ! -f "$script" ]]; then
38
59
  echo "PScore predictor script missing: $script" >&2
39
60
  exit 1
40
61
  fi
62
+ if [[ ! -d "$src_dir/DBS" ]]; then
63
+ echo "PScore DBS data missing: $src_dir/DBS (gitignored). Install with: bash $pkg_dir/install.sh" >&2
64
+ exit 1
65
+ fi
41
66
 
42
67
  python_cmd=""
43
68
  for cand in "${PHASEPRED_PYTHON:-}" python3 python; do
@@ -52,5 +77,17 @@ if [[ -z "$python_cmd" ]]; then
52
77
  exit 1
53
78
  fi
54
79
 
80
+ # The predictor must run from SourceCodeS2 so its relative DBS path works.
81
+ # Resolve the caller's relative FASTA and -output paths before changing cwd.
82
+ args=("$@")
83
+ if [[ "${args[0]}" != /* ]]; then
84
+ args[0]="$PWD/${args[0]}"
85
+ fi
86
+ for ((i = 1; i < ${#args[@]} - 1; i++)); do
87
+ if [[ "${args[i]}" == "-output" && "${args[i+1]}" != /* ]]; then
88
+ args[i+1]="$PWD/${args[i+1]}"
89
+ fi
90
+ done
91
+
55
92
  cd "$src_dir"
56
- exec "$python_cmd" "$script" "$@"
93
+ exec "$python_cmd" "$script" "${args[@]}"
@@ -58,6 +58,14 @@ class FeatureSchemaError(ValueError):
58
58
  """Raised when feature inputs do not satisfy a model schema."""
59
59
 
60
60
 
61
+ def compute_fcr(sequence: str) -> float:
62
+ """Charged-residue fraction; defined even when another scale lacks a residue."""
63
+ normalized = sequence.upper()
64
+ if not normalized:
65
+ raise FeatureSchemaError("Cannot compute features for an empty sequence")
66
+ return sum(residue in CHARGED_RESIDUES for residue in normalized) / len(normalized)
67
+
68
+
61
69
  def compute_native_features(sequence: str) -> dict[str, float]:
62
70
  normalized = sequence.upper()
63
71
  if not normalized:
@@ -69,7 +77,7 @@ def compute_native_features(sequence: str) -> dict[str, float]:
69
77
  return {
70
78
  "length": float(length),
71
79
  "Hydropathy": SequenceParameters(normalized).get_uversky_hydropathy(),
72
- "FCR": sum(1 for residue in normalized if residue in CHARGED_RESIDUES) / length,
80
+ "FCR": compute_fcr(normalized),
73
81
  }
74
82
 
75
83
 
@@ -33,6 +33,7 @@ def compute_all_features(
33
33
  from catgranule import CatGranuleInputError, score_sequence
34
34
 
35
35
  from phasepred import tools
36
+ from phasepred.features import compute_fcr
36
37
  from phasepred.features import compute_native_features as _native
37
38
 
38
39
  t_start = time.time()
@@ -55,9 +56,9 @@ def compute_all_features(
55
56
  native_rows.append(
56
57
  {
57
58
  "UniprotEntry": r["accession"],
58
- "length": float("nan"),
59
+ "length": float(len(seq)),
59
60
  "Hydropathy": float("nan"),
60
- "FCR": float("nan"),
61
+ "FCR": compute_fcr(seq) if seq else float("nan"),
61
62
  }
62
63
  )
63
64
 
@@ -212,4 +213,4 @@ def _model_predict_proba(model, X: pd.DataFrame) -> np.ndarray:
212
213
  if hasattr(model, "estimator"):
213
214
  # ModelArtifact wrapper
214
215
  return model.estimator.predict_proba(X)
215
- return model.predict_proba(X)
216
+ return model.predict_proba(X)
@@ -23,7 +23,7 @@ from typing import cast
23
23
  import pandas as pd
24
24
 
25
25
  from phasepred import tools
26
- from phasepred.features import CHARGED_RESIDUES, compute_native_features
26
+ from phasepred.features import CHARGED_RESIDUES, compute_fcr, compute_native_features
27
27
 
28
28
  # Tool vocabulary (web API order).
29
29
  TOOL_NAMES = [
@@ -94,7 +94,10 @@ def compute_tool_features(
94
94
  try:
95
95
  native[r["accession"]] = compute_native_features(str(r["sequence"]).upper())
96
96
  except Exception:
97
- native[r["accession"]] = {}
97
+ seq = str(r["sequence"]).upper()
98
+ native[r["accession"]] = {
99
+ "FCR": compute_fcr(seq) if seq else float("nan")
100
+ }
98
101
 
99
102
  if "hydropathy" in requested:
100
103
  for i, r in enumerate(records):