catomatic 0.2.0__tar.gz → 0.2.3__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.
- {catomatic-0.2.0 → catomatic-0.2.3}/LICENSE +0 -0
- {catomatic-0.2.0/src/catomatic.egg-info → catomatic-0.2.3}/PKG-INFO +23 -16
- {catomatic-0.2.0 → catomatic-0.2.3}/README.md +22 -15
- {catomatic-0.2.0 → catomatic-0.2.3}/pyproject.toml +1 -1
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/BinaryCatalogue.py +84 -16
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/PiezoTools.py +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/RegressionCatalogue.py +335 -216
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/__init__.py +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/__main__.py +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/cli.py +13 -12
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic/defence_module.py +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3/src/catomatic.egg-info}/PKG-INFO +23 -16
- {catomatic-0.2.0 → catomatic-0.2.3}/src/tests/__init__.py +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/tests/test_BuildBinaryCatalogue.py +25 -19
- {catomatic-0.2.0 → catomatic-0.2.3}/src/tests/test_BuildRegressionCatalogue.py +88 -163
- {catomatic-0.2.0 → catomatic-0.2.3}/setup.cfg +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic.egg-info/SOURCES.txt +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic.egg-info/dependency_links.txt +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic.egg-info/entry_points.txt +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic.egg-info/not-zip-safe +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic.egg-info/requires.txt +0 -0
- {catomatic-0.2.0 → catomatic-0.2.3}/src/catomatic.egg-info/top_level.txt +0 -0
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: catomatic
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A tool for automatically building catalogues of antibiotic resistance-associated variants
|
|
5
5
|
Author: Dylan Adlard
|
|
6
6
|
Author-email: Philip W Fowler <philip.fowler@ndm.ox.ac.uk>
|
|
@@ -48,15 +48,15 @@ The first is used in [https://doi.org/10.1101/2025.01.30.635633](https://doi.org
|
|
|
48
48
|
|
|
49
49
|
This method relies on the logic that mutations that do not cause resistance can co-occur with those that do. If a mutation in isolation (solo) does not cause resistance, then it is not contributing to the phenotype when present in a mixture either.
|
|
50
50
|
|
|
51
|
-
Mutations that occur in isolation
|
|
51
|
+
Mutations that occur in isolation are traversed in sequence. When they meet the susceptible criteria for the selected test, they are characterized as benign (`S`) and removed from the dataset. This step repeats iteratively until no more solo benign mutations are found.
|
|
52
52
|
|
|
53
53
|
Remaining mutations are classified based on their resistance rates and statistical test results. Those that don’t meet thresholds are labeled as `U`.
|
|
54
54
|
|
|
55
55
|
The classification approach supports:
|
|
56
56
|
|
|
57
|
-
- **No test**:
|
|
58
|
-
- **Binomial test**: against a specified background resistance rate
|
|
59
|
-
- **Fisher's test**:
|
|
57
|
+
- **No test**: calls a mutation `S` during iterative unlocking when all its solo observations are susceptible; remaining solo mutations are `U`
|
|
58
|
+
- **Binomial test**: tests the solo resistance rate against a specified background resistance rate
|
|
59
|
+
- **Fisher's test**: compares the mutation solo contingency table with the no-mutation solo background
|
|
60
60
|
|
|
61
61
|
### Optional Interventions
|
|
62
62
|
|
|
@@ -68,9 +68,9 @@ Because the method uses GARC1 grammar, rules like `{rpoB@*_fs:R}` can be supplie
|
|
|
68
68
|
- Be additive (lower priority than specific entries)
|
|
69
69
|
- Replace matching mutations (requires `replace=True` and `wildcards` supplied)
|
|
70
70
|
|
|
71
|
-
The catalogue
|
|
71
|
+
The built catalogue is available as a dictionary through the `catalogue.catalogue` attribute. It can also be converted to a Piezo-compatible `pandas.DataFrame` with `build_piezo()`.
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Evidence is stored with each catalogue entry and exported in the `EVIDENCE` field. It includes proportions, Wilson confidence intervals, solo contingency tables used for classification, full sample-level contingency tables for description, and p-values when a statistical test is used. Sample IDs can be included with `record_ids=True`.
|
|
74
74
|
|
|
75
75
|
### Example Workflow using Fisher's:
|
|
76
76
|
|
|
@@ -125,7 +125,7 @@ from catomatic.BinaryCatalogue import BinaryBuilder
|
|
|
125
125
|
catalogue = BinaryBuilder(samples=samples_df, mutations=mutations_df).build()
|
|
126
126
|
|
|
127
127
|
# View dictionary version
|
|
128
|
-
cat_dict = catalogue.
|
|
128
|
+
cat_dict = catalogue.catalogue
|
|
129
129
|
|
|
130
130
|
# Convert to Piezo-compatible format
|
|
131
131
|
catalogue_df = catalogue.build_piezo(
|
|
@@ -149,7 +149,7 @@ catalogue.to_piezo(
|
|
|
149
149
|
|
|
150
150
|
### CLI
|
|
151
151
|
|
|
152
|
-
After installation, the simplest way to run the catomatic catalogue builder is via the command line interface using the `binary` subcommand.
|
|
152
|
+
After installation, the simplest way to run the catomatic catalogue builder is via the command line interface using the `binary` subcommand. Use `--to_piezo` or `--to_json` to export the catalogue. If neither is supplied, no file is exported. Additional metadata is required when using `--to_piezo`.
|
|
153
153
|
|
|
154
154
|
#### Export to JSON
|
|
155
155
|
|
|
@@ -178,6 +178,8 @@ catomatic binary \
|
|
|
178
178
|
|
|
179
179
|
### CLI Parameters
|
|
180
180
|
|
|
181
|
+
The Binary CLI does not expose the Python `build()` options `tails` or `min_count`. The output flags are not mutually exclusive; if both are supplied, both exporters write to the same `--outfile`, so use only one.
|
|
182
|
+
|
|
181
183
|
| Parameter | Type | Description |
|
|
182
184
|
| ------------------ | ------- | ---------------------------------------------------------------------------------------------- |
|
|
183
185
|
| `--samples` | `str` | Path to the samples (phenotypes) file. Required. |
|
|
@@ -190,11 +192,16 @@ catomatic binary \
|
|
|
190
192
|
| `--version` | `str` | Catalogue version. Required with `--to_piezo`. |
|
|
191
193
|
| `--drug` | `str` | Name of the drug. Required with `--to_piezo`. |
|
|
192
194
|
| `--wildcards` | `str` | Path to JSON file containing wildcard mutation definitions. Required with `--to_piezo`. |
|
|
193
|
-
| `--test` | `str` | Type of statistical test to apply
|
|
194
|
-
| `--background` | `float` | Background
|
|
195
|
-
| `--p` | `float` |
|
|
196
|
-
| `--
|
|
197
|
-
| `--
|
|
195
|
+
| `--test` | `str` | Type of statistical test to apply: `Binomial` or `Fisher`. Optional; if omitted, no statistical test is used. |
|
|
196
|
+
| `--background` | `float` | Background resistance rate (0–1). Required if `--test Binomial` is used. |
|
|
197
|
+
| `--p` | `float` | Confidence level used for statistical testing. Optional. Defaults to `0.95` (a 0.05 significance threshold). |
|
|
198
|
+
| `--strict_unlock` | `flag` | For two-tailed tests, require statistical significance to classify homogeneous susceptible mutations as `S` during iterative unlocking. |
|
|
199
|
+
| `--frs` | `float` | Optional fraction-read-support threshold. Requires an `FRS` column in the mutations file. |
|
|
200
|
+
| `--seed` | `str[]` | Optional list of mutations to seed as susceptible before building. |
|
|
201
|
+
| `--record_ids` | `flag` | Include sample IDs in evidence records. |
|
|
202
|
+
| `--grammar` | `str` | Grammar used for Piezo export. Default: `GARC1`. |
|
|
203
|
+
| `--values` | `str` | Prediction values for Piezo export. Default: `RUS`. |
|
|
204
|
+
| `--for_piezo` | `flag` | Add placeholder rows for Piezo export. Default: `False` in the CLI. |
|
|
198
205
|
|
|
199
206
|
## Running catomatic's Regression Builder
|
|
200
207
|
|
|
@@ -310,8 +317,8 @@ catomatic regression \
|
|
|
310
317
|
|
|
311
318
|
### Notes
|
|
312
319
|
|
|
313
|
-
-
|
|
314
|
-
- For Piezo export, placeholder entries are inserted
|
|
320
|
+
- For `BinaryBuilder`, use `update_catalogue()` to apply post-hoc rules. Supply `wildcards` and set `replace=True` to replace entries matched by an aggregate rule. Specific entries can be added or replaced without `replace=True`.
|
|
321
|
+
- For Piezo export, placeholder entries are inserted when `for_piezo=True` and needed to satisfy parser requirements (R, S, and U must be represented). The Python export methods default to `for_piezo=True`; the CLI flag is off by default.
|
|
315
322
|
- The EVIDENCE column includes contingency tables, proportions, confidence intervals, and p-values, and may optionally include sample IDs if `record_ids=True`.
|
|
316
323
|
- To build a catalogue with the regression builder, as currently implemented, requires an ecoff as it will compare the predited effected against the background to supply an R/S/U label
|
|
317
324
|
- To only calculate predicted effects, this can be done in Python by calling RegressionBuilder.predict_effects()
|
|
@@ -23,15 +23,15 @@ The first is used in [https://doi.org/10.1101/2025.01.30.635633](https://doi.org
|
|
|
23
23
|
|
|
24
24
|
This method relies on the logic that mutations that do not cause resistance can co-occur with those that do. If a mutation in isolation (solo) does not cause resistance, then it is not contributing to the phenotype when present in a mixture either.
|
|
25
25
|
|
|
26
|
-
Mutations that occur in isolation
|
|
26
|
+
Mutations that occur in isolation are traversed in sequence. When they meet the susceptible criteria for the selected test, they are characterized as benign (`S`) and removed from the dataset. This step repeats iteratively until no more solo benign mutations are found.
|
|
27
27
|
|
|
28
28
|
Remaining mutations are classified based on their resistance rates and statistical test results. Those that don’t meet thresholds are labeled as `U`.
|
|
29
29
|
|
|
30
30
|
The classification approach supports:
|
|
31
31
|
|
|
32
|
-
- **No test**:
|
|
33
|
-
- **Binomial test**: against a specified background resistance rate
|
|
34
|
-
- **Fisher's test**:
|
|
32
|
+
- **No test**: calls a mutation `S` during iterative unlocking when all its solo observations are susceptible; remaining solo mutations are `U`
|
|
33
|
+
- **Binomial test**: tests the solo resistance rate against a specified background resistance rate
|
|
34
|
+
- **Fisher's test**: compares the mutation solo contingency table with the no-mutation solo background
|
|
35
35
|
|
|
36
36
|
### Optional Interventions
|
|
37
37
|
|
|
@@ -43,9 +43,9 @@ Because the method uses GARC1 grammar, rules like `{rpoB@*_fs:R}` can be supplie
|
|
|
43
43
|
- Be additive (lower priority than specific entries)
|
|
44
44
|
- Replace matching mutations (requires `replace=True` and `wildcards` supplied)
|
|
45
45
|
|
|
46
|
-
The catalogue
|
|
46
|
+
The built catalogue is available as a dictionary through the `catalogue.catalogue` attribute. It can also be converted to a Piezo-compatible `pandas.DataFrame` with `build_piezo()`.
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Evidence is stored with each catalogue entry and exported in the `EVIDENCE` field. It includes proportions, Wilson confidence intervals, solo contingency tables used for classification, full sample-level contingency tables for description, and p-values when a statistical test is used. Sample IDs can be included with `record_ids=True`.
|
|
49
49
|
|
|
50
50
|
### Example Workflow using Fisher's:
|
|
51
51
|
|
|
@@ -100,7 +100,7 @@ from catomatic.BinaryCatalogue import BinaryBuilder
|
|
|
100
100
|
catalogue = BinaryBuilder(samples=samples_df, mutations=mutations_df).build()
|
|
101
101
|
|
|
102
102
|
# View dictionary version
|
|
103
|
-
cat_dict = catalogue.
|
|
103
|
+
cat_dict = catalogue.catalogue
|
|
104
104
|
|
|
105
105
|
# Convert to Piezo-compatible format
|
|
106
106
|
catalogue_df = catalogue.build_piezo(
|
|
@@ -124,7 +124,7 @@ catalogue.to_piezo(
|
|
|
124
124
|
|
|
125
125
|
### CLI
|
|
126
126
|
|
|
127
|
-
After installation, the simplest way to run the catomatic catalogue builder is via the command line interface using the `binary` subcommand.
|
|
127
|
+
After installation, the simplest way to run the catomatic catalogue builder is via the command line interface using the `binary` subcommand. Use `--to_piezo` or `--to_json` to export the catalogue. If neither is supplied, no file is exported. Additional metadata is required when using `--to_piezo`.
|
|
128
128
|
|
|
129
129
|
#### Export to JSON
|
|
130
130
|
|
|
@@ -153,6 +153,8 @@ catomatic binary \
|
|
|
153
153
|
|
|
154
154
|
### CLI Parameters
|
|
155
155
|
|
|
156
|
+
The Binary CLI does not expose the Python `build()` options `tails` or `min_count`. The output flags are not mutually exclusive; if both are supplied, both exporters write to the same `--outfile`, so use only one.
|
|
157
|
+
|
|
156
158
|
| Parameter | Type | Description |
|
|
157
159
|
| ------------------ | ------- | ---------------------------------------------------------------------------------------------- |
|
|
158
160
|
| `--samples` | `str` | Path to the samples (phenotypes) file. Required. |
|
|
@@ -165,11 +167,16 @@ catomatic binary \
|
|
|
165
167
|
| `--version` | `str` | Catalogue version. Required with `--to_piezo`. |
|
|
166
168
|
| `--drug` | `str` | Name of the drug. Required with `--to_piezo`. |
|
|
167
169
|
| `--wildcards` | `str` | Path to JSON file containing wildcard mutation definitions. Required with `--to_piezo`. |
|
|
168
|
-
| `--test` | `str` | Type of statistical test to apply
|
|
169
|
-
| `--background` | `float` | Background
|
|
170
|
-
| `--p` | `float` |
|
|
171
|
-
| `--
|
|
172
|
-
| `--
|
|
170
|
+
| `--test` | `str` | Type of statistical test to apply: `Binomial` or `Fisher`. Optional; if omitted, no statistical test is used. |
|
|
171
|
+
| `--background` | `float` | Background resistance rate (0–1). Required if `--test Binomial` is used. |
|
|
172
|
+
| `--p` | `float` | Confidence level used for statistical testing. Optional. Defaults to `0.95` (a 0.05 significance threshold). |
|
|
173
|
+
| `--strict_unlock` | `flag` | For two-tailed tests, require statistical significance to classify homogeneous susceptible mutations as `S` during iterative unlocking. |
|
|
174
|
+
| `--frs` | `float` | Optional fraction-read-support threshold. Requires an `FRS` column in the mutations file. |
|
|
175
|
+
| `--seed` | `str[]` | Optional list of mutations to seed as susceptible before building. |
|
|
176
|
+
| `--record_ids` | `flag` | Include sample IDs in evidence records. |
|
|
177
|
+
| `--grammar` | `str` | Grammar used for Piezo export. Default: `GARC1`. |
|
|
178
|
+
| `--values` | `str` | Prediction values for Piezo export. Default: `RUS`. |
|
|
179
|
+
| `--for_piezo` | `flag` | Add placeholder rows for Piezo export. Default: `False` in the CLI. |
|
|
173
180
|
|
|
174
181
|
## Running catomatic's Regression Builder
|
|
175
182
|
|
|
@@ -285,8 +292,8 @@ catomatic regression \
|
|
|
285
292
|
|
|
286
293
|
### Notes
|
|
287
294
|
|
|
288
|
-
-
|
|
289
|
-
- For Piezo export, placeholder entries are inserted
|
|
295
|
+
- For `BinaryBuilder`, use `update_catalogue()` to apply post-hoc rules. Supply `wildcards` and set `replace=True` to replace entries matched by an aggregate rule. Specific entries can be added or replaced without `replace=True`.
|
|
296
|
+
- For Piezo export, placeholder entries are inserted when `for_piezo=True` and needed to satisfy parser requirements (R, S, and U must be represented). The Python export methods default to `for_piezo=True`; the CLI flag is off by default.
|
|
290
297
|
- The EVIDENCE column includes contingency tables, proportions, confidence intervals, and p-values, and may optionally include sample IDs if `record_ids=True`.
|
|
291
298
|
- To build a catalogue with the regression builder, as currently implemented, requires an ecoff as it will compare the predited effected against the background to supply an R/S/U label
|
|
292
299
|
- To only calculate predicted effects, this can be done in Python by calling RegressionBuilder.predict_effects()
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "catomatic"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "A tool for automatically building catalogues of antibiotic resistance-associated variants"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
# If README.md is markdown, setuptools will pick it up; optionally:
|
|
@@ -27,7 +27,7 @@ class BinaryBuilder(PiezoExporter):
|
|
|
27
27
|
Required columns: ['UNIQUEID', 'MUTATION']
|
|
28
28
|
Optional columns: ['FRS']
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
frs (float, optional): The Fraction Read Support threshold used to construct the catalogues.
|
|
31
31
|
Lower FRS values allow for greater genotype heterogeneity.
|
|
32
32
|
|
|
33
33
|
seed (list) optional): A list of predefined GARC neutral mutations with associated phenotypes
|
|
@@ -140,10 +140,36 @@ class BinaryBuilder(PiezoExporter):
|
|
|
140
140
|
# If no more susceptible solos, classify all R and U solos in one, final sweep
|
|
141
141
|
self.classify(self.samples, self.mutations)
|
|
142
142
|
|
|
143
|
+
# add in rows for mutations without solos
|
|
144
|
+
# self.add_missing()
|
|
145
|
+
|
|
143
146
|
self.order_catalogue()
|
|
144
147
|
|
|
145
148
|
return self
|
|
146
149
|
|
|
150
|
+
def add_missing(self):
|
|
151
|
+
|
|
152
|
+
# add in remaining mutations
|
|
153
|
+
all_muts = set(self.mutations.MUTATION.dropna().unique())
|
|
154
|
+
classified_muts = set(self.catalogue.keys())
|
|
155
|
+
missing = all_muts - classified_muts
|
|
156
|
+
|
|
157
|
+
for mut in missing:
|
|
158
|
+
full_x = self.build_full_contingency(self.samples, self.mutations, mut)
|
|
159
|
+
|
|
160
|
+
proportion = self.calc_proportion(full_x)
|
|
161
|
+
ci = self.calc_confidence_interval(full_x)
|
|
162
|
+
|
|
163
|
+
data = {
|
|
164
|
+
"proportion": proportion,
|
|
165
|
+
"confidence": ci,
|
|
166
|
+
"full_contingency": full_x,
|
|
167
|
+
"solo_contingency": None, # explicitly absent
|
|
168
|
+
"note": "No solo evidence; added post hoc",
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
self.add_mutation(mut, "U", data)
|
|
172
|
+
|
|
147
173
|
def classify(self, samples: pd.DataFrame, mutations: pd.DataFrame) -> None:
|
|
148
174
|
"""
|
|
149
175
|
Orchestrate one classification iteration over exposed 'solo' mutations.
|
|
@@ -196,22 +222,26 @@ class BinaryBuilder(PiezoExporter):
|
|
|
196
222
|
# Skip mutations with fewer than min_count samples
|
|
197
223
|
if solos[solos.MUTATION == mut].shape[0] < self.min_count:
|
|
198
224
|
return
|
|
199
|
-
# build a contingency table
|
|
200
|
-
x, ids = self.
|
|
225
|
+
# build a contingency table for solo mutations
|
|
226
|
+
x, ids = self.build_solo_contingency(solos, mut)
|
|
227
|
+
# build a contingency table for all observations
|
|
228
|
+
full_x = self.build_full_contingency(self.samples, self.mutations, mut)
|
|
201
229
|
# temporarily store mutation groups:
|
|
202
230
|
self.temp_ids = ids
|
|
203
231
|
|
|
204
232
|
# classify susceptible variants according to specified test mode
|
|
205
233
|
if self.test is None:
|
|
206
|
-
self.skeleton_build(mut, x)
|
|
234
|
+
self.skeleton_build(mut, x, full_x)
|
|
207
235
|
elif self.test == "Binomial":
|
|
208
|
-
self.binomial_build(mut, x)
|
|
236
|
+
self.binomial_build(mut, x, full_x)
|
|
209
237
|
elif self.test == "Fisher":
|
|
210
|
-
self.fishers_build(mut, x)
|
|
238
|
+
self.fishers_build(mut, x, full_x)
|
|
211
239
|
else:
|
|
212
240
|
raise ValueError(f"Unknown test mode: {self.test}")
|
|
213
241
|
|
|
214
|
-
def skeleton_build(
|
|
242
|
+
def skeleton_build(
|
|
243
|
+
self, mutation: str, x: Contingency, full_x: Contingency
|
|
244
|
+
) -> None:
|
|
215
245
|
"""
|
|
216
246
|
Record descriptive statistics and optionally mark susceptible solos.
|
|
217
247
|
Calls homogenous susceptible S.
|
|
@@ -227,7 +257,12 @@ class BinaryBuilder(PiezoExporter):
|
|
|
227
257
|
proportion = self.calc_proportion(x)
|
|
228
258
|
ci = self.calc_confidence_interval(x)
|
|
229
259
|
|
|
230
|
-
data = {
|
|
260
|
+
data = {
|
|
261
|
+
"proportion": proportion,
|
|
262
|
+
"confidence": ci,
|
|
263
|
+
"solo_contingency": x,
|
|
264
|
+
"contingency": full_x,
|
|
265
|
+
}
|
|
231
266
|
|
|
232
267
|
if self.run_iter:
|
|
233
268
|
# if iteratively classifing S variants
|
|
@@ -238,8 +273,12 @@ class BinaryBuilder(PiezoExporter):
|
|
|
238
273
|
# not phenotyping, just adding to catalogue
|
|
239
274
|
self.add_mutation(mutation, "U", data)
|
|
240
275
|
|
|
241
|
-
def binomial_build(
|
|
242
|
-
|
|
276
|
+
def binomial_build(
|
|
277
|
+
self, mutation: str, x: Contingency, full_x: Contingency
|
|
278
|
+
) -> None:
|
|
279
|
+
assert (
|
|
280
|
+
self.background is not None
|
|
281
|
+
), "background must be provided for Binomial test"
|
|
243
282
|
bg: float = float(self.background)
|
|
244
283
|
|
|
245
284
|
# p-value function for binomial
|
|
@@ -258,10 +297,11 @@ class BinaryBuilder(PiezoExporter):
|
|
|
258
297
|
def resistant_rule(proportion: float, p_calc: float, x) -> bool:
|
|
259
298
|
return bool(proportion > bg)
|
|
260
299
|
|
|
261
|
-
self.hypothesis_test(
|
|
262
|
-
|
|
300
|
+
self.hypothesis_test(
|
|
301
|
+
mutation, x, full_x, pvalue_fn, susceptible_rule, resistant_rule
|
|
302
|
+
)
|
|
263
303
|
|
|
264
|
-
def fishers_build(self, mutation: str, x: Contingency) -> None:
|
|
304
|
+
def fishers_build(self, mutation: str, x: Contingency, full_x: Contingency) -> None:
|
|
265
305
|
"""
|
|
266
306
|
Classify mutation using Fisher's exact test and directional inference.
|
|
267
307
|
|
|
@@ -291,12 +331,15 @@ class BinaryBuilder(PiezoExporter):
|
|
|
291
331
|
odds = self.calc_odds_ratio(x)
|
|
292
332
|
return odds > 1
|
|
293
333
|
|
|
294
|
-
self.hypothesis_test(
|
|
334
|
+
self.hypothesis_test(
|
|
335
|
+
mutation, x, full_x, pvalue_fn, susceptible_rule, resistant_rule
|
|
336
|
+
)
|
|
295
337
|
|
|
296
338
|
def hypothesis_test(
|
|
297
339
|
self,
|
|
298
340
|
mutation: str,
|
|
299
341
|
x: Contingency,
|
|
342
|
+
full_x: Contingency,
|
|
300
343
|
pvalue_fn: Callable[[Contingency], float],
|
|
301
344
|
susceptible_rule: Callable[[float, float, Contingency], bool],
|
|
302
345
|
resistant_rule: Callable[[float, float, Contingency], bool],
|
|
@@ -324,7 +367,8 @@ class BinaryBuilder(PiezoExporter):
|
|
|
324
367
|
"proportion": proportion,
|
|
325
368
|
"confidence": ci,
|
|
326
369
|
"p_value": p_calc,
|
|
327
|
-
"
|
|
370
|
+
"solo_contingency": x, # solo-based (classification)
|
|
371
|
+
"contingency": full_x, # (descriptive only)
|
|
328
372
|
}
|
|
329
373
|
|
|
330
374
|
# ITERATIVE MODE (we actively try to find susceptibles)
|
|
@@ -414,7 +458,7 @@ class BinaryBuilder(PiezoExporter):
|
|
|
414
458
|
return (lower, upper)
|
|
415
459
|
|
|
416
460
|
@staticmethod
|
|
417
|
-
def
|
|
461
|
+
def build_solo_contingency(
|
|
418
462
|
solos: pd.DataFrame, mutation: str
|
|
419
463
|
) -> Tuple[list[list[int]], list[str]]:
|
|
420
464
|
"""
|
|
@@ -438,6 +482,30 @@ class BinaryBuilder(PiezoExporter):
|
|
|
438
482
|
|
|
439
483
|
return [[R_count, S_count], [R_count_no_mut, S_count_no_mut]], ids
|
|
440
484
|
|
|
485
|
+
@staticmethod
|
|
486
|
+
def build_full_contingency(
|
|
487
|
+
samples: pd.DataFrame, mutations: pd.DataFrame, mutation: str
|
|
488
|
+
) -> list[list[int]]:
|
|
489
|
+
"""
|
|
490
|
+
Full contingency using ALL samples (sample-level, not row-level).
|
|
491
|
+
"""
|
|
492
|
+
|
|
493
|
+
# determine which samples have the mutation
|
|
494
|
+
mut_present = mutations[mutations.MUTATION == mutation][
|
|
495
|
+
"UNIQUEID"
|
|
496
|
+
].drop_duplicates()
|
|
497
|
+
|
|
498
|
+
df = samples.copy()
|
|
499
|
+
df["has_mut"] = df["UNIQUEID"].isin(mut_present)
|
|
500
|
+
|
|
501
|
+
R_with = ((df.PHENOTYPE == "R") & (df.has_mut)).sum()
|
|
502
|
+
S_with = ((df.PHENOTYPE == "S") & (df.has_mut)).sum()
|
|
503
|
+
|
|
504
|
+
R_without = ((df.PHENOTYPE == "R") & (~df.has_mut)).sum()
|
|
505
|
+
S_without = ((df.PHENOTYPE == "S") & (~df.has_mut)).sum()
|
|
506
|
+
|
|
507
|
+
return [[int(R_with), int(S_with)], [int(R_without), int(S_without)]]
|
|
508
|
+
|
|
441
509
|
@staticmethod
|
|
442
510
|
def calc_odds_ratio(x: Contingency) -> float:
|
|
443
511
|
"""
|
|
File without changes
|