Repository: wfondrie/mokapot

Issue:
[BUG] Different scores for LinearConfidence and GroupConfidence
`LinearConfidence` and `GroupedConfidence` give different scores, even when for `GroupedConfidence` all PSMs are part of a single group. I'm using a random forest, which should give scores between 0 and 1, but for `GroupedConfidence` the scores seem to range between 1 and 2 instead.

When using `LinearConfidence`:
```
import mokapot
from sklearn.ensemble import RandomForestClassifier
psms = mokapot.read_pin("phospho_rep1.pin")
moka_conf, _ = mokapot.brew(psms, mokapot.Model(RandomForestClassifier(random_state=1)))
moka_conf.psms["mokapot score"].describe()
```
Output:
```
count    42330.000000
mean         0.686944
std          0.435288
min          0.000000
25%          0.060000
50%          1.000000
75%          1.000000
max          1.000000
```

For simplicity, I use the constant `Charge1` column in the example PIN file as group for `GroupedConfidence`, i.e. all PSMs are part of the same group (`Charge1 == 0`):
```
import mokapot
from sklearn.ensemble import RandomForestClassifier
psms_grouped = mokapot.read_pin("phospho_rep1.pin", group_column="Charge1")
moka_conf_grouped, _ = mokapot.brew(psms_grouped, mokapot.Model(RandomForestClassifier(random_state=1)))
moka_conf_grouped.group_confidence_estimates[0].psms["mokapot score"].describe()
```

Output:
```
count    42330.000000
mean         1.687226
std          0.435448
min          1.000000
25%          1.060000
50%          2.000000
75%          2.000000
max          2.000000
```

Note how the scores seem to be almost identical except for being 1 more. I tried to figure out in the code what was happening, but didn't immediately find the problem.

This is with mokapot version 0.8.2.

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2030c9a..588e408 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog for mokapot  
 
+## [0.8.3] - 2022-07-20
+### Fixed
+- Fixed the reported mokapot score when group FDR is used.
+
 ## [0.8.2] - 2022-07-18
 ### Added
 - `mokapot.Model()` objects now recored the CV fold that they were fit on.
diff --git a/mokapot/confidence.py b/mokapot/confidence.py
index c8935cb..e72cecd 100644
--- a/mokapot/confidence.py
+++ b/mokapot/confidence.py
@@ -63,9 +63,10 @@ class GroupedConfidence:
         group_psms = copy.copy(psms)
         self.group_column = group_psms._group_column
         group_psms._group_column = None
-        scores = scores * (desc * 2 - 1)
 
-        # Do TDC
+        # Do TDC to eliminate multiples PSMs for a spectrum that may occur
+        # in different groups.
+        keep = "last" if desc else "first"
         scores = (
             pd.Series(scores, index=psms._data.index)
             .sample(frac=1)
@@ -74,7 +75,7 @@ class GroupedConfidence:
 
         idx = (
             psms.data.loc[scores.index, :]
-            .drop_duplicates(psms._spectrum_columns, keep="last")
+            .drop_duplicates(psms._spectrum_columns, keep=keep)
             .index
         )
 
@@ -84,9 +85,9 @@ class GroupedConfidence:
             group_psms._data = None
             tdc_winners = group_df.index.intersection(idx)
             group_psms._data = group_df.loc[tdc_winners, :]
-            group_scores = scores.loc[group_psms._data.index].values + 1
+            group_scores = scores.loc[group_psms._data.index].values
             res = group_psms.assign_confidence(
-                group_scores * (2 * desc - 1), desc=desc, eval_fdr=eval_fdr
+                group_scores, desc=desc, eval_fdr=eval_fdr
             )
             self._group_confidence_estimates[group] = res
 


Test patch:
diff --git a/tests/unit_tests/test_confidence.py b/tests/unit_tests/test_confidence.py
index e69de29..0be3fcd 100644
--- a/tests/unit_tests/test_confidence.py
+++ b/tests/unit_tests/test_confidence.py
@@ -0,0 +1,38 @@
+"""Test that Confidence classes are working correctly"""
+import pytest
+import numpy as np
+import pandas as pd
+from mokapot import LinearPsmDataset
+
+
+def test_one_group(psm_df_1000):
+    """Test that one group is equivalent to no group."""
+    psm_data, _ = psm_df_1000
+    psm_data["group"] = 0
+
+    psms = LinearPsmDataset(
+        psms=psm_data,
+        target_column="target",
+        spectrum_columns="spectrum",
+        peptide_column="peptide",
+        feature_columns="score",
+        filename_column="filename",
+        scan_column="spectrum",
+        calcmass_column="calcmass",
+        expmass_column="expmass",
+        rt_column="ret_time",
+        charge_column="charge",
+        group_column="group",
+        copy_data=True,
+    )
+
+    np.random.seed(42)
+    grouped = psms.assign_confidence()
+    scores1 = grouped.group_confidence_estimates[0].psms["mokapot score"]
+
+    np.random.seed(42)
+    psms._group_column = None
+    ungrouped = psms.assign_confidence()
+    scores2 = ungrouped.psms["mokapot score"]
+
+    pd.testing.assert_series_equal(scores1, scores2)