ptmreloc 0.1.0__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.
ptmreloc-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BioJazz Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.4
2
+ Name: ptmreloc
3
+ Version: 0.1.0
4
+ Summary: Prior-knowledge (PhosphoSitePlus) guided relocalization of low-confidence PTM sites on peptides
5
+ Author: Song Feng
6
+ License-Expression: MIT
7
+ Keywords: proteomics,phosphoproteomics,PTM,phosphosite,site localization,AScore,PhosphoSitePlus,mass spectrometry
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: numpy>=1.22
18
+ Requires-Dist: pandas>=1.4
19
+ Requires-Dist: scipy>=1.8
20
+ Provides-Extra: excel
21
+ Requires-Dist: openpyxl; extra == "excel"
22
+ Provides-Extra: parquet
23
+ Requires-Dist: pyarrow; extra == "parquet"
24
+ Provides-Extra: test
25
+ Requires-Dist: pytest; extra == "test"
26
+ Dynamic: license-file
27
+
28
+ # ptmreloc
29
+
30
+ Prior-knowledge guided relocalization of low-confidence PTM (phosphorylation) sites on peptides.
31
+
32
+ When the MS2 fragment evidence cannot localize a site (low AScore), `ptmreloc` reassigns it
33
+ to the candidate residue best supported by PhosphoSitePlus (PSP). Each candidate site gets a score
34
+
35
+ ```
36
+ S_F = w_H * S_H + w_L * S_L + w_D * S_D
37
+ ```
38
+
39
+ * `S_H` – PSP high-throughput (MS) evidence, normalized within the peptide
40
+ * `S_L` – PSP low-throughput (literature) evidence, normalized within the peptide
41
+ * `S_D` – proximity to the originally assigned site
42
+
43
+ The top-n scoring sites (n = number of sites originally assigned) are kept for every
44
+ peptide with `AScore <= threshold`. Ties go to the original site, so peptides without
45
+ PSP evidence are left alone.
46
+
47
+ The weights are optimized against two independent references: **Gold Standard** sites (GS)
48
+ and **Functional Landscape** scores (FUN). The objective is a composite **Δ_REASSIGN**,
49
+ the geometric mean of the fraction of achievable GS improvement and the fraction of
50
+ achievable FUN improvement that a weight set realizes.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install ptmreloc # numpy, pandas, scipy
56
+ pip install "ptmreloc[excel]" # + openpyxl, to read .xlsx inputs
57
+ ```
58
+
59
+ From a source checkout: `pip install -e ".[test]"`.
60
+
61
+ ## Input
62
+
63
+ A peptide table with (column names configurable):
64
+
65
+ | column | example |
66
+ |---------|----------------------------|
67
+ | UniProt | `Q93015` |
68
+ | Peptide | `-.MELILSTS*PAELTLDPACQPK.L` (PTM label after the residue; other mod symbols are preserved) |
69
+ | Residue | `S8s` (multi-site: `S8sT10t`); optional, see below |
70
+ | AScore | `14.04` |
71
+
72
+ If there is no `Residue` column, protein positions are annotated by locating each peptide in
73
+ its protein sequence (first occurrence). This uses the default human proteome or your own
74
+ `fasta=`. Rows that cannot be located are passed through unchanged.
75
+
76
+ ## Reference database
77
+
78
+ `ptmreloc` uses a ready-to-use human reference database, so nothing needs to be preprocessed.
79
+ The files are not part of the installed package. They are **downloaded once, on first use**
80
+ (about 68 MB) from Zenodo ([10.5281/zenodo.23997751](https://doi.org/10.5281/zenodo.23997751))
81
+ into a per-user cache folder, and checked against SHA-256 checksums:
82
+
83
+ | dataset | file | used for |
84
+ |---|---|---|
85
+ | `psp` | `phospho_site_plus_human_clustered_indexed_by_name.csv` | PhosphoSitePlus HTP/LTP evidence (scoring) |
86
+ | `gold` | `gold_standard_sites_reindexed.tsv` | Gold Standard sites (optimization / evaluation) |
87
+ | `fun` | `functional_landscape_sites_reindexed.tsv` | Functional Landscape scores (optimization / evaluation) |
88
+ | `fasta` | `UP000005640_9606.fasta` | UniProt human reference proteome (residue annotation) |
89
+
90
+ ```bash
91
+ ptmreloc download # optional: fetch everything now (e.g. before going offline)
92
+ ptmreloc info # where each file is read from, cache folder, download URL
93
+ ```
94
+
95
+ Only the files you need are fetched. `reassign` needs only `psp`, plus `fasta` when the
96
+ input has no `Residue` column.
97
+
98
+ **Data terms.** The reference files are derived from third-party resources and are not
99
+ covered by this package's MIT license. PhosphoSitePlus data are subject to the
100
+ [PhosphoSitePlus terms of use](https://www.phosphosite.org/staticDownloads), and the UniProt
101
+ proteome is CC BY 4.0. Please cite the original resources when you use them.
102
+
103
+ ### Using your own data
104
+
105
+ Each dataset can be replaced with your own, individually, as a file path or DataFrame
106
+ (pkl / csv / tsv / parquet / xlsx; raw PSP `.txt` downloads work). Nothing is downloaded
107
+ for datasets you supply:
108
+
109
+ * PSP: `UniProt` or `ACC_ID`, `MOD_RSD` (e.g. `S8-p`), `MS_LIT`, `MS_CST`, `LT_LIT`
110
+ * Gold Standard: `UniProt`, `Position in target protein`
111
+ * Functional Landscape: `UniProt`, `Position`, `Functional_score`
112
+ * FASTA: UniProt-style headers (`>sp|P12345|NAME_HUMAN`) or plain IDs
113
+
114
+ ```python
115
+ pr.load_reference() # all default data
116
+ pr.load_reference(psp="my_psp.txt") # own PSP, default GS/FUN
117
+ pr.load_reference(gold="my_gs.tsv", fun=False) # default PSP, own GS, no FUN
118
+ pr.load_reference(database="path/to/other_db/") # a folder with the same file names
119
+ ```
120
+
121
+ Environment variables:
122
+
123
+ | variable | effect |
124
+ |---|---|
125
+ | `PTMRELOC_DATABASE` | folder with the reference files (checked before the cache) |
126
+ | `PTMRELOC_CACHE_DIR` | download cache folder |
127
+ | `PTMRELOC_DATABASE_URL` | alternative download location (a base URL holding the files) |
128
+ | `PTMRELOC_AUTO_DOWNLOAD=0` | never download automatically |
129
+
130
+ ## Default weights
131
+
132
+ You don't have to run the optimization. Without explicit weights, `reassign` and `evaluate` use
133
+ the weights found by Monte Carlo sampling in `sampling/Optimizing_Reassignment.py`
134
+ (the median of the best 5% of trials) with an AScore threshold of 30:
135
+
136
+ | `DEFAULT_WEIGHTS` | w_H | w_L | w_D |
137
+ |---|---|---|---|
138
+ | `"medians"` (default) | 0.40936 | 0.0028834 | 0.0044392 |
139
+
140
+ Other presets you can pass by name: `"fun_medians"`, `"gs_medians"` (best 5% ranked by FUN
141
+ or by GS alone) and `"htp_only"` (1, 0, 0). They were derived with the default (`legacy`)
142
+ feature settings.
143
+
144
+ ## Python library
145
+
146
+ ```python
147
+ import ptmreloc as pr
148
+
149
+ # Tables may be pandas DataFrames or file paths. Reference data defaults to the human database.
150
+
151
+ # 1. reassign with the default weights - no optimization, no reference files needed
152
+ out = pr.reassign(peptides) # == pr.reassign(peptides, weights="medians")
153
+
154
+ # 2. optimize weights for your data (against the default GS/FUN)
155
+ res = pr.optimize(peptides, n_samples=2000, threshold=30, out_dir="opt/")
156
+ print(res.summary()) # res.weights, res.trials, res.evaluation, res.by_ascore
157
+
158
+ # 3. reassign / evaluate with the optimized weights
159
+ out = pr.reassign(peptides, weights=res, output="reassigned.tsv")
160
+ rep = pr.evaluate(peptides, weights="opt/weights.json")
161
+ print(rep.summary()) # rep.overall (dict), rep.by_ascore (DataFrame)
162
+
163
+ # compare several weight sets on the same data (default: all presets)
164
+ pr.compare_weights(peptides, weight_sets={"default": None, "mine": res, "htp": "htp_only"})
165
+
166
+ # own reference data: pass any of psp= / gold= / fun= / fasta=, or a prebuilt reference
167
+ ref = pr.load_reference(psp="my_psp.txt") # build once, reuse across calls
168
+ out = pr.reassign(peptides, ref)
169
+ ```
170
+
171
+ | function | needs | returns |
172
+ |---|---|---|
173
+ | `reassign(peptides, psp=None, weights=None, threshold=None, ...)` | PSP | input table + relocalization columns |
174
+ | `optimize(peptides, psp=None, gold=None, fun=None, threshold=30, n_samples=2000, out_dir=None, ...)` | PSP, GS and/or FUN | `OptimizationResult` |
175
+ | `evaluate(peptides, psp=None, gold=None, fun=None, weights=None, threshold=None, bins=...)` | PSP, GS and/or FUN | `EvaluationReport` |
176
+ | `compare_weights(peptides, psp=None, gold=None, fun=None, weight_sets=None)` | PSP, GS and/or FUN | DataFrame |
177
+ | `load_reference(psp=None, gold=None, fun=None, database=None)` | | `ReferenceDB` |
178
+
179
+ `None` means the default dataset and `False` disables GS or FUN. All functions also take `fasta=`.
180
+
181
+ `weights` can be `None` (defaults), a preset name, a `weights.json` path, an `OptimizationResult`,
182
+ a dict `{"w_H", "w_L", "w_D"}` or a 3-tuple. A weights file or result also supplies its threshold
183
+ and feature settings, unless you override them with `threshold=` or `config=`. Column names
184
+ can be changed with `columns={"uniprot": ..., "peptide": ..., "residue": ..., "ascore": ...}`.
185
+
186
+ `reassign` appends `NewPeptide`, `NewResidue`, `Reassigned`, `ReassignStatus`
187
+ (`eligible` / `above_threshold` / `unparsed`), `OriginalSiteProb`, `NewSiteProb` and
188
+ `CandidateSiteProbs` (every candidate with its share of S_F).
189
+
190
+ Lower-level building blocks are exported too: `build_candidate_table`, `choose`,
191
+ `evaluate_selection`, `evaluate_by_ascore`, `optimize_weights` and `Reassigner`.
192
+
193
+ ## Command line
194
+
195
+ ```bash
196
+ ptmreloc info # reference data files, default weights
197
+
198
+ # reassign with the default weights and the default reference data
199
+ ptmreloc reassign -i peptides.tsv -o reassigned.tsv
200
+
201
+ # optimize weights (Monte Carlo + differential-evolution refinement, 20% proteins held out)
202
+ ptmreloc optimize -i peptides.tsv --threshold 30 --n-samples 2000 -o opt/
203
+ # -> opt/weights.json, trials.csv, evaluation.csv, metrics_by_ascore.csv
204
+
205
+ # reassign with optimized weights, a preset, or explicit values
206
+ ptmreloc reassign -i peptides.tsv --weights opt/weights.json -o reassigned.tsv
207
+ ptmreloc reassign -i peptides.tsv --weights htp_only -o reassigned.tsv
208
+ ptmreloc reassign -i peptides.tsv --w 1 0 0.01 --threshold 20 -o reassigned.tsv
209
+
210
+ # evaluate weights (default if none given) per AScore bin
211
+ ptmreloc evaluate -i peptides.tsv
212
+
213
+ # own reference data: any of --psp / --gold / --fun / --fasta (or --database DIR);
214
+ # use --gold none / --fun none to leave one out
215
+ ptmreloc optimize -i peptides.tsv --psp my_psp.txt --gold my_gs.tsv --fun none -o opt/
216
+ ```
217
+
218
+ ## Optimization details
219
+
220
+ * **Search.** Weights are sampled log-uniformly in `10^[-3, 0]`, as in the manuscript.
221
+ Differential evolution, seeded with the best samples, then refines the result. The
222
+ objective is an arg-max and therefore piecewise constant, so the search is derivative-free.
223
+ * **Recommended weights.** These are the per-weight median of the top 5% Monte Carlo trials
224
+ (the manuscript's "median of best 5%"). That is more robust than the single best trial,
225
+ and `evaluation.csv` reports both on the training and held-out proteins.
226
+ * **Scale invariance.** S_F rankings are unchanged when all weights are multiplied by the
227
+ same constant, so only the ratios matter. `normalized_weights` in `weights.json` sum to 1.
228
+ * **Metrics.** `delta_gs` and `delta_fun` are changes per site. `random_delta_*` is the
229
+ exact expectation of uniform random reassignment, and `oracle_delta_*` is the best
230
+ achievable change. `gs_gain` and `fun_gain` equal Δ / oracle Δ. `composite_trial_relative`
231
+ in `trials.csv` reproduces the manuscript's across-trial min-max scaled version.
232
+ * **Speed.** Candidate features are built once (about 1 s for 120k PSMs). Each weight
233
+ trial is then a vectorized group arg-max (a few ms), so thousands of trials take seconds.
234
+
235
+ ### Feature options (`FeatureConfig` / CLI flags)
236
+
237
+ | option | `legacy` (default) | alternative |
238
+ |---|---|---|
239
+ | `evidence_transform` | `log10(log2(n+1)+1)`, sum-normalized (original scripts) | `log`: `log(n+1)`, `raw`: `n` (manuscript text) |
240
+ | `distance_mode` | `1 - d/(d_max+1)`, sum-normalized (original scripts) | `inverse`: `1/(d+1)`, zero when AScore = 0 (manuscript text) |
241
+
242
+ The defaults reproduce `sampling/Optimizing_Reassignment.py`. Note that in both distance
243
+ variants, multiplying by AScore cancels out once the score is normalized within the
244
+ peptide. AScore only enters through the threshold, plus the AScore = 0 case in `inverse` mode.
@@ -0,0 +1,217 @@
1
+ # ptmreloc
2
+
3
+ Prior-knowledge guided relocalization of low-confidence PTM (phosphorylation) sites on peptides.
4
+
5
+ When the MS2 fragment evidence cannot localize a site (low AScore), `ptmreloc` reassigns it
6
+ to the candidate residue best supported by PhosphoSitePlus (PSP). Each candidate site gets a score
7
+
8
+ ```
9
+ S_F = w_H * S_H + w_L * S_L + w_D * S_D
10
+ ```
11
+
12
+ * `S_H` – PSP high-throughput (MS) evidence, normalized within the peptide
13
+ * `S_L` – PSP low-throughput (literature) evidence, normalized within the peptide
14
+ * `S_D` – proximity to the originally assigned site
15
+
16
+ The top-n scoring sites (n = number of sites originally assigned) are kept for every
17
+ peptide with `AScore <= threshold`. Ties go to the original site, so peptides without
18
+ PSP evidence are left alone.
19
+
20
+ The weights are optimized against two independent references: **Gold Standard** sites (GS)
21
+ and **Functional Landscape** scores (FUN). The objective is a composite **Δ_REASSIGN**,
22
+ the geometric mean of the fraction of achievable GS improvement and the fraction of
23
+ achievable FUN improvement that a weight set realizes.
24
+
25
+ ## Install
26
+
27
+ ```bash
28
+ pip install ptmreloc # numpy, pandas, scipy
29
+ pip install "ptmreloc[excel]" # + openpyxl, to read .xlsx inputs
30
+ ```
31
+
32
+ From a source checkout: `pip install -e ".[test]"`.
33
+
34
+ ## Input
35
+
36
+ A peptide table with (column names configurable):
37
+
38
+ | column | example |
39
+ |---------|----------------------------|
40
+ | UniProt | `Q93015` |
41
+ | Peptide | `-.MELILSTS*PAELTLDPACQPK.L` (PTM label after the residue; other mod symbols are preserved) |
42
+ | Residue | `S8s` (multi-site: `S8sT10t`); optional, see below |
43
+ | AScore | `14.04` |
44
+
45
+ If there is no `Residue` column, protein positions are annotated by locating each peptide in
46
+ its protein sequence (first occurrence). This uses the default human proteome or your own
47
+ `fasta=`. Rows that cannot be located are passed through unchanged.
48
+
49
+ ## Reference database
50
+
51
+ `ptmreloc` uses a ready-to-use human reference database, so nothing needs to be preprocessed.
52
+ The files are not part of the installed package. They are **downloaded once, on first use**
53
+ (about 68 MB) from Zenodo ([10.5281/zenodo.23997751](https://doi.org/10.5281/zenodo.23997751))
54
+ into a per-user cache folder, and checked against SHA-256 checksums:
55
+
56
+ | dataset | file | used for |
57
+ |---|---|---|
58
+ | `psp` | `phospho_site_plus_human_clustered_indexed_by_name.csv` | PhosphoSitePlus HTP/LTP evidence (scoring) |
59
+ | `gold` | `gold_standard_sites_reindexed.tsv` | Gold Standard sites (optimization / evaluation) |
60
+ | `fun` | `functional_landscape_sites_reindexed.tsv` | Functional Landscape scores (optimization / evaluation) |
61
+ | `fasta` | `UP000005640_9606.fasta` | UniProt human reference proteome (residue annotation) |
62
+
63
+ ```bash
64
+ ptmreloc download # optional: fetch everything now (e.g. before going offline)
65
+ ptmreloc info # where each file is read from, cache folder, download URL
66
+ ```
67
+
68
+ Only the files you need are fetched. `reassign` needs only `psp`, plus `fasta` when the
69
+ input has no `Residue` column.
70
+
71
+ **Data terms.** The reference files are derived from third-party resources and are not
72
+ covered by this package's MIT license. PhosphoSitePlus data are subject to the
73
+ [PhosphoSitePlus terms of use](https://www.phosphosite.org/staticDownloads), and the UniProt
74
+ proteome is CC BY 4.0. Please cite the original resources when you use them.
75
+
76
+ ### Using your own data
77
+
78
+ Each dataset can be replaced with your own, individually, as a file path or DataFrame
79
+ (pkl / csv / tsv / parquet / xlsx; raw PSP `.txt` downloads work). Nothing is downloaded
80
+ for datasets you supply:
81
+
82
+ * PSP: `UniProt` or `ACC_ID`, `MOD_RSD` (e.g. `S8-p`), `MS_LIT`, `MS_CST`, `LT_LIT`
83
+ * Gold Standard: `UniProt`, `Position in target protein`
84
+ * Functional Landscape: `UniProt`, `Position`, `Functional_score`
85
+ * FASTA: UniProt-style headers (`>sp|P12345|NAME_HUMAN`) or plain IDs
86
+
87
+ ```python
88
+ pr.load_reference() # all default data
89
+ pr.load_reference(psp="my_psp.txt") # own PSP, default GS/FUN
90
+ pr.load_reference(gold="my_gs.tsv", fun=False) # default PSP, own GS, no FUN
91
+ pr.load_reference(database="path/to/other_db/") # a folder with the same file names
92
+ ```
93
+
94
+ Environment variables:
95
+
96
+ | variable | effect |
97
+ |---|---|
98
+ | `PTMRELOC_DATABASE` | folder with the reference files (checked before the cache) |
99
+ | `PTMRELOC_CACHE_DIR` | download cache folder |
100
+ | `PTMRELOC_DATABASE_URL` | alternative download location (a base URL holding the files) |
101
+ | `PTMRELOC_AUTO_DOWNLOAD=0` | never download automatically |
102
+
103
+ ## Default weights
104
+
105
+ You don't have to run the optimization. Without explicit weights, `reassign` and `evaluate` use
106
+ the weights found by Monte Carlo sampling in `sampling/Optimizing_Reassignment.py`
107
+ (the median of the best 5% of trials) with an AScore threshold of 30:
108
+
109
+ | `DEFAULT_WEIGHTS` | w_H | w_L | w_D |
110
+ |---|---|---|---|
111
+ | `"medians"` (default) | 0.40936 | 0.0028834 | 0.0044392 |
112
+
113
+ Other presets you can pass by name: `"fun_medians"`, `"gs_medians"` (best 5% ranked by FUN
114
+ or by GS alone) and `"htp_only"` (1, 0, 0). They were derived with the default (`legacy`)
115
+ feature settings.
116
+
117
+ ## Python library
118
+
119
+ ```python
120
+ import ptmreloc as pr
121
+
122
+ # Tables may be pandas DataFrames or file paths. Reference data defaults to the human database.
123
+
124
+ # 1. reassign with the default weights - no optimization, no reference files needed
125
+ out = pr.reassign(peptides) # == pr.reassign(peptides, weights="medians")
126
+
127
+ # 2. optimize weights for your data (against the default GS/FUN)
128
+ res = pr.optimize(peptides, n_samples=2000, threshold=30, out_dir="opt/")
129
+ print(res.summary()) # res.weights, res.trials, res.evaluation, res.by_ascore
130
+
131
+ # 3. reassign / evaluate with the optimized weights
132
+ out = pr.reassign(peptides, weights=res, output="reassigned.tsv")
133
+ rep = pr.evaluate(peptides, weights="opt/weights.json")
134
+ print(rep.summary()) # rep.overall (dict), rep.by_ascore (DataFrame)
135
+
136
+ # compare several weight sets on the same data (default: all presets)
137
+ pr.compare_weights(peptides, weight_sets={"default": None, "mine": res, "htp": "htp_only"})
138
+
139
+ # own reference data: pass any of psp= / gold= / fun= / fasta=, or a prebuilt reference
140
+ ref = pr.load_reference(psp="my_psp.txt") # build once, reuse across calls
141
+ out = pr.reassign(peptides, ref)
142
+ ```
143
+
144
+ | function | needs | returns |
145
+ |---|---|---|
146
+ | `reassign(peptides, psp=None, weights=None, threshold=None, ...)` | PSP | input table + relocalization columns |
147
+ | `optimize(peptides, psp=None, gold=None, fun=None, threshold=30, n_samples=2000, out_dir=None, ...)` | PSP, GS and/or FUN | `OptimizationResult` |
148
+ | `evaluate(peptides, psp=None, gold=None, fun=None, weights=None, threshold=None, bins=...)` | PSP, GS and/or FUN | `EvaluationReport` |
149
+ | `compare_weights(peptides, psp=None, gold=None, fun=None, weight_sets=None)` | PSP, GS and/or FUN | DataFrame |
150
+ | `load_reference(psp=None, gold=None, fun=None, database=None)` | | `ReferenceDB` |
151
+
152
+ `None` means the default dataset and `False` disables GS or FUN. All functions also take `fasta=`.
153
+
154
+ `weights` can be `None` (defaults), a preset name, a `weights.json` path, an `OptimizationResult`,
155
+ a dict `{"w_H", "w_L", "w_D"}` or a 3-tuple. A weights file or result also supplies its threshold
156
+ and feature settings, unless you override them with `threshold=` or `config=`. Column names
157
+ can be changed with `columns={"uniprot": ..., "peptide": ..., "residue": ..., "ascore": ...}`.
158
+
159
+ `reassign` appends `NewPeptide`, `NewResidue`, `Reassigned`, `ReassignStatus`
160
+ (`eligible` / `above_threshold` / `unparsed`), `OriginalSiteProb`, `NewSiteProb` and
161
+ `CandidateSiteProbs` (every candidate with its share of S_F).
162
+
163
+ Lower-level building blocks are exported too: `build_candidate_table`, `choose`,
164
+ `evaluate_selection`, `evaluate_by_ascore`, `optimize_weights` and `Reassigner`.
165
+
166
+ ## Command line
167
+
168
+ ```bash
169
+ ptmreloc info # reference data files, default weights
170
+
171
+ # reassign with the default weights and the default reference data
172
+ ptmreloc reassign -i peptides.tsv -o reassigned.tsv
173
+
174
+ # optimize weights (Monte Carlo + differential-evolution refinement, 20% proteins held out)
175
+ ptmreloc optimize -i peptides.tsv --threshold 30 --n-samples 2000 -o opt/
176
+ # -> opt/weights.json, trials.csv, evaluation.csv, metrics_by_ascore.csv
177
+
178
+ # reassign with optimized weights, a preset, or explicit values
179
+ ptmreloc reassign -i peptides.tsv --weights opt/weights.json -o reassigned.tsv
180
+ ptmreloc reassign -i peptides.tsv --weights htp_only -o reassigned.tsv
181
+ ptmreloc reassign -i peptides.tsv --w 1 0 0.01 --threshold 20 -o reassigned.tsv
182
+
183
+ # evaluate weights (default if none given) per AScore bin
184
+ ptmreloc evaluate -i peptides.tsv
185
+
186
+ # own reference data: any of --psp / --gold / --fun / --fasta (or --database DIR);
187
+ # use --gold none / --fun none to leave one out
188
+ ptmreloc optimize -i peptides.tsv --psp my_psp.txt --gold my_gs.tsv --fun none -o opt/
189
+ ```
190
+
191
+ ## Optimization details
192
+
193
+ * **Search.** Weights are sampled log-uniformly in `10^[-3, 0]`, as in the manuscript.
194
+ Differential evolution, seeded with the best samples, then refines the result. The
195
+ objective is an arg-max and therefore piecewise constant, so the search is derivative-free.
196
+ * **Recommended weights.** These are the per-weight median of the top 5% Monte Carlo trials
197
+ (the manuscript's "median of best 5%"). That is more robust than the single best trial,
198
+ and `evaluation.csv` reports both on the training and held-out proteins.
199
+ * **Scale invariance.** S_F rankings are unchanged when all weights are multiplied by the
200
+ same constant, so only the ratios matter. `normalized_weights` in `weights.json` sum to 1.
201
+ * **Metrics.** `delta_gs` and `delta_fun` are changes per site. `random_delta_*` is the
202
+ exact expectation of uniform random reassignment, and `oracle_delta_*` is the best
203
+ achievable change. `gs_gain` and `fun_gain` equal Δ / oracle Δ. `composite_trial_relative`
204
+ in `trials.csv` reproduces the manuscript's across-trial min-max scaled version.
205
+ * **Speed.** Candidate features are built once (about 1 s for 120k PSMs). Each weight
206
+ trial is then a vectorized group arg-max (a few ms), so thousands of trials take seconds.
207
+
208
+ ### Feature options (`FeatureConfig` / CLI flags)
209
+
210
+ | option | `legacy` (default) | alternative |
211
+ |---|---|---|
212
+ | `evidence_transform` | `log10(log2(n+1)+1)`, sum-normalized (original scripts) | `log`: `log(n+1)`, `raw`: `n` (manuscript text) |
213
+ | `distance_mode` | `1 - d/(d_max+1)`, sum-normalized (original scripts) | `inverse`: `1/(d+1)`, zero when AScore = 0 (manuscript text) |
214
+
215
+ The defaults reproduce `sampling/Optimizing_Reassignment.py`. Note that in both distance
216
+ variants, multiplying by AScore cancels out once the score is normalized within the
217
+ peptide. AScore only enters through the threshold, plus the AScore = 0 case in `inverse` mode.
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ptmreloc"
7
+ version = "0.1.0"
8
+ description = "Prior-knowledge (PhosphoSitePlus) guided relocalization of low-confidence PTM sites on peptides"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [{ name = "Song Feng" }]
14
+ keywords = ["proteomics", "phosphoproteomics", "PTM", "phosphosite", "site localization",
15
+ "AScore", "PhosphoSitePlus", "mass spectrometry"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Science/Research",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
23
+ ]
24
+ dependencies = ["numpy>=1.22", "pandas>=1.4", "scipy>=1.8"]
25
+
26
+ [project.optional-dependencies]
27
+ excel = ["openpyxl"]
28
+ parquet = ["pyarrow"]
29
+ test = ["pytest"]
30
+
31
+ [project.scripts]
32
+ ptmreloc = "ptmreloc.cli:main"
33
+
34
+ # Code only: the reference data (database/) is downloaded on first use, not packaged.
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+
38
+ [tool.pytest.ini_options]
39
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,50 @@
1
+ """ptmreloc — prior-knowledge guided relocalization of low-confidence PTM sites.
2
+
3
+ Quick start. The human reference database (PhosphoSitePlus, Gold Standard, Functional
4
+ Landscape, UniProt FASTA) is downloaded once on first use, unless you pass your own tables::
5
+
6
+ import ptmreloc as pr
7
+
8
+ out = pr.reassign(peptides) # default weights, default PSP
9
+ res = pr.optimize(peptides, out_dir="opt/") # optimize against default GS/FUN
10
+ out = pr.reassign(peptides, weights=res) # or weights="opt/weights.json"
11
+ rep = pr.evaluate(peptides, weights=res); print(rep.summary())
12
+
13
+ # own data: any of psp= / gold= / fun= / fasta= (DataFrame or file path)
14
+ out = pr.reassign(peptides, psp="my_psp.tsv")
15
+
16
+ The lower-level building blocks (``build_candidate_table``, ``choose``,
17
+ ``evaluate_selection``, ``optimize_weights``, ``Reassigner``) are exported too.
18
+ """
19
+ from .api import EvaluationReport, compare_weights, evaluate, load_reference, optimize, reassign, resolve_weights
20
+ from .database import (DATABASE_FILES, annotate_residues, cache_dir, database_dir, database_file,
21
+ database_info, default_proteome, default_reference, download_database, read_fasta)
22
+ from .defaults import DEFAULT_THRESHOLD, DEFAULT_WEIGHTS, WEIGHT_PRESETS
23
+ from .engine import choose, site_scores
24
+ from .features import FEATURE_NAMES, WEIGHT_NAMES, CandidateTable, FeatureConfig, build_candidate_table
25
+ from .metrics import composite_score, evaluate_by_ascore, trial_relative_composite
26
+ from .metrics import evaluate as evaluate_selection
27
+ from .optimize import OptimizationResult, normalize_weights, optimize_weights
28
+ from .peptide import format_residue, parse_peptide, parse_residue, relabel
29
+ from .reassign import Reassigner, apply_selection, load_weights
30
+ from .reference import ReferenceDB, read_table, write_table
31
+
32
+ __version__ = "0.1.0"
33
+
34
+ __all__ = [
35
+ # high-level API
36
+ "optimize", "reassign", "evaluate", "compare_weights", "load_reference", "resolve_weights",
37
+ "EvaluationReport", "OptimizationResult",
38
+ # reference database
39
+ "DATABASE_FILES", "download_database", "cache_dir", "database_dir", "database_file", "database_info",
40
+ "default_reference",
41
+ "default_proteome", "read_fasta", "annotate_residues",
42
+ # defaults
43
+ "DEFAULT_WEIGHTS", "DEFAULT_THRESHOLD", "WEIGHT_PRESETS",
44
+ # building blocks
45
+ "ReferenceDB", "read_table", "write_table", "FeatureConfig", "CandidateTable", "build_candidate_table",
46
+ "FEATURE_NAMES", "WEIGHT_NAMES", "choose", "site_scores", "evaluate_selection", "evaluate_by_ascore",
47
+ "composite_score", "trial_relative_composite", "optimize_weights", "normalize_weights",
48
+ "Reassigner", "apply_selection", "load_weights", "parse_peptide", "parse_residue", "format_residue",
49
+ "relabel",
50
+ ]