|
| 1 | +# TODO: generalize child-count filtering in `LFQData` |
| 2 | + |
| 3 | +> `filter_proteins_by_peptide_count()` does not fit `LFQData`'s generic, |
| 4 | +> any-hierarchy-level nature, and its threshold lives in the wrong place |
| 5 | +> (`config$min_peptides_protein`). Reconsider both. |
| 6 | +
|
| 7 | +## Context |
| 8 | + |
| 9 | +`prolfquapp` is adding a minimum-peptides-per-parent-protein filter and |
| 10 | +deliberately does **not** reuse this prolfqua function (see |
| 11 | +`prolfquapp/TODO/TODO_expose_nr_peptides.md`). While investigating, two problems |
| 12 | +with the existing prolfqua API surfaced. This TODO records them for a separate |
| 13 | +prolfqua-side cleanup; it is not blocking the prolfquapp work. |
| 14 | + |
| 15 | +## Requirements |
| 16 | + |
| 17 | +- The child-count filter should match `LFQData`'s design: it works at **any |
| 18 | + hierarchy level** (protein→peptide, protein→precursor, peptide→fragment, …), |
| 19 | + parameterized by an explicit **parent key** and **child key**, not tied to the |
| 20 | + modelling `hierarchy_depth`. |
| 21 | +- The threshold should be an **explicit argument**, not read implicitly from a |
| 22 | + config field. |
| 23 | +- Backwards compatibility: the current no-arg `LFQData$filter_proteins_by_peptide_count()` |
| 24 | + is used by the `prolfquabenchmark` vignettes and the prolfqua test/vignette — |
| 25 | + their behavior must be preserved (or migrated deliberately). |
| 26 | + |
| 27 | +## Current state (verified in code) |
| 28 | + |
| 29 | +- Exported `filter_proteins_by_peptide_count(pdata, config)` |
| 30 | + (`R/LFQData.R:549-561`) delegates to `nr_B_in_A(pdata, config)` |
| 31 | + (`R/LFQData.R:520-529`): `level_a = config$hierarchy_keys_depth()`, |
| 32 | + `level_b = hierarchy_keys()[length(level_a) + 1]`, then keeps rows with |
| 33 | + `count >= config$min_peptides_protein` (`R/LFQData.R:554`). |
| 34 | +- **Depth coupling:** it counts the hierarchy level *just below the modelling |
| 35 | + depth*. For a peptide-level (`_PEPTIDE`) config with `hierarchy_depth = 2` |
| 36 | + there is no level below → `nr_B_in_A` warns "here is no B in A" and returns |
| 37 | + `NULL` → the filter is a **no-op**. Confirmed empirically in the review. |
| 38 | +- **Threshold source:** `config$min_peptides_protein` defaults to `2` |
| 39 | + (`R/AnalysisConfiguration.R:79-80`) — an implicit config field rather than an |
| 40 | + argument, so callers can't ask for a different level/threshold without mutating |
| 41 | + config. |
| 42 | +- **`LFQData$filter_proteins_by_peptide_count()`** (`R/LFQData.R:181-185`) is the |
| 43 | + no-arg method wrapper; used by `prolfquabenchmark` vignettes (multiple), |
| 44 | + `prolfqua` `test-LFQData.R:21`, and `vignettes/SimulateData.Rmd`. |
| 45 | + |
| 46 | +## Design (sketch) |
| 47 | + |
| 48 | +- Rework the core to accept **explicit `parent_key`, `child_key`, and `threshold`** |
| 49 | + arguments, independent of `hierarchy_depth`; count distinct `child_key` per |
| 50 | + `parent_key`, keep parents at/above `threshold`. |
| 51 | +- Keep a thin backwards-compatible `LFQData$filter_proteins_by_peptide_count()` |
| 52 | + that defaults `parent_key = hierarchy_keys()[1]`, `child_key = hierarchy_keys()[2]`, |
| 53 | + `threshold = config$min_peptides_protein`, so existing vignette/test call sites |
| 54 | + keep working. |
| 55 | +- Decide the fate of `config$min_peptides_protein`: keep it as the default |
| 56 | + source for the no-arg method, or deprecate in favor of an explicit argument. |
| 57 | + |
| 58 | +## Implementation plan (later) |
| 59 | + |
| 60 | +- [ ] Add explicit-key/threshold arguments to `filter_proteins_by_peptide_count()` |
| 61 | + (and/or `nr_B_in_A`), independent of `hierarchy_depth`. |
| 62 | +- [ ] Make the no-arg `LFQData$` method delegate with backwards-compatible |
| 63 | + defaults; verify `prolfquabenchmark` vignettes and `test-LFQData.R` still pass. |
| 64 | +- [ ] Decide whether to keep or deprecate `config$min_peptides_protein`. |
| 65 | +- [ ] Tests: filtering works at protein→peptide *and* peptide-level/nested shapes |
| 66 | + (the `_PEPTIDE` case that currently no-ops), at explicit thresholds. |
| 67 | + |
| 68 | +## Open questions |
| 69 | + |
| 70 | +- Should the explicit-key filter be the primitive and the config field become |
| 71 | + just a default, or should `min_peptides_protein` be removed entirely? |
| 72 | +- Does `prolfquapp`'s reader-local helper eventually get promoted into this |
| 73 | + prolfqua primitive once it is generic, so there is one implementation? |
0 commit comments