Sync from GitHub via hub-sync
Browse files- README.md +428 -9
- app.py +841 -0
- data/examples/single-point/dose-response_count.csv +0 -0
- data/examples/single-point/dose-response_sample_meta.csv +181 -0
- data/examples/single-point/dose-response_strain_meta.csv +117 -0
- data/examples/single-point/test_count.csv +0 -0
- data/examples/single-point/test_sample_meta.csv +19 -0
- data/examples/single-point/test_strain_meta.csv +117 -0
- requirements.txt +8 -0
README.md
CHANGED
|
@@ -1,14 +1,433 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
app_file: app.py
|
| 9 |
-
pinned:
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
---
|
| 13 |
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: bartab
|
| 3 |
+
emoji: 🍹
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: "5.50.0"
|
| 8 |
app_file: app.py
|
| 9 |
+
pinned: true
|
| 10 |
+
short_description: Fitness from pooled competition experiments.
|
| 11 |
+
tags:
|
| 12 |
+
- biology
|
| 13 |
+
- sequencing
|
| 14 |
+
- pooled-screen
|
| 15 |
+
- fitness
|
| 16 |
+
- gradio
|
| 17 |
---
|
| 18 |
|
| 19 |
+
# 🍹 bartab
|
| 20 |
+
|
| 21 |
+
**Estimate strain fitness from sequencing-based pooled competition experiments.**
|
| 22 |
+
|
| 23 |
+
`bartab` analyses pooled barcode sequencing experiments in which multiple strains,
|
| 24 |
+
mutants, guides, or constructs are grown together and quantified by NGS over time.
|
| 25 |
+
It estimates the relative fitness of each barcode compared with a reference strain,
|
| 26 |
+
typically WT.
|
| 27 |
+
|
| 28 |
+
[](https://huggingface.co/spaces/scbirlab/bartab)
|
| 29 |
+
|
| 30 |
+
---
|
| 31 |
+
|
| 32 |
+
## What this app does
|
| 33 |
+
|
| 34 |
+
Upload three tables:
|
| 35 |
+
|
| 36 |
+
1. **Count table**
|
| 37 |
+
Read or UMI counts for each barcode in each sequencing sample.
|
| 38 |
+
|
| 39 |
+
2. **Sample sheet**
|
| 40 |
+
Metadata describing each sample: sample ID, culture/replicate ID, timepoint,
|
| 41 |
+
optional concentration, optional growth measurement, and optional sampled volume.
|
| 42 |
+
|
| 43 |
+
3. **Barcode sheet**
|
| 44 |
+
Barcode or strain identifiers, plus optional strain-level metadata.
|
| 45 |
+
|
| 46 |
+
`bartab` then estimates how each barcode changes relative to a reference barcode as
|
| 47 |
+
the culture expands.
|
| 48 |
+
|
| 49 |
+
---
|
| 50 |
+
|
| 51 |
+
### Option 1: Spike-in normalisation
|
| 52 |
+
|
| 53 |
+
Use this when your experiment includes a non-growing spike-in barcode, such as a
|
| 54 |
+
heat-killed strain, plasmid-only control, or other fitness-zero control.
|
| 55 |
+
|
| 56 |
+
If the spike-in does not grow, then changes in the spike-in:WT count ratio report how
|
| 57 |
+
much WT has expanded.
|
| 58 |
+
|
| 59 |
+
For a non-growing spike-in:
|
| 60 |
+
|
| 61 |
+
$$
|
| 62 |
+
\log \left(
|
| 63 |
+
\frac{c_{spike}(t)}{c_{wt}(t)}
|
| 64 |
+
\frac{c_{wt}(0)}{c_{spike}(0)}
|
| 65 |
+
\right)
|
| 66 |
+
=
|
| 67 |
+
-
|
| 68 |
+
\log
|
| 69 |
+
\frac{n_{wt}(t)}{n_{wt}(0)}
|
| 70 |
+
$$
|
| 71 |
+
|
| 72 |
+
Substituting this into the barcode model gives:
|
| 73 |
+
|
| 74 |
+
$$
|
| 75 |
+
\log \left(
|
| 76 |
+
\frac{c_i(t)}{c_{wt}(t)}
|
| 77 |
+
\frac{c_{wt}(0)}{c_i(0)}
|
| 78 |
+
\right)
|
| 79 |
+
=
|
| 80 |
+
\left(
|
| 81 |
+
1 - \frac{w_i}{w_{wt}}
|
| 82 |
+
\right)
|
| 83 |
+
\log \left(
|
| 84 |
+
\frac{c_{spike}(t)}{c_{wt}(t)}
|
| 85 |
+
\frac{c_{wt}(0)}{c_{spike}(0)}
|
| 86 |
+
\right)
|
| 87 |
+
$$
|
| 88 |
+
|
| 89 |
+
So, when using spike-in normalisation, `bartab` estimates relative fitness from the
|
| 90 |
+
relationship between:
|
| 91 |
+
|
| 92 |
+
- the barcode:WT log-ratio change
|
| 93 |
+
- the spike-in:WT log-ratio change
|
| 94 |
+
|
| 95 |
+
---
|
| 96 |
+
|
| 97 |
+
### Option 2: Growth-based normalisation
|
| 98 |
+
|
| 99 |
+
Use this when you have measured culture growth directly, for example:
|
| 100 |
+
|
| 101 |
+
- OD600
|
| 102 |
+
- CFU/mL
|
| 103 |
+
- estimated generations
|
| 104 |
+
- another density-like growth measurement
|
| 105 |
+
|
| 106 |
+
In this mode, `bartab` uses the supplied growth column as the culture expansion axis
|
| 107 |
+
instead of estimating expansion from a spike-in barcode.
|
| 108 |
+
|
| 109 |
+
---
|
| 110 |
+
|
| 111 |
+
## Analysis modes
|
| 112 |
+
|
| 113 |
+
### 👟 Fitness in a single condition
|
| 114 |
+
|
| 115 |
+
This is the standard mode for pooled competition assays.
|
| 116 |
+
|
| 117 |
+
`bartab` fits a weighted least-squares model to estimate relative fitness for each
|
| 118 |
+
barcode.
|
| 119 |
+
|
| 120 |
+
Main outputs:
|
| 121 |
+
|
| 122 |
+
| Column | Meaning |
|
| 123 |
+
|---|---|
|
| 124 |
+
| `fitness` | relative fitness compared with the reference barcode |
|
| 125 |
+
| `fitness_low` | lower confidence interval bound |
|
| 126 |
+
| `fitness_high` | upper confidence interval bound |
|
| 127 |
+
| `slope_p` | p-value for deviation from neutral fitness |
|
| 128 |
+
|
| 129 |
+
Interpretation:
|
| 130 |
+
|
| 131 |
+
| Fitness | Interpretation |
|
| 132 |
+
|---|---|
|
| 133 |
+
| `1` | grows like the reference |
|
| 134 |
+
| `< 1` | growth disadvantage |
|
| 135 |
+
| `> 1` | growth advantage |
|
| 136 |
+
|
| 137 |
+
---
|
| 138 |
+
|
| 139 |
+
### 📉 Dose response
|
| 140 |
+
|
| 141 |
+
Use this when the sample sheet contains a concentration column.
|
| 142 |
+
|
| 143 |
+
`bartab` first estimates barcode fitness across concentrations, then fits a
|
| 144 |
+
two-parameter Hill model to estimate dose-response parameters.
|
| 145 |
+
|
| 146 |
+
Main outputs:
|
| 147 |
+
|
| 148 |
+
| Column | Meaning |
|
| 149 |
+
|---|---|
|
| 150 |
+
| `log_ic50` | log10 concentration giving 50% inhibition |
|
| 151 |
+
| `log_ic50_p` | p-value associated with the IC50 estimate |
|
| 152 |
+
|
| 153 |
+
Lower IC50 values indicate greater sensitivity to the inducer or drug.
|
| 154 |
+
|
| 155 |
+
---
|
| 156 |
+
|
| 157 |
+
## Required input tables
|
| 158 |
+
|
| 159 |
+
The app lets you select the relevant columns after upload.
|
| 160 |
+
|
| 161 |
+
Supported file formats:
|
| 162 |
+
|
| 163 |
+
- `.csv`
|
| 164 |
+
- `.tsv`
|
| 165 |
+
- `.txt`
|
| 166 |
+
- `.xlsx`
|
| 167 |
+
|
| 168 |
+
---
|
| 169 |
+
|
| 170 |
+
### 1. Count table
|
| 171 |
+
|
| 172 |
+
One row per barcode per sample.
|
| 173 |
+
|
| 174 |
+
Required columns:
|
| 175 |
+
|
| 176 |
+
| Meaning | Example |
|
| 177 |
+
|---|---|
|
| 178 |
+
| barcode / strain identifier | `strain_id` |
|
| 179 |
+
| sample identifier | `sample_id` |
|
| 180 |
+
| read or UMI count | `count` |
|
| 181 |
+
|
| 182 |
+
Example:
|
| 183 |
+
|
| 184 |
+
| strain_id | sample_id | count |
|
| 185 |
+
|---|---:|---:|
|
| 186 |
+
| wt | sample_0 | 12034 |
|
| 187 |
+
| mutant_A | sample_0 | 8312 |
|
| 188 |
+
| spike | sample_0 | 5021 |
|
| 189 |
+
| wt | sample_1 | 18420 |
|
| 190 |
+
| mutant_A | sample_1 | 6420 |
|
| 191 |
+
| spike | sample_1 | 2100 |
|
| 192 |
+
|
| 193 |
+
---
|
| 194 |
+
|
| 195 |
+
### 2. Barcode sheet
|
| 196 |
+
|
| 197 |
+
One row per barcode.
|
| 198 |
+
|
| 199 |
+
Required columns:
|
| 200 |
+
|
| 201 |
+
| Meaning | Example |
|
| 202 |
+
|---|---|
|
| 203 |
+
| barcode / strain identifier | `strain_id` |
|
| 204 |
+
|
| 205 |
+
Optional metadata columns are carried through to the output.
|
| 206 |
+
|
| 207 |
+
Example:
|
| 208 |
+
|
| 209 |
+
| strain_id | gene | annotation |
|
| 210 |
+
|---|---|---|
|
| 211 |
+
| wt | WT | reference |
|
| 212 |
+
| mutant_A | geneA | deletion mutant |
|
| 213 |
+
| spike | spike | non-growing spike-in |
|
| 214 |
+
|
| 215 |
+
---
|
| 216 |
+
|
| 217 |
+
### 3. Sample sheet
|
| 218 |
+
|
| 219 |
+
One row per sequencing sample.
|
| 220 |
+
|
| 221 |
+
Required columns:
|
| 222 |
+
|
| 223 |
+
| Meaning | Example |
|
| 224 |
+
|---|---|
|
| 225 |
+
| sample identifier | `sample_id` |
|
| 226 |
+
| culture / biological replicate | `replicate` |
|
| 227 |
+
| timepoint | `timepoint` |
|
| 228 |
+
|
| 229 |
+
Optional columns:
|
| 230 |
+
|
| 231 |
+
| Meaning | Example | Used for |
|
| 232 |
+
|---|---|---|
|
| 233 |
+
| concentration | `dose` | dose-response analysis |
|
| 234 |
+
| growth measurement | `growth` | growth-based normalisation |
|
| 235 |
+
| sampled volume | `volume` | adaptive-volume sampling |
|
| 236 |
+
|
| 237 |
+
Example:
|
| 238 |
+
|
| 239 |
+
| sample_id | replicate | timepoint | dose | growth | volume |
|
| 240 |
+
|---|---|---:|---:|---:|---:|
|
| 241 |
+
| sample_0 | rep1 | 0 | 0 | 0.05 | 1.0 |
|
| 242 |
+
| sample_1 | rep1 | 1 | 0 | 0.20 | 1.0 |
|
| 243 |
+
| sample_2 | rep1 | 2 | 0 | 0.80 | 1.0 |
|
| 244 |
+
|
| 245 |
+
---
|
| 246 |
+
|
| 247 |
+
## Example datasets
|
| 248 |
+
|
| 249 |
+
The Space includes synthetic example datasets for:
|
| 250 |
+
|
| 251 |
+
- single-concentration analysis using spike-in normalisation
|
| 252 |
+
- single-concentration analysis using growth-based normalisation
|
| 253 |
+
- dose-response analysis using spike-in normalisation
|
| 254 |
+
- dose-response analysis using growth-based normalisation
|
| 255 |
+
|
| 256 |
+
Start with these examples if you want to see the expected table structure.
|
| 257 |
+
|
| 258 |
+
---
|
| 259 |
+
|
| 260 |
+
## Outputs
|
| 261 |
+
|
| 262 |
+
After analysis, the app returns:
|
| 263 |
+
|
| 264 |
+
1. **Fitted parameter table**
|
| 265 |
+
A CSV file containing estimated fitness or dose-response parameters.
|
| 266 |
+
|
| 267 |
+
2. **Annotated `.h5ad` object**
|
| 268 |
+
A full `AnnData` object containing input data, metadata, transformations,
|
| 269 |
+
fitted values, and model outputs.
|
| 270 |
+
|
| 271 |
+
3. **Diagnostic plots**
|
| 272 |
+
|
| 273 |
+
Depending on the analysis mode, plots include:
|
| 274 |
+
|
| 275 |
+
- time vs count
|
| 276 |
+
- expansion vs count
|
| 277 |
+
- time vs ratio
|
| 278 |
+
- expansion vs ratio
|
| 279 |
+
- predicted vs observed
|
| 280 |
+
- volcano plot
|
| 281 |
+
- dose-response curves
|
| 282 |
+
|
| 283 |
+
---
|
| 284 |
+
|
| 285 |
+
## Practical guidance
|
| 286 |
+
|
| 287 |
+
- Use consistent barcode and sample identifiers across all three tables.
|
| 288 |
+
- If using spike-in normalisation, include the spike-in barcode in both the count table
|
| 289 |
+
and barcode sheet.
|
| 290 |
+
- If using growth-based normalisation, include a numeric growth column in the sample sheet.
|
| 291 |
+
- For dose-response analysis, concentration values must be numeric.
|
| 292 |
+
- Low-count barcodes may give unstable estimates.
|
| 293 |
+
- Always inspect diagnostic plots before interpreting individual hits.
|
| 294 |
+
|
| 295 |
+
---
|
| 296 |
+
|
| 297 |
+
## The model
|
| 298 |
+
|
| 299 |
+
[Interactive tutorial on analysis principles](https://huggingface.co/spaces/scbirlab/tutorial-seq-fitness)
|
| 300 |
+
|
| 301 |
+
In a pooled growth experiment, strains compete in the same culture. Their absolute
|
| 302 |
+
growth curves may be complex because the pool eventually approaches carrying capacity.
|
| 303 |
+
However, if we compare every strain to a reference strain, the shared density-dependent
|
| 304 |
+
term cancels. The reference strain’s expansion can then be used as the effective
|
| 305 |
+
growth clock.
|
| 306 |
+
|
| 307 |
+
For strain $i$ relative to WT:
|
| 308 |
+
|
| 309 |
+
$$
|
| 310 |
+
\log n_i(t)
|
| 311 |
+
=
|
| 312 |
+
\frac{w_i}{w_{wt}}
|
| 313 |
+
\log \frac{n_{wt}(t)}{n_{wt}(0)}
|
| 314 |
+
+
|
| 315 |
+
\log n_i(0)
|
| 316 |
+
$$
|
| 317 |
+
|
| 318 |
+
where:
|
| 319 |
+
|
| 320 |
+
- $n_i(t)$ is the abundance of strain $i$ at time $t$
|
| 321 |
+
- $w_i$ is the intrinsic growth rate of strain $i$
|
| 322 |
+
- $w_i / w_{wt}$ is the relative fitness
|
| 323 |
+
|
| 324 |
+
So the problem becomes: estimate how barcode abundance changes relative to WT as WT
|
| 325 |
+
expands.
|
| 326 |
+
|
| 327 |
+
---
|
| 328 |
+
|
| 329 |
+
## From cells to sequencing counts
|
| 330 |
+
|
| 331 |
+
In practice, we do not observe cell numbers directly. We observe read counts:
|
| 332 |
+
|
| 333 |
+
$$
|
| 334 |
+
c_i(t)
|
| 335 |
+
$$
|
| 336 |
+
|
| 337 |
+
These are affected by sampling, library preparation, and sequencing depth. To remove
|
| 338 |
+
sample-specific sequencing depth effects, `bartab` works with ratios of barcode counts
|
| 339 |
+
to the reference barcode.
|
| 340 |
+
|
| 341 |
+
The key quantity is:
|
| 342 |
+
|
| 343 |
+
$$
|
| 344 |
+
\log \left(
|
| 345 |
+
\frac{c_i(t)}{c_{wt}(t)}
|
| 346 |
+
\frac{c_{wt}(0)}{c_i(0)}
|
| 347 |
+
\right)
|
| 348 |
+
$$
|
| 349 |
+
|
| 350 |
+
This is the log-change in the abundance of barcode $i$ relative to WT, normalised
|
| 351 |
+
to the starting timepoint.
|
| 352 |
+
|
| 353 |
+
Under the model:
|
| 354 |
+
|
| 355 |
+
$$
|
| 356 |
+
\log \left(
|
| 357 |
+
\frac{c_i(t)}{c_{wt}(t)}
|
| 358 |
+
\frac{c_{wt}(0)}{c_i(0)}
|
| 359 |
+
\right)
|
| 360 |
+
=
|
| 361 |
+
\left(
|
| 362 |
+
\frac{w_i}{w_{wt}} - 1
|
| 363 |
+
\right)
|
| 364 |
+
\log
|
| 365 |
+
\frac{n_{wt}(t)}{n_{wt}(0)}
|
| 366 |
+
$$
|
| 367 |
+
|
| 368 |
+
Thus, each barcode should follow an approximately straight line. The slope gives the
|
| 369 |
+
barcode’s fitness relative to WT.
|
| 370 |
+
|
| 371 |
+
---
|
| 372 |
+
|
| 373 |
+
## Estimating culture expansion
|
| 374 |
+
|
| 375 |
+
The remaining problem is that the true WT expansion,
|
| 376 |
+
|
| 377 |
+
$$
|
| 378 |
+
\frac{n_{wt}(t)}{n_{wt}(0)}
|
| 379 |
+
$$
|
| 380 |
+
|
| 381 |
+
is usually not directly observed. `bartab` supports two ways to estimate it.
|
| 382 |
+
|
| 383 |
+
---
|
| 384 |
+
|
| 385 |
+
## When this model is appropriate
|
| 386 |
+
|
| 387 |
+
`bartab` is designed for pooled competition experiments where:
|
| 388 |
+
|
| 389 |
+
- barcodes identify strains, mutants, guides, or constructs
|
| 390 |
+
- all barcodes are grown together in shared cultures
|
| 391 |
+
- barcode abundance is quantified by sequencing
|
| 392 |
+
- one barcode can be treated as a reference
|
| 393 |
+
- expansion can be estimated from a spike-in or measured growth
|
| 394 |
+
|
| 395 |
+
It is especially useful for:
|
| 396 |
+
|
| 397 |
+
- bacterial pooled competition assays
|
| 398 |
+
- barcoded mutant libraries
|
| 399 |
+
- CRISPRi or guide-based growth assays
|
| 400 |
+
- chemical-genetic pooled fitness experiments
|
| 401 |
+
- inducer or drug dose-response screens
|
| 402 |
+
|
| 403 |
+
---
|
| 404 |
+
|
| 405 |
+
## Limitations
|
| 406 |
+
|
| 407 |
+
`bartab` estimates relative fitness, not absolute growth rate.
|
| 408 |
+
|
| 409 |
+
Results may be unreliable when:
|
| 410 |
+
|
| 411 |
+
- the reference barcode is depleted or poorly counted
|
| 412 |
+
- the spike-in is not truly non-growing
|
| 413 |
+
- barcode counts are extremely low
|
| 414 |
+
- barcode identities are mismatched between tables
|
| 415 |
+
- bottlenecks dominate the experiment
|
| 416 |
+
- strong barcode-specific sequencing biases are present
|
| 417 |
+
- timepoints or concentrations are too sparse for model fitting
|
| 418 |
+
|
| 419 |
+
For dose-response fitting, IC50 estimates are most meaningful when the tested
|
| 420 |
+
concentration range brackets the transition from weak to strong inhibition.
|
| 421 |
+
|
| 422 |
+
---
|
| 423 |
+
|
| 424 |
+
## Local use
|
| 425 |
+
|
| 426 |
+
To run the app locally:
|
| 427 |
+
|
| 428 |
+
```bash
|
| 429 |
+
pip install -r requirements.txt
|
| 430 |
+
gradio app.py
|
| 431 |
+
```
|
| 432 |
+
|
| 433 |
+
For package and source code, see https://github.com/scbirlab/bartab
|
app.py
ADDED
|
@@ -0,0 +1,841 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Gradio demo for bartab."""
|
| 2 |
+
|
| 3 |
+
from typing import Iterable, List, Union
|
| 4 |
+
from functools import partial
|
| 5 |
+
from io import TextIOWrapper
|
| 6 |
+
import os
|
| 7 |
+
os.environ["COMMANDLINE_ARGS"] = "--no-gradio-queue"
|
| 8 |
+
|
| 9 |
+
from carabiner import cast, print_err
|
| 10 |
+
from carabiner.decorators import decorator_with_params
|
| 11 |
+
from carabiner.pd import read_table
|
| 12 |
+
import gradio as gr
|
| 13 |
+
import nemony as nm
|
| 14 |
+
import numpy as np
|
| 15 |
+
import pandas as pd
|
| 16 |
+
|
| 17 |
+
import anndata
|
| 18 |
+
anndata.settings.allow_write_nullable_strings = True
|
| 19 |
+
import bartab
|
| 20 |
+
from bartab.io import load_anndata
|
| 21 |
+
from bartab.models.anndata import AnnDataWLSModel, AnnDataHillModel
|
| 22 |
+
from bartab.plotting import (
|
| 23 |
+
dose_response,
|
| 24 |
+
expansion_vs_count,
|
| 25 |
+
expansion_vs_ratio,
|
| 26 |
+
pred_vs_true,
|
| 27 |
+
time_vs_count,
|
| 28 |
+
time_vs_ratio,
|
| 29 |
+
volcano
|
| 30 |
+
)
|
| 31 |
+
from bartab.transforms import compute_log_ratios
|
| 32 |
+
|
| 33 |
+
pd.options.future.infer_string = True
|
| 34 |
+
|
| 35 |
+
MODES: dict = {
|
| 36 |
+
"single": "👟 Fitness in a single condition",
|
| 37 |
+
"dose response": "📉 Fitness dose response to CRISPRi inducer",
|
| 38 |
+
}
|
| 39 |
+
def _message(s: str):
|
| 40 |
+
print_err(f"[INFO] {s}")
|
| 41 |
+
gr.Info(s, duration=10)
|
| 42 |
+
return None
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def load_input_data(
|
| 46 |
+
filename: str,
|
| 47 |
+
cols: Iterable
|
| 48 |
+
) -> List[pd.DataFrame]:
|
| 49 |
+
df = read_table(filename)
|
| 50 |
+
print_err(df)
|
| 51 |
+
out = [gr.update(value=df, visible=False)]
|
| 52 |
+
for key, col in cols.items():
|
| 53 |
+
if isinstance(col, tuple):
|
| 54 |
+
col_type = col[1]
|
| 55 |
+
if col_type == "string":
|
| 56 |
+
choices = list(df.select_dtypes(include="str"))
|
| 57 |
+
elif col_type == "numeric":
|
| 58 |
+
choices = list(df.select_dtypes(include="number"))
|
| 59 |
+
else:
|
| 60 |
+
choices = list(df)
|
| 61 |
+
else:
|
| 62 |
+
choices = list(df)
|
| 63 |
+
choices = [""] + choices
|
| 64 |
+
print_err(key, f"{choices=}")
|
| 65 |
+
out.append(
|
| 66 |
+
gr.update(
|
| 67 |
+
choices=choices,
|
| 68 |
+
value=key if key in choices else choices[0],
|
| 69 |
+
interactive=True,
|
| 70 |
+
visible=True,
|
| 71 |
+
)
|
| 72 |
+
)
|
| 73 |
+
print_err(out)
|
| 74 |
+
return out
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def load_barcode_names(
|
| 78 |
+
df: pd.DataFrame,
|
| 79 |
+
strain_col: str
|
| 80 |
+
) -> List[List[str]]:
|
| 81 |
+
strains = sorted(df[strain_col].unique())
|
| 82 |
+
print_err(strain_col, f"{strains=}")
|
| 83 |
+
return gr.update(
|
| 84 |
+
choices=strains,
|
| 85 |
+
value="wt" if "wt" in strains else strains[0],
|
| 86 |
+
interactive=True,
|
| 87 |
+
visible=True,
|
| 88 |
+
), gr.update(
|
| 89 |
+
choices=strains,
|
| 90 |
+
value="spike" if "spike" in strains else "",
|
| 91 |
+
interactive=True,
|
| 92 |
+
visible=True,
|
| 93 |
+
), gr.update(
|
| 94 |
+
choices=strains,
|
| 95 |
+
value=[],
|
| 96 |
+
allow_custom_value=True,
|
| 97 |
+
interactive=True,
|
| 98 |
+
visible=True,
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def _prepare_to_fit(
|
| 103 |
+
counts: pd.DataFrame,
|
| 104 |
+
strain_sheet: pd.DataFrame,
|
| 105 |
+
sample_sheet: pd.DataFrame,
|
| 106 |
+
count_column: str,
|
| 107 |
+
strain_id_column: str,
|
| 108 |
+
timepoint_column: str,
|
| 109 |
+
concentration_column: str,
|
| 110 |
+
sample_id_column: str,
|
| 111 |
+
culture_id_column: str,
|
| 112 |
+
volume_column: str = "volume",
|
| 113 |
+
growth_column: str = "growth",
|
| 114 |
+
reference: str = "wt",
|
| 115 |
+
spike_name: str = "spike",
|
| 116 |
+
spike_mode: str = "Spike",
|
| 117 |
+
growth_type: str = "density",
|
| 118 |
+
pseudocount: float = 1.
|
| 119 |
+
):
|
| 120 |
+
use_spike = (spike_mode == "Spike")
|
| 121 |
+
adata = load_anndata(
|
| 122 |
+
counts=counts,
|
| 123 |
+
sample_meta=sample_sheet,
|
| 124 |
+
strain_meta=strain_sheet,
|
| 125 |
+
reference=reference,
|
| 126 |
+
count_column=count_column,
|
| 127 |
+
timepoint_column=timepoint_column,
|
| 128 |
+
# t0=args.t0,
|
| 129 |
+
concentration_column=concentration_column,
|
| 130 |
+
strain_id=strain_id_column,
|
| 131 |
+
sample_id=sample_id_column,
|
| 132 |
+
culture_id=culture_id_column,
|
| 133 |
+
spike=spike_name if spike_name else None,
|
| 134 |
+
)
|
| 135 |
+
print_err(adata)
|
| 136 |
+
adata = compute_log_ratios(
|
| 137 |
+
adata=adata,
|
| 138 |
+
pseudocount=pseudocount,
|
| 139 |
+
volume_column=volume_column,
|
| 140 |
+
growth_column=growth_column,
|
| 141 |
+
growth_type=growth_type,
|
| 142 |
+
use_spike=use_spike,
|
| 143 |
+
)
|
| 144 |
+
print_err(adata)
|
| 145 |
+
return adata
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def do_analysis(*args):
|
| 149 |
+
args = [
|
| 150 |
+
a if not (isinstance(a, str) and a == "") else None
|
| 151 |
+
for a in args
|
| 152 |
+
]
|
| 153 |
+
mode = args[-1]
|
| 154 |
+
concentration_column = args[3]
|
| 155 |
+
print_err(args[:-1])
|
| 156 |
+
try:
|
| 157 |
+
adata = _prepare_to_fit(*args[:-1])
|
| 158 |
+
except TypeError as e:
|
| 159 |
+
print_err(*args[:-1])
|
| 160 |
+
raise e
|
| 161 |
+
_message("Using a weighted least squares model")
|
| 162 |
+
model = AnnDataWLSModel()
|
| 163 |
+
results = model.fit(adata=adata)
|
| 164 |
+
if mode == MODES["dose response"]:
|
| 165 |
+
_message(
|
| 166 |
+
"Using a Hill non-linear model with "
|
| 167 |
+
f"'{concentration_column}' for concentration."
|
| 168 |
+
)
|
| 169 |
+
model = AnnDataHillModel()
|
| 170 |
+
results = model.fit(adata=results, concentration=concentration_column)
|
| 171 |
+
return gr.update(value=results.obs, visible=True), results
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
def _fig2img(fig):
|
| 175 |
+
import PIL
|
| 176 |
+
# img = PIL.Image.frombytes(
|
| 177 |
+
# "RGBa",
|
| 178 |
+
# fig.canvas.get_width_height(),
|
| 179 |
+
# fig.canvas.buffer_rgba(),
|
| 180 |
+
# )
|
| 181 |
+
import io
|
| 182 |
+
buf = io.BytesIO()
|
| 183 |
+
fig.savefig(buf)
|
| 184 |
+
buf.seek(0)
|
| 185 |
+
img = PIL.Image.open(buf)
|
| 186 |
+
return img
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
@decorator_with_params
|
| 190 |
+
def _plot_wrapper(fn, message="Plotting..."):
|
| 191 |
+
def _fn(*args, **kwargs):
|
| 192 |
+
if args[1] == "":
|
| 193 |
+
args[1] = None
|
| 194 |
+
if message:
|
| 195 |
+
_message(message)
|
| 196 |
+
fig, axes = fn(*args, **kwargs)
|
| 197 |
+
if isinstance(fig, tuple) and isinstance(axes, bool):
|
| 198 |
+
fig, vis = fig
|
| 199 |
+
return gr.update(
|
| 200 |
+
value=_fig2img(fig) if fig is not None else fig,
|
| 201 |
+
visible=vis,
|
| 202 |
+
)
|
| 203 |
+
else:
|
| 204 |
+
return gr.update(value=_fig2img(fig), visible=True)
|
| 205 |
+
return _fn
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
@_plot_wrapper()
|
| 209 |
+
def _plot_dose_response(
|
| 210 |
+
adata,
|
| 211 |
+
highlight=None,
|
| 212 |
+
control_prefix: str = "ctrl_",
|
| 213 |
+
mode: str = MODES["single"]
|
| 214 |
+
):
|
| 215 |
+
do_dose_response = mode == MODES["dose response"]
|
| 216 |
+
if do_dose_response:
|
| 217 |
+
print_err("Plotting dose response")
|
| 218 |
+
fig, axes = dose_response(
|
| 219 |
+
adata,
|
| 220 |
+
highlight_barcodes=highlight,
|
| 221 |
+
model_name="WLS",
|
| 222 |
+
control_prefix=control_prefix,
|
| 223 |
+
)
|
| 224 |
+
return fig, axes
|
| 225 |
+
else:
|
| 226 |
+
print_err("Skipping dose response")
|
| 227 |
+
return (None, None), False
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
@_plot_wrapper(message="Plotting time vs count")
|
| 231 |
+
def _plot_time_vs_count(
|
| 232 |
+
adata,
|
| 233 |
+
highlight=None,
|
| 234 |
+
control_prefix: str = "ctrl_",
|
| 235 |
+
*args, **kwargs
|
| 236 |
+
):
|
| 237 |
+
return time_vs_count(
|
| 238 |
+
adata,
|
| 239 |
+
highlight_barcodes=highlight,
|
| 240 |
+
control_prefix=control_prefix,
|
| 241 |
+
)
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
@_plot_wrapper(message="Plotting expansion vs count")
|
| 245 |
+
def _plot_expansion_vs_count(
|
| 246 |
+
adata,
|
| 247 |
+
highlight=None,
|
| 248 |
+
control_prefix: str = "ctrl_",
|
| 249 |
+
*args, **kwargs
|
| 250 |
+
):
|
| 251 |
+
return expansion_vs_count(
|
| 252 |
+
adata,
|
| 253 |
+
highlight_barcodes=highlight,
|
| 254 |
+
control_prefix=control_prefix,
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
@_plot_wrapper(message="Plotting time vs ratio")
|
| 259 |
+
def _plot_time_vs_ratio(
|
| 260 |
+
adata,
|
| 261 |
+
highlight=None,
|
| 262 |
+
control_prefix: str = "ctrl_",
|
| 263 |
+
*args, **kwargs
|
| 264 |
+
):
|
| 265 |
+
return time_vs_ratio(
|
| 266 |
+
adata,
|
| 267 |
+
highlight_barcodes=highlight,
|
| 268 |
+
control_prefix=control_prefix,
|
| 269 |
+
)
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
@_plot_wrapper(message="Plotting expansion vs ratio")
|
| 273 |
+
def _plot_expansion_vs_ratio(
|
| 274 |
+
adata,
|
| 275 |
+
highlight=None,
|
| 276 |
+
control_prefix: str = "ctrl_",
|
| 277 |
+
*args, **kwargs
|
| 278 |
+
):
|
| 279 |
+
return expansion_vs_ratio(
|
| 280 |
+
adata,
|
| 281 |
+
highlight_barcodes=highlight,
|
| 282 |
+
control_prefix=control_prefix,
|
| 283 |
+
)
|
| 284 |
+
|
| 285 |
+
@_plot_wrapper(message="Plotting predicted vs observed")
|
| 286 |
+
def _plot_pred_vs_true(
|
| 287 |
+
adata,
|
| 288 |
+
highlight=None,
|
| 289 |
+
control_prefix: str = "ctrl_",
|
| 290 |
+
mode: str = MODES["single"]
|
| 291 |
+
):
|
| 292 |
+
do_dose_response = mode == MODES["dose response"]
|
| 293 |
+
return pred_vs_true(
|
| 294 |
+
adata,
|
| 295 |
+
model_name="HillFitnessModel" if do_dose_response else "WLS",
|
| 296 |
+
highlight_barcodes=highlight,
|
| 297 |
+
control_prefix=control_prefix,
|
| 298 |
+
)
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
@_plot_wrapper(message="Plotting volcano")
|
| 302 |
+
def _plot_volcano(
|
| 303 |
+
adata,
|
| 304 |
+
highlight=None,
|
| 305 |
+
control_prefix: str = "ctrl_",
|
| 306 |
+
mode: str = MODES["single"]
|
| 307 |
+
):
|
| 308 |
+
do_dose_response = mode == MODES["dose response"]
|
| 309 |
+
return volcano(
|
| 310 |
+
adata,
|
| 311 |
+
highlight_barcodes=highlight,
|
| 312 |
+
control_prefix=control_prefix,
|
| 313 |
+
model_name="HillFitnessModel" if do_dose_response else "WLS",
|
| 314 |
+
param="ic50" if do_dose_response else "fitness",
|
| 315 |
+
xscale="log" if do_dose_response else "linear",
|
| 316 |
+
vline=None if do_dose_response else 1.,
|
| 317 |
+
p="log_ic50_p" if do_dose_response else "slope_p",
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
|
| 321 |
+
def download_tables(
|
| 322 |
+
df: pd.DataFrame,
|
| 323 |
+
adata
|
| 324 |
+
) -> str:
|
| 325 |
+
df_hash = nm.hash(pd.util.hash_pandas_object(df).values)
|
| 326 |
+
filename = f"bartab-{df_hash}"
|
| 327 |
+
filename_csv = f"{filename}.csv"
|
| 328 |
+
df.to_csv(filename, index=False)
|
| 329 |
+
filename_adata = f"{filename}.h5ad"
|
| 330 |
+
adata.write(filename_adata)
|
| 331 |
+
return gr.update(
|
| 332 |
+
value=filename_csv,
|
| 333 |
+
visible=True,
|
| 334 |
+
), gr.update(
|
| 335 |
+
value=filename_adata,
|
| 336 |
+
visible=True,
|
| 337 |
+
)
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
def _file_input(**kwargs):
|
| 342 |
+
return partial(gr.File,
|
| 343 |
+
file_types=[".xlsx", ".csv", ".tsv", ".txt"],
|
| 344 |
+
)(**kwargs)
|
| 345 |
+
|
| 346 |
+
|
| 347 |
+
def _load_from_file(*args):
|
| 348 |
+
if len(args) > 1:
|
| 349 |
+
return args
|
| 350 |
+
else:
|
| 351 |
+
return args[0]
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
def _invisible_dropdown(**kwargs):
|
| 355 |
+
return partial(gr.Dropdown,
|
| 356 |
+
choices=[],
|
| 357 |
+
interactive=False,
|
| 358 |
+
visible=True,
|
| 359 |
+
)(**kwargs)
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
def _invisible_plot(**kwargs):
|
| 363 |
+
return partial(gr.Image,
|
| 364 |
+
visible=False,
|
| 365 |
+
)(**kwargs)
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
with gr.Blocks() as demo:
|
| 369 |
+
gr.Markdown(
|
| 370 |
+
f"""
|
| 371 |
+
# 🍹 bartab: Fitness from pooled competition assays
|
| 372 |
+
|
| 373 |
+
*Using* `bartab` v{bartab.__version__} | [Documentation](https://github.com/scbirlab/bartab) | [Tutorial on analysis principles](https://huggingface.co/spaces/scbirlab/tutorial-seq-fitness)
|
| 374 |
+
|
| 375 |
+
Infer the competitive fitness of barcoded strains from next-generation
|
| 376 |
+
sequencing of pooled growth experiments.
|
| 377 |
+
|
| 378 |
+
Upload your count table, sample sheet, and barcode sheet, then
|
| 379 |
+
click **Calculate fitness**.
|
| 380 |
+
|
| 381 |
+
"""
|
| 382 |
+
)
|
| 383 |
+
gr.Markdown(
|
| 384 |
+
"""
|
| 385 |
+
---
|
| 386 |
+
|
| 387 |
+
## 1️⃣ Input tables
|
| 388 |
+
|
| 389 |
+
Three tables are required. You can upload CSV, TSV, or XLSX files,
|
| 390 |
+
or try one of the **example datasets** below.
|
| 391 |
+
|
| 392 |
+
"""
|
| 393 |
+
)
|
| 394 |
+
input_filenames = {
|
| 395 |
+
"count_table": gr.Textbox(interactive=False, visible=False),
|
| 396 |
+
"sample_sheet": gr.Textbox(interactive=False, visible=False),
|
| 397 |
+
"strain_sheet": gr.Textbox(interactive=False, visible=False),
|
| 398 |
+
}
|
| 399 |
+
app_root = os.path.dirname(__file__)
|
| 400 |
+
data_path = os.path.join(app_root, "data", "examples", "single-point")
|
| 401 |
+
control_strains = {
|
| 402 |
+
"reference": _invisible_dropdown(
|
| 403 |
+
label="Reference (WT) barcode name",
|
| 404 |
+
render=False,
|
| 405 |
+
),
|
| 406 |
+
"spike": _invisible_dropdown(
|
| 407 |
+
label="Spike-in barcode name (if using)",
|
| 408 |
+
render=False,
|
| 409 |
+
),
|
| 410 |
+
}
|
| 411 |
+
analysis_opts = {
|
| 412 |
+
"use_spike": gr.Radio(
|
| 413 |
+
label="Culture expansion uses:",
|
| 414 |
+
choices=["Spike", "Growth"],
|
| 415 |
+
value="Spike",
|
| 416 |
+
render=False,
|
| 417 |
+
),
|
| 418 |
+
"growth_type": gr.Radio(
|
| 419 |
+
label="Growth type",
|
| 420 |
+
choices=["density", "generations"],
|
| 421 |
+
value="density",
|
| 422 |
+
visible=False,
|
| 423 |
+
render=False,
|
| 424 |
+
),
|
| 425 |
+
"pseudocount": gr.Number(
|
| 426 |
+
label="Pseudocount",
|
| 427 |
+
value=1.,
|
| 428 |
+
render=False,
|
| 429 |
+
),
|
| 430 |
+
}
|
| 431 |
+
plotting_opts = {
|
| 432 |
+
"highlight": _invisible_dropdown(
|
| 433 |
+
label="Strain(s) to highlight in plots",
|
| 434 |
+
render=False,
|
| 435 |
+
multiselect=True,
|
| 436 |
+
),
|
| 437 |
+
"controls": gr.Textbox(
|
| 438 |
+
label="Prefix of control barcode names",
|
| 439 |
+
value="ctrl_",
|
| 440 |
+
render=False,
|
| 441 |
+
),
|
| 442 |
+
}
|
| 443 |
+
mode_switch = gr.Radio(
|
| 444 |
+
label="Analysis mode",
|
| 445 |
+
choices=list(MODES.values()),
|
| 446 |
+
value=MODES["single"],
|
| 447 |
+
render=False,
|
| 448 |
+
)
|
| 449 |
+
examples = gr.Examples(
|
| 450 |
+
label="Examples with synthetic data",
|
| 451 |
+
examples=[
|
| 452 |
+
[
|
| 453 |
+
os.path.join(data_path, "test_count.csv"),
|
| 454 |
+
os.path.join(data_path, "test_sample_meta.csv"),
|
| 455 |
+
os.path.join(data_path, "test_strain_meta.csv"),
|
| 456 |
+
MODES["single"],
|
| 457 |
+
"Spike",
|
| 458 |
+
],
|
| 459 |
+
[
|
| 460 |
+
os.path.join(data_path, "test_count.csv"),
|
| 461 |
+
os.path.join(data_path, "test_sample_meta.csv"),
|
| 462 |
+
os.path.join(data_path, "test_strain_meta.csv"),
|
| 463 |
+
MODES["single"],
|
| 464 |
+
"Growth",
|
| 465 |
+
],
|
| 466 |
+
[
|
| 467 |
+
os.path.join(data_path, "dose-response_count.csv"),
|
| 468 |
+
os.path.join(data_path, "dose-response_sample_meta.csv"),
|
| 469 |
+
os.path.join(data_path, "dose-response_strain_meta.csv"),
|
| 470 |
+
MODES["dose response"],
|
| 471 |
+
"Spike",
|
| 472 |
+
],
|
| 473 |
+
[
|
| 474 |
+
os.path.join(data_path, "dose-response_count.csv"),
|
| 475 |
+
os.path.join(data_path, "dose-response_sample_meta.csv"),
|
| 476 |
+
os.path.join(data_path, "dose-response_strain_meta.csv"),
|
| 477 |
+
MODES["dose response"],
|
| 478 |
+
"Growth",
|
| 479 |
+
],
|
| 480 |
+
],
|
| 481 |
+
example_labels=[
|
| 482 |
+
["Single point, using spike-in"],
|
| 483 |
+
["Single point, using growth"],
|
| 484 |
+
["Dose response, using spike-in"],
|
| 485 |
+
["Dose response, using growth"],
|
| 486 |
+
],
|
| 487 |
+
inputs=[
|
| 488 |
+
input_filenames["count_table"],
|
| 489 |
+
input_filenames["sample_sheet"],
|
| 490 |
+
input_filenames["strain_sheet"],
|
| 491 |
+
mode_switch,
|
| 492 |
+
analysis_opts["use_spike"],
|
| 493 |
+
],
|
| 494 |
+
# cache_examples=True,
|
| 495 |
+
# cache_mode="eager",
|
| 496 |
+
)
|
| 497 |
+
input_files = {}
|
| 498 |
+
input_cols = {}
|
| 499 |
+
go_button = gr.Button(
|
| 500 |
+
value="🚀 Calculate fitness!",
|
| 501 |
+
interactive=False,
|
| 502 |
+
render=False,
|
| 503 |
+
)
|
| 504 |
+
with gr.Row():
|
| 505 |
+
with gr.Column():
|
| 506 |
+
gr.Markdown(
|
| 507 |
+
"""
|
| 508 |
+
---
|
| 509 |
+
|
| 510 |
+
### 🧮 Count table
|
| 511 |
+
|
| 512 |
+
One row per barcode per sample. Must contain:
|
| 513 |
+
- a column of **barcode/strain identifiers** (matching your barcode sheet)
|
| 514 |
+
- a column of **sample identifiers** (matching your sample sheet)
|
| 515 |
+
- a column of **read or UMI counts**
|
| 516 |
+
|
| 517 |
+
"""
|
| 518 |
+
)
|
| 519 |
+
input_files["count_table"] = _file_input(
|
| 520 |
+
label="Upload your barcode sequencing counts data here",
|
| 521 |
+
)
|
| 522 |
+
input_cols["count_table"] = {
|
| 523 |
+
"count": (_invisible_dropdown(
|
| 524 |
+
label="Counts column",
|
| 525 |
+
), "numeric"),
|
| 526 |
+
}
|
| 527 |
+
with gr.Column():
|
| 528 |
+
gr.Markdown(
|
| 529 |
+
"""
|
| 530 |
+
---
|
| 531 |
+
|
| 532 |
+
### 📶 Barcode information
|
| 533 |
+
|
| 534 |
+
One row per unique barcode. Must contain:
|
| 535 |
+
- a column of **barcode identifiers**
|
| 536 |
+
|
| 537 |
+
Optionally: any metadata about strains (gene targets, constructs,
|
| 538 |
+
etc.). These will be carried through to the output.
|
| 539 |
+
|
| 540 |
+
"""
|
| 541 |
+
)
|
| 542 |
+
input_files["strain_sheet"] = _file_input(
|
| 543 |
+
label="Upload your barcode information here",
|
| 544 |
+
)
|
| 545 |
+
input_cols["strain_sheet"] = {
|
| 546 |
+
"strain_id": (_invisible_dropdown(
|
| 547 |
+
label="Barcode identifier column",
|
| 548 |
+
), "string"),
|
| 549 |
+
}
|
| 550 |
+
with gr.Row():
|
| 551 |
+
gr.Markdown(
|
| 552 |
+
r"""
|
| 553 |
+
---
|
| 554 |
+
|
| 555 |
+
### 🧪 Sample sheet
|
| 556 |
+
|
| 557 |
+
One row per sample (sequencing library). Must contain:
|
| 558 |
+
- **Sample ID**: unique identifier matching the count table
|
| 559 |
+
- **Culture ID**: biological replicate identifier. Samples from
|
| 560 |
+
the same culture share this label
|
| 561 |
+
- **Timepoint**: numeric timepoint values. The earliest timepoint
|
| 562 |
+
is treated as $t_0$.
|
| 563 |
+
|
| 564 |
+
**For spike-in normalisation**:
|
| 565 |
+
no extra columns needed. Just include your spike-in barcode in
|
| 566 |
+
the count table and barcode sheet.
|
| 567 |
+
|
| 568 |
+
**For growth-based normalisation**: add a column of OD600, CFU/mL,
|
| 569 |
+
or generation counts measured at each sample.
|
| 570 |
+
|
| 571 |
+
**For dose-response analysis**: add a column of inducer/drug
|
| 572 |
+
concentrations. Samples with concentration = 0 are treated as
|
| 573 |
+
uninduced controls.
|
| 574 |
+
|
| 575 |
+
**For adaptive-volume sampling** (if you took different volumes
|
| 576 |
+
from each sample): add a column of sampled volumes.
|
| 577 |
+
|
| 578 |
+
"""
|
| 579 |
+
)
|
| 580 |
+
input_files["sample_sheet"] = _file_input(
|
| 581 |
+
label="Upload your sample information here",
|
| 582 |
+
)
|
| 583 |
+
with gr.Row():
|
| 584 |
+
input_cols["sample_sheet"] = {
|
| 585 |
+
"timepoint": (_invisible_dropdown(
|
| 586 |
+
label="Timepoint column",
|
| 587 |
+
), "any"),
|
| 588 |
+
"dose": (_invisible_dropdown(
|
| 589 |
+
label="Concentration column",
|
| 590 |
+
), "numeric"),
|
| 591 |
+
"sample_id": (_invisible_dropdown(
|
| 592 |
+
label="Individual sample ID column",
|
| 593 |
+
), "string"),
|
| 594 |
+
"replicate": (_invisible_dropdown(
|
| 595 |
+
label="Culture / biological replicate column",
|
| 596 |
+
), "string"),
|
| 597 |
+
"volume": (_invisible_dropdown(
|
| 598 |
+
label="Volume column (if using)",
|
| 599 |
+
), "numeric"),
|
| 600 |
+
"growth": (_invisible_dropdown(
|
| 601 |
+
label="Growth column (if using)",
|
| 602 |
+
), "numeric"),
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
with gr.Row():
|
| 606 |
+
input_data = {
|
| 607 |
+
key: gr.Dataframe(
|
| 608 |
+
label=f"Input data: {key}",
|
| 609 |
+
max_height=50,
|
| 610 |
+
visible=False,
|
| 611 |
+
interactive=False,
|
| 612 |
+
) for key in input_files
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
adata = gr.State()
|
| 616 |
+
with gr.Row():
|
| 617 |
+
with gr.Column():
|
| 618 |
+
gr.Markdown(
|
| 619 |
+
"""
|
| 620 |
+
---
|
| 621 |
+
|
| 622 |
+
## 2️⃣ Control strains
|
| 623 |
+
|
| 624 |
+
- **Reference (WT)**: the strain relative to which all
|
| 625 |
+
fitness values are calculated. Fitness = 1 by definition.
|
| 626 |
+
- **Spike-in**: a non-growing strain (e.g. heat-killed or
|
| 627 |
+
plasmid-only) added at a fixed concentration before library
|
| 628 |
+
preparation. Used to infer how much the reference strain has
|
| 629 |
+
expanded between timepoints, removing the need for growth
|
| 630 |
+
measurements. Leave blank if using growth measurements instead.
|
| 631 |
+
|
| 632 |
+
"""
|
| 633 |
+
)
|
| 634 |
+
for key, val in control_strains.items():
|
| 635 |
+
val.render()
|
| 636 |
+
with gr.Column():
|
| 637 |
+
gr.Markdown(
|
| 638 |
+
"""
|
| 639 |
+
---
|
| 640 |
+
|
| 641 |
+
## 3️⃣ Analysis options
|
| 642 |
+
|
| 643 |
+
- **Culture expansion**: choose **Spike** if you have a
|
| 644 |
+
non-growing spike-in control, or **Growth** if you have
|
| 645 |
+
OD600/CFU measurements.
|
| 646 |
+
- **Pseudocount**: added to all counts before log transformation
|
| 647 |
+
to avoid log(0).
|
| 648 |
+
- **Analysis mode**: choose **Single concentration** for standard fitness
|
| 649 |
+
screens, or **Dose response** if your sample sheet contains a concentration
|
| 650 |
+
column. Dose response fitting uses a 2-parameter Hill model to estimate the
|
| 651 |
+
IC₅₀ and maximum effectfor each barcode.
|
| 652 |
+
|
| 653 |
+
"""
|
| 654 |
+
)
|
| 655 |
+
for key, val in analysis_opts.items():
|
| 656 |
+
val.render()
|
| 657 |
+
with gr.Column():
|
| 658 |
+
gr.Markdown(
|
| 659 |
+
"""
|
| 660 |
+
---
|
| 661 |
+
|
| 662 |
+
## Plotting options
|
| 663 |
+
|
| 664 |
+
"""
|
| 665 |
+
)
|
| 666 |
+
for key, val in plotting_opts.items():
|
| 667 |
+
val.render()
|
| 668 |
+
|
| 669 |
+
with gr.Column():
|
| 670 |
+
mode_switch.render()
|
| 671 |
+
go_button.render()
|
| 672 |
+
|
| 673 |
+
mode_switch.change(
|
| 674 |
+
lambda x: gr.update(value=x),
|
| 675 |
+
inputs=[mode_switch],
|
| 676 |
+
outputs=[go_button],
|
| 677 |
+
)
|
| 678 |
+
gr.Markdown(
|
| 679 |
+
r"""
|
| 680 |
+
## 4️⃣ Results
|
| 681 |
+
|
| 682 |
+
Fitness values are estimated by weighted least squares regression of the log-ratio of each barcode against the reference strain, using the spike-in or growth measurements as the x-axis.
|
| 683 |
+
|
| 684 |
+
**Key output columns**:
|
| 685 |
+
- For single concentration:
|
| 686 |
+
- `fitness`: relative fitness ($w_i / w_{wt}$). Values < 1 indicate growth disadvantage; > 1 indicates advantage.
|
| 687 |
+
- `fitness_low` / `fitness_high`: 95% confidence interval bounds.
|
| 688 |
+
- `slope_p`: p-value for the slope being different from 0 (i.e. fitness ≠ 1).
|
| 689 |
+
- For dose-response:
|
| 690 |
+
- `log_ic50` (log₁₀ concentration at 50% inhibition) and `log_ic50_p`.
|
| 691 |
+
|
| 692 |
+
Results and the full annotated dataset (`.h5ad`) can be downloaded below.
|
| 693 |
+
|
| 694 |
+
"""
|
| 695 |
+
)
|
| 696 |
+
|
| 697 |
+
plots = {}
|
| 698 |
+
with gr.Row():
|
| 699 |
+
plots |= {
|
| 700 |
+
"dose_response": (
|
| 701 |
+
_invisible_plot(label="Dose response"),
|
| 702 |
+
_plot_dose_response,
|
| 703 |
+
),
|
| 704 |
+
"count_time": (
|
| 705 |
+
_invisible_plot(label="Time vs count"),
|
| 706 |
+
_plot_time_vs_count,
|
| 707 |
+
),
|
| 708 |
+
"count_exp": (
|
| 709 |
+
_invisible_plot(label="Expansion vs count"),
|
| 710 |
+
_plot_expansion_vs_count,
|
| 711 |
+
),
|
| 712 |
+
}
|
| 713 |
+
with gr.Row():
|
| 714 |
+
plots |= {
|
| 715 |
+
"count_exp": (
|
| 716 |
+
_invisible_plot(label="Time vs ratio"),
|
| 717 |
+
_plot_time_vs_ratio,
|
| 718 |
+
),
|
| 719 |
+
"ratio_exp": (
|
| 720 |
+
_invisible_plot(label="Expansion vs ratio"),
|
| 721 |
+
_plot_expansion_vs_ratio,
|
| 722 |
+
),
|
| 723 |
+
}
|
| 724 |
+
with gr.Row():
|
| 725 |
+
plots |= {
|
| 726 |
+
"pred_obs": (
|
| 727 |
+
_invisible_plot(label="Predicted vs observed"),
|
| 728 |
+
_plot_pred_vs_true,
|
| 729 |
+
),
|
| 730 |
+
"volcano": (
|
| 731 |
+
_invisible_plot(label="Volcano"),
|
| 732 |
+
_plot_volcano,
|
| 733 |
+
),
|
| 734 |
+
}
|
| 735 |
+
with gr.Row():
|
| 736 |
+
download = gr.DownloadButton(
|
| 737 |
+
label="Download parameters as CSV",
|
| 738 |
+
visible=False,
|
| 739 |
+
)
|
| 740 |
+
download_adata = gr.DownloadButton(
|
| 741 |
+
label="Download all analysis as .h5ad",
|
| 742 |
+
visible=False,
|
| 743 |
+
)
|
| 744 |
+
output_table = gr.Dataframe(
|
| 745 |
+
label="Fitted parameters",
|
| 746 |
+
# max_height=100,
|
| 747 |
+
visible=False,
|
| 748 |
+
interactive=False,
|
| 749 |
+
)
|
| 750 |
+
|
| 751 |
+
# ======
|
| 752 |
+
# EVENTS
|
| 753 |
+
# ======
|
| 754 |
+
|
| 755 |
+
for key, input_file in input_files.items():
|
| 756 |
+
input_columns = input_cols[key]
|
| 757 |
+
event_fn = {
|
| 758 |
+
"fn": partial(load_input_data, cols=input_columns),
|
| 759 |
+
"outputs": [input_data[key]] + [
|
| 760 |
+
col[0] if isinstance(col, tuple) else col
|
| 761 |
+
for _, col in input_columns.items()
|
| 762 |
+
],
|
| 763 |
+
}
|
| 764 |
+
input_filenames[key].change(
|
| 765 |
+
_load_from_file,
|
| 766 |
+
inputs=[input_filenames[key]],
|
| 767 |
+
outputs=[input_file],
|
| 768 |
+
).then(
|
| 769 |
+
**event_fn,
|
| 770 |
+
inputs=[input_filenames[key]],
|
| 771 |
+
)
|
| 772 |
+
input_file.upload(
|
| 773 |
+
**event_fn,
|
| 774 |
+
inputs=[input_file],
|
| 775 |
+
)
|
| 776 |
+
|
| 777 |
+
input_cols["strain_sheet"]["strain_id"][0].change(
|
| 778 |
+
load_barcode_names,
|
| 779 |
+
inputs=[
|
| 780 |
+
input_data["strain_sheet"],
|
| 781 |
+
input_cols["strain_sheet"]["strain_id"][0],
|
| 782 |
+
],
|
| 783 |
+
outputs=[
|
| 784 |
+
control_strains["reference"],
|
| 785 |
+
control_strains["spike"],
|
| 786 |
+
plotting_opts["highlight"],
|
| 787 |
+
],
|
| 788 |
+
).then(
|
| 789 |
+
lambda : gr.update(interactive=True),
|
| 790 |
+
inputs=[],
|
| 791 |
+
outputs=[go_button],
|
| 792 |
+
)
|
| 793 |
+
|
| 794 |
+
analysis_opts["use_spike"].change(
|
| 795 |
+
lambda x: gr.update(visible=x == "Growth"),
|
| 796 |
+
inputs=[analysis_opts["use_spike"]],
|
| 797 |
+
outputs=[analysis_opts["growth_type"]],
|
| 798 |
+
)
|
| 799 |
+
|
| 800 |
+
comptuation_inputs = (
|
| 801 |
+
[
|
| 802 |
+
f for _, f in input_data.items()
|
| 803 |
+
] + [
|
| 804 |
+
opt[0] if isinstance(opt, tuple) else opt
|
| 805 |
+
for _, input_col in input_cols.items()
|
| 806 |
+
for _, opt in input_col.items()
|
| 807 |
+
] + [
|
| 808 |
+
v for k, v in control_strains.items()
|
| 809 |
+
] + [
|
| 810 |
+
v for k, v in analysis_opts.items()
|
| 811 |
+
]
|
| 812 |
+
)
|
| 813 |
+
|
| 814 |
+
evt = go_button.click(
|
| 815 |
+
fn=do_analysis,
|
| 816 |
+
inputs=comptuation_inputs + [mode_switch],
|
| 817 |
+
outputs=[
|
| 818 |
+
output_table,
|
| 819 |
+
adata,
|
| 820 |
+
],
|
| 821 |
+
).then(
|
| 822 |
+
download_tables,
|
| 823 |
+
inputs=[output_table, adata],
|
| 824 |
+
outputs=[download, download_adata],
|
| 825 |
+
)
|
| 826 |
+
|
| 827 |
+
for key, (p, fn) in plots.items():
|
| 828 |
+
evt = evt.then(
|
| 829 |
+
fn,
|
| 830 |
+
inputs=[
|
| 831 |
+
adata,
|
| 832 |
+
plotting_opts["highlight"],
|
| 833 |
+
plotting_opts["controls"],
|
| 834 |
+
mode_switch,
|
| 835 |
+
],
|
| 836 |
+
outputs=[p],
|
| 837 |
+
)
|
| 838 |
+
|
| 839 |
+
if __name__ == "__main__":
|
| 840 |
+
demo.queue()
|
| 841 |
+
demo.launch(share=True)
|
data/examples/single-point/dose-response_count.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/examples/single-point/dose-response_sample_meta.csv
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
sample_id,replicate,timepoint,dose,growth,generations,is_t0
|
| 2 |
+
dose_0-rep_0-t_0,dose_0-rep_0,0.0,0.12345679012345678,117055.0,0.0,True
|
| 3 |
+
dose_0-rep_0-t_1,dose_0-rep_0,1.0,0.12345679012345678,234292.89384810615,1.0011266371943761,False
|
| 4 |
+
dose_0-rep_0-t_2,dose_0-rep_0,2.0,0.12345679012345678,427061.5122706585,1.8672573245346546,False
|
| 5 |
+
dose_0-rep_0-t_3,dose_0-rep_0,3.0,0.12345679012345678,668560.4452222767,2.5138714412935887,False
|
| 6 |
+
dose_0-rep_0-t_4,dose_0-rep_0,4.0,0.12345679012345678,883476.5973974025,2.9160053589907093,False
|
| 7 |
+
dose_0-rep_0-t_5,dose_0-rep_0,5.0,0.12345679012345678,1024302.3566620992,3.129383171737148,False
|
| 8 |
+
dose_0-rep_1-t_0,dose_0-rep_1,0.0,0.12345679012345678,117055.0,0.0,True
|
| 9 |
+
dose_0-rep_1-t_1,dose_0-rep_1,1.0,0.12345679012345678,234292.89384810615,1.0011266371943761,False
|
| 10 |
+
dose_0-rep_1-t_2,dose_0-rep_1,2.0,0.12345679012345678,427061.5122706585,1.8672573245346546,False
|
| 11 |
+
dose_0-rep_1-t_3,dose_0-rep_1,3.0,0.12345679012345678,668560.4452222767,2.5138714412935887,False
|
| 12 |
+
dose_0-rep_1-t_4,dose_0-rep_1,4.0,0.12345679012345678,883476.5973974025,2.9160053589907093,False
|
| 13 |
+
dose_0-rep_1-t_5,dose_0-rep_1,5.0,0.12345679012345678,1024302.3566620992,3.129383171737148,False
|
| 14 |
+
dose_0-rep_2-t_0,dose_0-rep_2,0.0,0.12345679012345678,117055.0,0.0,True
|
| 15 |
+
dose_0-rep_2-t_1,dose_0-rep_2,1.0,0.12345679012345678,234292.89384810615,1.0011266371943761,False
|
| 16 |
+
dose_0-rep_2-t_2,dose_0-rep_2,2.0,0.12345679012345678,427061.5122706585,1.8672573245346546,False
|
| 17 |
+
dose_0-rep_2-t_3,dose_0-rep_2,3.0,0.12345679012345678,668560.4452222767,2.5138714412935887,False
|
| 18 |
+
dose_0-rep_2-t_4,dose_0-rep_2,4.0,0.12345679012345678,883476.5973974025,2.9160053589907093,False
|
| 19 |
+
dose_0-rep_2-t_5,dose_0-rep_2,5.0,0.12345679012345678,1024302.3566620992,3.129383171737148,False
|
| 20 |
+
dose_1-rep_0-t_0,dose_1-rep_0,0.0,0.20117262002701805,117055.0,0.0,True
|
| 21 |
+
dose_1-rep_0-t_1,dose_1-rep_0,1.0,0.20117262002701805,222422.7611495618,0.9261178702440107,False
|
| 22 |
+
dose_1-rep_0-t_2,dose_1-rep_0,2.0,0.20117262002701805,394457.30302182614,1.7526825875833112,False
|
| 23 |
+
dose_1-rep_0-t_3,dose_1-rep_0,3.0,0.20117262002701805,618290.3220565522,2.401097863199693,False
|
| 24 |
+
dose_1-rep_0-t_4,dose_1-rep_0,4.0,0.20117262002701805,833511.6554962726,2.832015812996294,False
|
| 25 |
+
dose_1-rep_0-t_5,dose_1-rep_0,5.0,0.20117262002701805,988339.672526323,3.077820391955883,False
|
| 26 |
+
dose_1-rep_1-t_0,dose_1-rep_1,0.0,0.20117262002701805,117055.0,0.0,True
|
| 27 |
+
dose_1-rep_1-t_1,dose_1-rep_1,1.0,0.20117262002701805,222422.7611495618,0.9261178702440107,False
|
| 28 |
+
dose_1-rep_1-t_2,dose_1-rep_1,2.0,0.20117262002701805,394457.30302182614,1.7526825875833112,False
|
| 29 |
+
dose_1-rep_1-t_3,dose_1-rep_1,3.0,0.20117262002701805,618290.3220565522,2.401097863199693,False
|
| 30 |
+
dose_1-rep_1-t_4,dose_1-rep_1,4.0,0.20117262002701805,833511.6554962726,2.832015812996294,False
|
| 31 |
+
dose_1-rep_1-t_5,dose_1-rep_1,5.0,0.20117262002701805,988339.672526323,3.077820391955883,False
|
| 32 |
+
dose_1-rep_2-t_0,dose_1-rep_2,0.0,0.20117262002701805,117055.0,0.0,True
|
| 33 |
+
dose_1-rep_2-t_1,dose_1-rep_2,1.0,0.20117262002701805,222422.7611495618,0.9261178702440107,False
|
| 34 |
+
dose_1-rep_2-t_2,dose_1-rep_2,2.0,0.20117262002701805,394457.30302182614,1.7526825875833112,False
|
| 35 |
+
dose_1-rep_2-t_3,dose_1-rep_2,3.0,0.20117262002701805,618290.3220565522,2.401097863199693,False
|
| 36 |
+
dose_1-rep_2-t_4,dose_1-rep_2,4.0,0.20117262002701805,833511.6554962726,2.832015812996294,False
|
| 37 |
+
dose_1-rep_2-t_5,dose_1-rep_2,5.0,0.20117262002701805,988339.672526323,3.077820391955883,False
|
| 38 |
+
dose_2-rep_0-t_0,dose_2-rep_0,0.0,0.3278104266931334,117055.0,0.0,True
|
| 39 |
+
dose_2-rep_0-t_1,dose_2-rep_0,1.0,0.3278104266931334,208766.2945323125,0.834702246130147,False
|
| 40 |
+
dose_2-rep_0-t_2,dose_2-rep_0,2.0,0.3278104266931334,356837.17092046584,1.6080793449317268,False
|
| 41 |
+
dose_2-rep_0-t_3,dose_2-rep_0,3.0,0.3278104266931334,557154.5259169642,2.250890951794641,False
|
| 42 |
+
dose_2-rep_0-t_4,dose_2-rep_0,4.0,0.3278104266931334,767351.9087930336,2.712701791269896,False
|
| 43 |
+
dose_2-rep_0-t_5,dose_2-rep_0,5.0,0.3278104266931334,936068.5780837294,2.9994276677073946,False
|
| 44 |
+
dose_2-rep_1-t_0,dose_2-rep_1,0.0,0.3278104266931334,117055.0,0.0,True
|
| 45 |
+
dose_2-rep_1-t_1,dose_2-rep_1,1.0,0.3278104266931334,208766.2945323125,0.834702246130147,False
|
| 46 |
+
dose_2-rep_1-t_2,dose_2-rep_1,2.0,0.3278104266931334,356837.17092046584,1.6080793449317268,False
|
| 47 |
+
dose_2-rep_1-t_3,dose_2-rep_1,3.0,0.3278104266931334,557154.5259169642,2.250890951794641,False
|
| 48 |
+
dose_2-rep_1-t_4,dose_2-rep_1,4.0,0.3278104266931334,767351.9087930336,2.712701791269896,False
|
| 49 |
+
dose_2-rep_1-t_5,dose_2-rep_1,5.0,0.3278104266931334,936068.5780837294,2.9994276677073946,False
|
| 50 |
+
dose_2-rep_2-t_0,dose_2-rep_2,0.0,0.3278104266931334,117055.0,0.0,True
|
| 51 |
+
dose_2-rep_2-t_1,dose_2-rep_2,1.0,0.3278104266931334,208766.2945323125,0.834702246130147,False
|
| 52 |
+
dose_2-rep_2-t_2,dose_2-rep_2,2.0,0.3278104266931334,356837.17092046584,1.6080793449317268,False
|
| 53 |
+
dose_2-rep_2-t_3,dose_2-rep_2,3.0,0.3278104266931334,557154.5259169642,2.250890951794641,False
|
| 54 |
+
dose_2-rep_2-t_4,dose_2-rep_2,4.0,0.3278104266931334,767351.9087930336,2.712701791269896,False
|
| 55 |
+
dose_2-rep_2-t_5,dose_2-rep_2,5.0,0.3278104266931334,936068.5780837294,2.9994276677073946,False
|
| 56 |
+
dose_3-rep_0-t_0,dose_3-rep_0,0.0,0.5341665075212624,117055.0,0.0,True
|
| 57 |
+
dose_3-rep_0-t_1,dose_3-rep_0,1.0,0.5341665075212624,194167.85296808663,0.7301178030311807,False
|
| 58 |
+
dose_3-rep_0-t_2,dose_3-rep_0,2.0,0.5341665075212624,316942.8764619754,1.437036282232122,False
|
| 59 |
+
dose_3-rep_0-t_3,dose_3-rep_0,3.0,0.5341665075212624,489512.636121671,2.0641595411437166,False
|
| 60 |
+
dose_3-rep_0-t_4,dose_3-rep_0,4.0,0.5341665075212624,687865.3222216408,2.5549395655675515,False
|
| 61 |
+
dose_3-rep_0-t_5,dose_3-rep_0,5.0,0.5341665075212624,867383.0729686539,2.889482728766238,False
|
| 62 |
+
dose_3-rep_1-t_0,dose_3-rep_1,0.0,0.5341665075212624,117055.0,0.0,True
|
| 63 |
+
dose_3-rep_1-t_1,dose_3-rep_1,1.0,0.5341665075212624,194167.85296808663,0.7301178030311807,False
|
| 64 |
+
dose_3-rep_1-t_2,dose_3-rep_1,2.0,0.5341665075212624,316942.8764619754,1.437036282232122,False
|
| 65 |
+
dose_3-rep_1-t_3,dose_3-rep_1,3.0,0.5341665075212624,489512.636121671,2.0641595411437166,False
|
| 66 |
+
dose_3-rep_1-t_4,dose_3-rep_1,4.0,0.5341665075212624,687865.3222216408,2.5549395655675515,False
|
| 67 |
+
dose_3-rep_1-t_5,dose_3-rep_1,5.0,0.5341665075212624,867383.0729686539,2.889482728766238,False
|
| 68 |
+
dose_3-rep_2-t_0,dose_3-rep_2,0.0,0.5341665075212624,117055.0,0.0,True
|
| 69 |
+
dose_3-rep_2-t_1,dose_3-rep_2,1.0,0.5341665075212624,194167.85296808663,0.7301178030311807,False
|
| 70 |
+
dose_3-rep_2-t_2,dose_3-rep_2,2.0,0.5341665075212624,316942.8764619754,1.437036282232122,False
|
| 71 |
+
dose_3-rep_2-t_3,dose_3-rep_2,3.0,0.5341665075212624,489512.636121671,2.0641595411437166,False
|
| 72 |
+
dose_3-rep_2-t_4,dose_3-rep_2,4.0,0.5341665075212624,687865.3222216408,2.5549395655675515,False
|
| 73 |
+
dose_3-rep_2-t_5,dose_3-rep_2,5.0,0.5341665075212624,867383.0729686539,2.889482728766238,False
|
| 74 |
+
dose_4-rep_0-t_0,dose_4-rep_0,0.0,0.870423374374747,117055.0,0.0,True
|
| 75 |
+
dose_4-rep_0-t_1,dose_4-rep_0,1.0,0.870423374374747,179849.0377847039,0.619599880459945,False
|
| 76 |
+
dose_4-rep_0-t_2,dose_4-rep_0,2.0,0.870423374374747,278757.0181696531,1.2518215672959792,False
|
| 77 |
+
dose_4-rep_0-t_3,dose_4-rep_0,3.0,0.870423374374747,423504.06388361723,1.8551892530849372,False
|
| 78 |
+
dose_4-rep_0-t_4,dose_4-rep_0,4.0,0.870423374374747,605732.9764283933,2.3714953941895147,False
|
| 79 |
+
dose_4-rep_0-t_5,dose_4-rep_0,5.0,0.870423374374747,791779.1028853382,2.757911430955815,False
|
| 80 |
+
dose_4-rep_1-t_0,dose_4-rep_1,0.0,0.870423374374747,117055.0,0.0,True
|
| 81 |
+
dose_4-rep_1-t_1,dose_4-rep_1,1.0,0.870423374374747,179849.0377847039,0.619599880459945,False
|
| 82 |
+
dose_4-rep_1-t_2,dose_4-rep_1,2.0,0.870423374374747,278757.0181696531,1.2518215672959792,False
|
| 83 |
+
dose_4-rep_1-t_3,dose_4-rep_1,3.0,0.870423374374747,423504.06388361723,1.8551892530849372,False
|
| 84 |
+
dose_4-rep_1-t_4,dose_4-rep_1,4.0,0.870423374374747,605732.9764283933,2.3714953941895147,False
|
| 85 |
+
dose_4-rep_1-t_5,dose_4-rep_1,5.0,0.870423374374747,791779.1028853382,2.757911430955815,False
|
| 86 |
+
dose_4-rep_2-t_0,dose_4-rep_2,0.0,0.870423374374747,117055.0,0.0,True
|
| 87 |
+
dose_4-rep_2-t_1,dose_4-rep_2,1.0,0.870423374374747,179849.0377847039,0.619599880459945,False
|
| 88 |
+
dose_4-rep_2-t_2,dose_4-rep_2,2.0,0.870423374374747,278757.0181696531,1.2518215672959792,False
|
| 89 |
+
dose_4-rep_2-t_3,dose_4-rep_2,3.0,0.870423374374747,423504.06388361723,1.8551892530849372,False
|
| 90 |
+
dose_4-rep_2-t_4,dose_4-rep_2,4.0,0.870423374374747,605732.9764283933,2.3714953941895147,False
|
| 91 |
+
dose_4-rep_2-t_5,dose_4-rep_2,5.0,0.870423374374747,791779.1028853382,2.757911430955815,False
|
| 92 |
+
dose_5-rep_0-t_0,dose_5-rep_0,0.0,1.41835334112138,117055.0,0.0,True
|
| 93 |
+
dose_5-rep_0-t_1,dose_5-rep_0,1.0,1.41835334112138,167060.34358941315,0.5131827498868529,False
|
| 94 |
+
dose_5-rep_0-t_2,dose_5-rep_0,2.0,1.41835334112138,246041.4256362762,1.0717146800456518,False
|
| 95 |
+
dose_5-rep_0-t_3,dose_5-rep_0,3.0,1.41835334112138,367542.52779013116,1.6507246312376866,False
|
| 96 |
+
dose_5-rep_0-t_4,dose_5-rep_0,4.0,1.41835334112138,535033.3697428543,2.1924423140004268,False
|
| 97 |
+
dose_5-rep_0-t_5,dose_5-rep_0,5.0,1.41835334112138,726051.529930286,2.6328853835701116,False
|
| 98 |
+
dose_5-rep_1-t_0,dose_5-rep_1,0.0,1.41835334112138,117055.0,0.0,True
|
| 99 |
+
dose_5-rep_1-t_1,dose_5-rep_1,1.0,1.41835334112138,167060.34358941315,0.5131827498868529,False
|
| 100 |
+
dose_5-rep_1-t_2,dose_5-rep_1,2.0,1.41835334112138,246041.4256362762,1.0717146800456518,False
|
| 101 |
+
dose_5-rep_1-t_3,dose_5-rep_1,3.0,1.41835334112138,367542.52779013116,1.6507246312376866,False
|
| 102 |
+
dose_5-rep_1-t_4,dose_5-rep_1,4.0,1.41835334112138,535033.3697428543,2.1924423140004268,False
|
| 103 |
+
dose_5-rep_1-t_5,dose_5-rep_1,5.0,1.41835334112138,726051.529930286,2.6328853835701116,False
|
| 104 |
+
dose_5-rep_2-t_0,dose_5-rep_2,0.0,1.41835334112138,117055.0,0.0,True
|
| 105 |
+
dose_5-rep_2-t_1,dose_5-rep_2,1.0,1.41835334112138,167060.34358941315,0.5131827498868529,False
|
| 106 |
+
dose_5-rep_2-t_2,dose_5-rep_2,2.0,1.41835334112138,246041.4256362762,1.0717146800456518,False
|
| 107 |
+
dose_5-rep_2-t_3,dose_5-rep_2,3.0,1.41835334112138,367542.52779013116,1.6507246312376866,False
|
| 108 |
+
dose_5-rep_2-t_4,dose_5-rep_2,4.0,1.41835334112138,535033.3697428543,2.1924423140004268,False
|
| 109 |
+
dose_5-rep_2-t_5,dose_5-rep_2,5.0,1.41835334112138,726051.529930286,2.6328853835701116,False
|
| 110 |
+
dose_6-rep_0-t_0,dose_6-rep_0,0.0,2.3112042478354495,117055.0,0.0,True
|
| 111 |
+
dose_6-rep_0-t_1,dose_6-rep_0,1.0,2.3112042478354495,156640.12723312783,0.4202672814724111,False
|
| 112 |
+
dose_6-rep_0-t_2,dose_6-rep_0,2.0,2.3112042478354495,220761.033587925,0.9152989848252058,False
|
| 113 |
+
dose_6-rep_0-t_3,dose_6-rep_0,3.0,2.3112042478354495,325801.3065623647,1.4768058290896102,False
|
| 114 |
+
dose_6-rep_0-t_4,dose_6-rep_0,4.0,2.3112042478354495,483650.1317704568,2.0467772315256103,False
|
| 115 |
+
dose_6-rep_0-t_5,dose_6-rep_0,5.0,2.3112042478354495,680616.3580916729,2.5396552653559166,False
|
| 116 |
+
dose_6-rep_1-t_0,dose_6-rep_1,0.0,2.3112042478354495,117055.0,0.0,True
|
| 117 |
+
dose_6-rep_1-t_1,dose_6-rep_1,1.0,2.3112042478354495,156640.12723312783,0.4202672814724111,False
|
| 118 |
+
dose_6-rep_1-t_2,dose_6-rep_1,2.0,2.3112042478354495,220761.033587925,0.9152989848252058,False
|
| 119 |
+
dose_6-rep_1-t_3,dose_6-rep_1,3.0,2.3112042478354495,325801.3065623647,1.4768058290896102,False
|
| 120 |
+
dose_6-rep_1-t_4,dose_6-rep_1,4.0,2.3112042478354495,483650.1317704568,2.0467772315256103,False
|
| 121 |
+
dose_6-rep_1-t_5,dose_6-rep_1,5.0,2.3112042478354495,680616.3580916729,2.5396552653559166,False
|
| 122 |
+
dose_6-rep_2-t_0,dose_6-rep_2,0.0,2.3112042478354495,117055.0,0.0,True
|
| 123 |
+
dose_6-rep_2-t_1,dose_6-rep_2,1.0,2.3112042478354495,156640.12723312783,0.4202672814724111,False
|
| 124 |
+
dose_6-rep_2-t_2,dose_6-rep_2,2.0,2.3112042478354495,220761.033587925,0.9152989848252058,False
|
| 125 |
+
dose_6-rep_2-t_3,dose_6-rep_2,3.0,2.3112042478354495,325801.3065623647,1.4768058290896102,False
|
| 126 |
+
dose_6-rep_2-t_4,dose_6-rep_2,4.0,2.3112042478354495,483650.1317704568,2.0467772315256103,False
|
| 127 |
+
dose_6-rep_2-t_5,dose_6-rep_2,5.0,2.3112042478354495,680616.3580916729,2.5396552653559166,False
|
| 128 |
+
dose_7-rep_0-t_0,dose_7-rep_0,0.0,3.7661032130325105,117055.0,0.0,True
|
| 129 |
+
dose_7-rep_0-t_1,dose_7-rep_0,1.0,3.7661032130325105,148801.10472623174,0.3461986768823421,False
|
| 130 |
+
dose_7-rep_0-t_2,dose_7-rep_0,2.0,3.7661032130325105,202753.24840351264,0.7925384682803503,False
|
| 131 |
+
dose_7-rep_0-t_3,dose_7-rep_0,3.0,3.7661032130325105,297423.17062527494,1.3453304838789686,False
|
| 132 |
+
dose_7-rep_0-t_4,dose_7-rep_0,4.0,3.7661032130325105,450412.9783225577,1.9440618377944692,False
|
| 133 |
+
dose_7-rep_0-t_5,dose_7-rep_0,5.0,3.7661032130325105,653766.1815845432,2.4815881899955756,False
|
| 134 |
+
dose_7-rep_1-t_0,dose_7-rep_1,0.0,3.7661032130325105,117055.0,0.0,True
|
| 135 |
+
dose_7-rep_1-t_1,dose_7-rep_1,1.0,3.7661032130325105,148801.10472623174,0.3461986768823421,False
|
| 136 |
+
dose_7-rep_1-t_2,dose_7-rep_1,2.0,3.7661032130325105,202753.24840351264,0.7925384682803503,False
|
| 137 |
+
dose_7-rep_1-t_3,dose_7-rep_1,3.0,3.7661032130325105,297423.17062527494,1.3453304838789686,False
|
| 138 |
+
dose_7-rep_1-t_4,dose_7-rep_1,4.0,3.7661032130325105,450412.9783225577,1.9440618377944692,False
|
| 139 |
+
dose_7-rep_1-t_5,dose_7-rep_1,5.0,3.7661032130325105,653766.1815845432,2.4815881899955756,False
|
| 140 |
+
dose_7-rep_2-t_0,dose_7-rep_2,0.0,3.7661032130325105,117055.0,0.0,True
|
| 141 |
+
dose_7-rep_2-t_1,dose_7-rep_2,1.0,3.7661032130325105,148801.10472623174,0.3461986768823421,False
|
| 142 |
+
dose_7-rep_2-t_2,dose_7-rep_2,2.0,3.7661032130325105,202753.24840351264,0.7925384682803503,False
|
| 143 |
+
dose_7-rep_2-t_3,dose_7-rep_2,3.0,3.7661032130325105,297423.17062527494,1.3453304838789686,False
|
| 144 |
+
dose_7-rep_2-t_4,dose_7-rep_2,4.0,3.7661032130325105,450412.9783225577,1.9440618377944692,False
|
| 145 |
+
dose_7-rep_2-t_5,dose_7-rep_2,5.0,3.7661032130325105,653766.1815845432,2.4815881899955756,False
|
| 146 |
+
dose_8-rep_0-t_0,dose_8-rep_0,0.0,6.1368584903291605,117055.0,0.0,True
|
| 147 |
+
dose_8-rep_0-t_1,dose_8-rep_0,1.0,6.1368584903291605,143258.0596617452,0.29142974648746456,False
|
| 148 |
+
dose_8-rep_0-t_2,dose_8-rep_0,2.0,6.1368584903291605,190613.57755750668,0.7034643267976026,False
|
| 149 |
+
dose_8-rep_0-t_3,dose_8-rep_0,3.0,6.1368584903291605,279137.85937086184,1.2537912494702186,False
|
| 150 |
+
dose_8-rep_0-t_4,dose_8-rep_0,4.0,6.1368584903291605,430135.55843049457,1.8776048404415195,False
|
| 151 |
+
dose_8-rep_0-t_5,dose_8-rep_0,5.0,6.1368584903291605,639010.8809450462,2.448653936862557,False
|
| 152 |
+
dose_8-rep_1-t_0,dose_8-rep_1,0.0,6.1368584903291605,117055.0,0.0,True
|
| 153 |
+
dose_8-rep_1-t_1,dose_8-rep_1,1.0,6.1368584903291605,143258.0596617452,0.29142974648746456,False
|
| 154 |
+
dose_8-rep_1-t_2,dose_8-rep_1,2.0,6.1368584903291605,190613.57755750668,0.7034643267976026,False
|
| 155 |
+
dose_8-rep_1-t_3,dose_8-rep_1,3.0,6.1368584903291605,279137.85937086184,1.2537912494702186,False
|
| 156 |
+
dose_8-rep_1-t_4,dose_8-rep_1,4.0,6.1368584903291605,430135.55843049457,1.8776048404415195,False
|
| 157 |
+
dose_8-rep_1-t_5,dose_8-rep_1,5.0,6.1368584903291605,639010.8809450462,2.448653936862557,False
|
| 158 |
+
dose_8-rep_2-t_0,dose_8-rep_2,0.0,6.1368584903291605,117055.0,0.0,True
|
| 159 |
+
dose_8-rep_2-t_1,dose_8-rep_2,1.0,6.1368584903291605,143258.0596617452,0.29142974648746456,False
|
| 160 |
+
dose_8-rep_2-t_2,dose_8-rep_2,2.0,6.1368584903291605,190613.57755750668,0.7034643267976026,False
|
| 161 |
+
dose_8-rep_2-t_3,dose_8-rep_2,3.0,6.1368584903291605,279137.85937086184,1.2537912494702186,False
|
| 162 |
+
dose_8-rep_2-t_4,dose_8-rep_2,4.0,6.1368584903291605,430135.55843049457,1.8776048404415195,False
|
| 163 |
+
dose_8-rep_2-t_5,dose_8-rep_2,5.0,6.1368584903291605,639010.8809450462,2.448653936862557,False
|
| 164 |
+
dose_9-rep_0-t_0,dose_9-rep_0,0.0,10.0,117055.0,0.0,True
|
| 165 |
+
dose_9-rep_0-t_1,dose_9-rep_0,1.0,10.0,139507.74375037773,0.2531586444918018,False
|
| 166 |
+
dose_9-rep_0-t_2,dose_9-rep_0,2.0,10.0,182703.5738878364,0.642318294551051,False
|
| 167 |
+
dose_9-rep_0-t_3,dose_9-rep_0,3.0,10.0,267670.4959774961,1.1932715660229316,False
|
| 168 |
+
dose_9-rep_0-t_4,dose_9-rep_0,4.0,10.0,418045.1524475581,1.8364722136788576,False
|
| 169 |
+
dose_9-rep_0-t_5,dose_9-rep_0,5.0,10.0,631095.7950410473,2.4306724503882338,False
|
| 170 |
+
dose_9-rep_1-t_0,dose_9-rep_1,0.0,10.0,117055.0,0.0,True
|
| 171 |
+
dose_9-rep_1-t_1,dose_9-rep_1,1.0,10.0,139507.74375037773,0.2531586444918018,False
|
| 172 |
+
dose_9-rep_1-t_2,dose_9-rep_1,2.0,10.0,182703.5738878364,0.642318294551051,False
|
| 173 |
+
dose_9-rep_1-t_3,dose_9-rep_1,3.0,10.0,267670.4959774961,1.1932715660229316,False
|
| 174 |
+
dose_9-rep_1-t_4,dose_9-rep_1,4.0,10.0,418045.1524475581,1.8364722136788576,False
|
| 175 |
+
dose_9-rep_1-t_5,dose_9-rep_1,5.0,10.0,631095.7950410473,2.4306724503882338,False
|
| 176 |
+
dose_9-rep_2-t_0,dose_9-rep_2,0.0,10.0,117055.0,0.0,True
|
| 177 |
+
dose_9-rep_2-t_1,dose_9-rep_2,1.0,10.0,139507.74375037773,0.2531586444918018,False
|
| 178 |
+
dose_9-rep_2-t_2,dose_9-rep_2,2.0,10.0,182703.5738878364,0.642318294551051,False
|
| 179 |
+
dose_9-rep_2-t_3,dose_9-rep_2,3.0,10.0,267670.4959774961,1.1932715660229316,False
|
| 180 |
+
dose_9-rep_2-t_4,dose_9-rep_2,4.0,10.0,418045.1524475581,1.8364722136788576,False
|
| 181 |
+
dose_9-rep_2-t_5,dose_9-rep_2,5.0,10.0,631095.7950410473,2.4306724503882338,False
|
data/examples/single-point/dose-response_strain_meta.csv
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
strain_id,dose_params,is_reference,is_spike
|
| 2 |
+
wt,"[10000.0, 1.0]",True,False
|
| 3 |
+
spike,"[1e-09, 0.0]",False,True
|
| 4 |
+
mut_A,"[0.1, 0.0]",False,False
|
| 5 |
+
mut_B,"[1.0, 0.0]",False,False
|
| 6 |
+
mut_C,"[10.0, 0.0]",False,False
|
| 7 |
+
mut_D,"[1.0, 0.5]",False,False
|
| 8 |
+
ctrl_000,"[10000.0, 1.0]",False,False
|
| 9 |
+
ctrl_001,"[10000.0, 1.0]",False,False
|
| 10 |
+
ctrl_002,"[10000.0, 1.0]",False,False
|
| 11 |
+
ctrl_003,"[10000.0, 1.0]",False,False
|
| 12 |
+
ctrl_004,"[10000.0, 1.0]",False,False
|
| 13 |
+
ctrl_005,"[10000.0, 1.0]",False,False
|
| 14 |
+
ctrl_006,"[10000.0, 1.0]",False,False
|
| 15 |
+
ctrl_007,"[10000.0, 1.0]",False,False
|
| 16 |
+
ctrl_008,"[10000.0, 1.0]",False,False
|
| 17 |
+
ctrl_009,"[10000.0, 1.0]",False,False
|
| 18 |
+
str_000,"[np.float64(1.160934072833945), 0.0]",False,False
|
| 19 |
+
str_001,"[np.float64(0.6583176596280784), 0.0]",False,False
|
| 20 |
+
str_002,"[np.float64(1.2878968798670738), 0.0]",False,False
|
| 21 |
+
str_003,"[np.float64(1.046052043589046), 0.0]",False,False
|
| 22 |
+
str_004,"[np.float64(0.1412660218314743), 0.0]",False,False
|
| 23 |
+
str_005,"[np.float64(1.463433527455134), 0.0]",False,False
|
| 24 |
+
str_006,"[np.float64(1.1417095529855295), 0.0]",False,False
|
| 25 |
+
str_007,"[np.float64(1.1790964579154308), 0.0]",False,False
|
| 26 |
+
str_008,"[np.float64(0.1921704490133188), 0.0]",False,False
|
| 27 |
+
str_009,"[np.float64(0.6755789068433506), 0.0]",False,False
|
| 28 |
+
str_010,"[np.float64(0.5561970363488719), 0.0]",False,False
|
| 29 |
+
str_011,"[np.float64(1.3901474832729028), 0.0]",False,False
|
| 30 |
+
str_012,"[np.float64(0.9657976801209969), 0.0]",False,False
|
| 31 |
+
str_013,"[np.float64(1.234142419906245), 0.0]",False,False
|
| 32 |
+
str_014,"[np.float64(0.6651212982409966), 0.0]",False,False
|
| 33 |
+
str_015,"[np.float64(0.34085808267716533), 0.0]",False,False
|
| 34 |
+
str_016,"[np.float64(0.8318771805237521), 0.0]",False,False
|
| 35 |
+
str_017,"[np.float64(0.09572588415626299), 0.0]",False,False
|
| 36 |
+
str_018,"[np.float64(1.241446757988873), 0.0]",False,False
|
| 37 |
+
str_019,"[np.float64(0.9474965986830972), 0.0]",False,False
|
| 38 |
+
str_020,"[np.float64(1.1371316101280606), 0.0]",False,False
|
| 39 |
+
str_021,"[np.float64(0.5317889521948025), 0.0]",False,False
|
| 40 |
+
str_022,"[np.float64(1.4560470365923548), 0.0]",False,False
|
| 41 |
+
str_023,"[np.float64(1.3396816819832966), 0.0]",False,False
|
| 42 |
+
str_024,"[np.float64(1.1675752456106427), 0.0]",False,False
|
| 43 |
+
str_025,"[np.float64(0.29195806177795136), 0.0]",False,False
|
| 44 |
+
str_026,"[np.float64(0.7000815055905513), 0.0]",False,False
|
| 45 |
+
str_027,"[np.float64(0.06570564868084317), 0.0]",False,False
|
| 46 |
+
str_028,"[np.float64(0.23143423810132174), 0.0]",False,False
|
| 47 |
+
str_029,"[np.float64(1.024573429863682), 0.0]",False,False
|
| 48 |
+
str_030,"[np.float64(1.1171432338617258), 0.0]",False,False
|
| 49 |
+
str_031,"[np.float64(1.451264598651315), 0.0]",False,False
|
| 50 |
+
str_032,"[np.float64(0.4887380372072279), 0.0]",False,False
|
| 51 |
+
str_033,"[np.float64(0.5556895590523033), 0.0]",False,False
|
| 52 |
+
str_034,"[np.float64(0.7043337169137118), 0.0]",False,False
|
| 53 |
+
str_035,"[np.float64(0.28420703862642854), 0.0]",False,False
|
| 54 |
+
str_036,"[np.float64(0.19488225800320746), 0.0]",False,False
|
| 55 |
+
str_037,"[np.float64(0.7135573893389007), 0.0]",False,False
|
| 56 |
+
str_038,"[np.float64(0.34036402357632617), 0.0]",False,False
|
| 57 |
+
str_039,"[np.float64(1.0047209920237656), 0.0]",False,False
|
| 58 |
+
str_040,"[np.float64(0.6557278783084961), 0.0]",False,False
|
| 59 |
+
str_041,"[np.float64(1.249017294086756), 0.0]",False,False
|
| 60 |
+
str_042,"[np.float64(1.0503976530033736), 0.0]",False,False
|
| 61 |
+
str_043,"[np.float64(0.4685499620730616), 0.0]",False,False
|
| 62 |
+
str_044,"[np.float64(1.2483897020928016), 0.0]",False,False
|
| 63 |
+
str_045,"[np.float64(1.2071465362452027), 0.0]",False,False
|
| 64 |
+
str_046,"[np.float64(0.5812175685452616), 0.0]",False,False
|
| 65 |
+
str_047,"[np.float64(0.43249215589536616), 0.0]",False,False
|
| 66 |
+
str_048,"[np.float64(1.0237432559624633), 0.0]",False,False
|
| 67 |
+
str_049,"[np.float64(0.2096287254139647), 0.0]",False,False
|
| 68 |
+
str_050,"[np.float64(0.2998623037126625), 0.0]",False,False
|
| 69 |
+
str_051,"[np.float64(0.011043404626508269), 0.0]",False,False
|
| 70 |
+
str_052,"[np.float64(1.1803865662532076), 0.0]",False,False
|
| 71 |
+
str_053,"[np.float64(0.9972762848880482), 0.0]",False,False
|
| 72 |
+
str_054,"[np.float64(1.0577480679395026), 0.0]",False,False
|
| 73 |
+
str_055,"[np.float64(1.1710935465329517), 0.0]",False,False
|
| 74 |
+
str_056,"[np.float64(0.6883736633075099), 0.0]",False,False
|
| 75 |
+
str_057,"[np.float64(0.8531117939293407), 0.0]",False,False
|
| 76 |
+
str_058,"[np.float64(0.20969549719148617), 0.0]",False,False
|
| 77 |
+
str_059,"[np.float64(0.17179511030396016), 0.0]",False,False
|
| 78 |
+
str_060,"[np.float64(1.0026044426857075), 0.0]",False,False
|
| 79 |
+
str_061,"[np.float64(0.7066443092146988), 0.0]",False,False
|
| 80 |
+
str_062,"[np.float64(0.8478541597217832), 0.0]",False,False
|
| 81 |
+
str_063,"[np.float64(1.1474982861240384), 0.0]",False,False
|
| 82 |
+
str_064,"[np.float64(0.9520774800008862), 0.0]",False,False
|
| 83 |
+
str_065,"[np.float64(0.8303691009869938), 0.0]",False,False
|
| 84 |
+
str_066,"[np.float64(0.8388107411181203), 0.0]",False,False
|
| 85 |
+
str_067,"[np.float64(0.4559251470939183), 0.0]",False,False
|
| 86 |
+
str_068,"[np.float64(0.04622675185190911), 0.0]",False,False
|
| 87 |
+
str_069,"[np.float64(0.6550760838485435), 0.0]",False,False
|
| 88 |
+
str_070,"[np.float64(0.3218770092292938), 0.0]",False,False
|
| 89 |
+
str_071,"[np.float64(0.6127929655869542), 0.0]",False,False
|
| 90 |
+
str_072,"[np.float64(1.2801046099022493), 0.0]",False,False
|
| 91 |
+
str_073,"[np.float64(0.3509092287980111), 0.0]",False,False
|
| 92 |
+
str_074,"[np.float64(0.08745411253359903), 0.0]",False,False
|
| 93 |
+
str_075,"[np.float64(0.4220758380329948), 0.0]",False,False
|
| 94 |
+
str_076,"[np.float64(0.4403906366500254), 0.0]",False,False
|
| 95 |
+
str_077,"[np.float64(0.9928747720903426), 0.0]",False,False
|
| 96 |
+
str_078,"[np.float64(0.8355482285119176), 0.0]",False,False
|
| 97 |
+
str_079,"[np.float64(1.1758473136596201), 0.0]",False,False
|
| 98 |
+
str_080,"[np.float64(0.9964703104910813), 0.0]",False,False
|
| 99 |
+
str_081,"[np.float64(0.6095802921601058), 0.0]",False,False
|
| 100 |
+
str_082,"[np.float64(1.221030576999052), 0.0]",False,False
|
| 101 |
+
str_083,"[np.float64(0.25045937986155586), 0.0]",False,False
|
| 102 |
+
str_084,"[np.float64(0.034068109700790716), 0.0]",False,False
|
| 103 |
+
str_085,"[np.float64(0.13507179116346263), 0.0]",False,False
|
| 104 |
+
str_086,"[np.float64(1.0835390258946753), 0.0]",False,False
|
| 105 |
+
str_087,"[np.float64(0.6928158453770811), 0.0]",False,False
|
| 106 |
+
str_088,"[np.float64(0.2419076685504027), 0.0]",False,False
|
| 107 |
+
str_089,"[np.float64(0.7515671626550453), 0.0]",False,False
|
| 108 |
+
str_090,"[np.float64(0.22846815406975263), 0.0]",False,False
|
| 109 |
+
str_091,"[np.float64(1.044480562616604), 0.0]",False,False
|
| 110 |
+
str_092,"[np.float64(0.669234413361046), 0.0]",False,False
|
| 111 |
+
str_093,"[np.float64(0.5715318391447237), 0.0]",False,False
|
| 112 |
+
str_094,"[np.float64(0.4522681337218148), 0.0]",False,False
|
| 113 |
+
str_095,"[np.float64(0.9454238896783327), 0.0]",False,False
|
| 114 |
+
str_096,"[np.float64(0.5427189158300856), 0.0]",False,False
|
| 115 |
+
str_097,"[np.float64(0.1314748789741515), 0.0]",False,False
|
| 116 |
+
str_098,"[np.float64(0.17700885318077297), 0.0]",False,False
|
| 117 |
+
str_099,"[np.float64(1.4428464968242718), 0.0]",False,False
|
data/examples/single-point/test_count.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/examples/single-point/test_sample_meta.csv
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
sample_id,replicate,timepoint,dose,growth,generations,is_t0
|
| 2 |
+
dose_0-rep_0-t_0,dose_0-rep_0,0.0,1.0,117055.0,0.0,True
|
| 3 |
+
dose_0-rep_0-t_1,dose_0-rep_0,1.0,1.0,235530.43107290982,1.008726910963631,False
|
| 4 |
+
dose_0-rep_0-t_2,dose_0-rep_0,2.0,1.0,457470.31913837086,1.966491583356558,False
|
| 5 |
+
dose_0-rep_0-t_3,dose_0-rep_0,3.0,1.0,745400.9751793981,2.6708301460588992,False
|
| 6 |
+
dose_0-rep_0-t_4,dose_0-rep_0,4.0,1.0,972048.1257198368,3.053841182431035,False
|
| 7 |
+
dose_0-rep_0-t_5,dose_0-rep_0,5.0,1.0,1088034.9223100767,3.216466397510134,False
|
| 8 |
+
dose_0-rep_1-t_0,dose_0-rep_1,0.0,1.0,117055.0,0.0,True
|
| 9 |
+
dose_0-rep_1-t_1,dose_0-rep_1,1.0,1.0,235530.43107290982,1.008726910963631,False
|
| 10 |
+
dose_0-rep_1-t_2,dose_0-rep_1,2.0,1.0,457470.31913837086,1.966491583356558,False
|
| 11 |
+
dose_0-rep_1-t_3,dose_0-rep_1,3.0,1.0,745400.9751793981,2.6708301460588992,False
|
| 12 |
+
dose_0-rep_1-t_4,dose_0-rep_1,4.0,1.0,972048.1257198368,3.053841182431035,False
|
| 13 |
+
dose_0-rep_1-t_5,dose_0-rep_1,5.0,1.0,1088034.9223100767,3.216466397510134,False
|
| 14 |
+
dose_0-rep_2-t_0,dose_0-rep_2,0.0,1.0,117055.0,0.0,True
|
| 15 |
+
dose_0-rep_2-t_1,dose_0-rep_2,1.0,1.0,235530.43107290982,1.008726910963631,False
|
| 16 |
+
dose_0-rep_2-t_2,dose_0-rep_2,2.0,1.0,457470.31913837086,1.966491583356558,False
|
| 17 |
+
dose_0-rep_2-t_3,dose_0-rep_2,3.0,1.0,745400.9751793981,2.6708301460588992,False
|
| 18 |
+
dose_0-rep_2-t_4,dose_0-rep_2,4.0,1.0,972048.1257198368,3.053841182431035,False
|
| 19 |
+
dose_0-rep_2-t_5,dose_0-rep_2,5.0,1.0,1088034.9223100767,3.216466397510134,False
|
data/examples/single-point/test_strain_meta.csv
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
strain_id,true_fitness,is_reference,is_spike
|
| 2 |
+
wt,1.0,True,False
|
| 3 |
+
spike,0.0,False,True
|
| 4 |
+
mut_A,1.5,False,False
|
| 5 |
+
mut_B,0.5,False,False
|
| 6 |
+
mut_C,0.9,False,False
|
| 7 |
+
mut_D,1.1,False,False
|
| 8 |
+
ctrl_000,1.0,False,False
|
| 9 |
+
ctrl_001,1.0,False,False
|
| 10 |
+
ctrl_002,1.0,False,False
|
| 11 |
+
ctrl_003,1.0,False,False
|
| 12 |
+
ctrl_004,1.0,False,False
|
| 13 |
+
ctrl_005,1.0,False,False
|
| 14 |
+
ctrl_006,1.0,False,False
|
| 15 |
+
ctrl_007,1.0,False,False
|
| 16 |
+
ctrl_008,1.0,False,False
|
| 17 |
+
ctrl_009,1.0,False,False
|
| 18 |
+
str_000,1.160934072833945,False,False
|
| 19 |
+
str_001,0.6583176596280784,False,False
|
| 20 |
+
str_002,1.2878968798670738,False,False
|
| 21 |
+
str_003,1.046052043589046,False,False
|
| 22 |
+
str_004,0.1412660218314743,False,False
|
| 23 |
+
str_005,1.463433527455134,False,False
|
| 24 |
+
str_006,1.1417095529855295,False,False
|
| 25 |
+
str_007,1.1790964579154308,False,False
|
| 26 |
+
str_008,0.1921704490133188,False,False
|
| 27 |
+
str_009,0.6755789068433506,False,False
|
| 28 |
+
str_010,0.5561970363488719,False,False
|
| 29 |
+
str_011,1.3901474832729028,False,False
|
| 30 |
+
str_012,0.9657976801209969,False,False
|
| 31 |
+
str_013,1.234142419906245,False,False
|
| 32 |
+
str_014,0.6651212982409966,False,False
|
| 33 |
+
str_015,0.34085808267716533,False,False
|
| 34 |
+
str_016,0.8318771805237521,False,False
|
| 35 |
+
str_017,0.09572588415626299,False,False
|
| 36 |
+
str_018,1.241446757988873,False,False
|
| 37 |
+
str_019,0.9474965986830972,False,False
|
| 38 |
+
str_020,1.1371316101280606,False,False
|
| 39 |
+
str_021,0.5317889521948025,False,False
|
| 40 |
+
str_022,1.4560470365923548,False,False
|
| 41 |
+
str_023,1.3396816819832966,False,False
|
| 42 |
+
str_024,1.1675752456106427,False,False
|
| 43 |
+
str_025,0.29195806177795136,False,False
|
| 44 |
+
str_026,0.7000815055905513,False,False
|
| 45 |
+
str_027,0.06570564868084317,False,False
|
| 46 |
+
str_028,0.23143423810132174,False,False
|
| 47 |
+
str_029,1.024573429863682,False,False
|
| 48 |
+
str_030,1.1171432338617258,False,False
|
| 49 |
+
str_031,1.451264598651315,False,False
|
| 50 |
+
str_032,0.4887380372072279,False,False
|
| 51 |
+
str_033,0.5556895590523033,False,False
|
| 52 |
+
str_034,0.7043337169137118,False,False
|
| 53 |
+
str_035,0.28420703862642854,False,False
|
| 54 |
+
str_036,0.19488225800320746,False,False
|
| 55 |
+
str_037,0.7135573893389007,False,False
|
| 56 |
+
str_038,0.34036402357632617,False,False
|
| 57 |
+
str_039,1.0047209920237656,False,False
|
| 58 |
+
str_040,0.6557278783084961,False,False
|
| 59 |
+
str_041,1.249017294086756,False,False
|
| 60 |
+
str_042,1.0503976530033736,False,False
|
| 61 |
+
str_043,0.4685499620730616,False,False
|
| 62 |
+
str_044,1.2483897020928016,False,False
|
| 63 |
+
str_045,1.2071465362452027,False,False
|
| 64 |
+
str_046,0.5812175685452616,False,False
|
| 65 |
+
str_047,0.43249215589536616,False,False
|
| 66 |
+
str_048,1.0237432559624633,False,False
|
| 67 |
+
str_049,0.2096287254139647,False,False
|
| 68 |
+
str_050,0.2998623037126625,False,False
|
| 69 |
+
str_051,0.011043404626508269,False,False
|
| 70 |
+
str_052,1.1803865662532076,False,False
|
| 71 |
+
str_053,0.9972762848880482,False,False
|
| 72 |
+
str_054,1.0577480679395026,False,False
|
| 73 |
+
str_055,1.1710935465329517,False,False
|
| 74 |
+
str_056,0.6883736633075099,False,False
|
| 75 |
+
str_057,0.8531117939293407,False,False
|
| 76 |
+
str_058,0.20969549719148617,False,False
|
| 77 |
+
str_059,0.17179511030396016,False,False
|
| 78 |
+
str_060,1.0026044426857075,False,False
|
| 79 |
+
str_061,0.7066443092146988,False,False
|
| 80 |
+
str_062,0.8478541597217832,False,False
|
| 81 |
+
str_063,1.1474982861240384,False,False
|
| 82 |
+
str_064,0.9520774800008862,False,False
|
| 83 |
+
str_065,0.8303691009869938,False,False
|
| 84 |
+
str_066,0.8388107411181203,False,False
|
| 85 |
+
str_067,0.4559251470939183,False,False
|
| 86 |
+
str_068,0.04622675185190911,False,False
|
| 87 |
+
str_069,0.6550760838485435,False,False
|
| 88 |
+
str_070,0.3218770092292938,False,False
|
| 89 |
+
str_071,0.6127929655869542,False,False
|
| 90 |
+
str_072,1.2801046099022493,False,False
|
| 91 |
+
str_073,0.3509092287980111,False,False
|
| 92 |
+
str_074,0.08745411253359903,False,False
|
| 93 |
+
str_075,0.4220758380329948,False,False
|
| 94 |
+
str_076,0.4403906366500254,False,False
|
| 95 |
+
str_077,0.9928747720903426,False,False
|
| 96 |
+
str_078,0.8355482285119176,False,False
|
| 97 |
+
str_079,1.1758473136596201,False,False
|
| 98 |
+
str_080,0.9964703104910813,False,False
|
| 99 |
+
str_081,0.6095802921601058,False,False
|
| 100 |
+
str_082,1.221030576999052,False,False
|
| 101 |
+
str_083,0.25045937986155586,False,False
|
| 102 |
+
str_084,0.034068109700790716,False,False
|
| 103 |
+
str_085,0.13507179116346263,False,False
|
| 104 |
+
str_086,1.0835390258946753,False,False
|
| 105 |
+
str_087,0.6928158453770811,False,False
|
| 106 |
+
str_088,0.2419076685504027,False,False
|
| 107 |
+
str_089,0.7515671626550453,False,False
|
| 108 |
+
str_090,0.22846815406975263,False,False
|
| 109 |
+
str_091,1.044480562616604,False,False
|
| 110 |
+
str_092,0.669234413361046,False,False
|
| 111 |
+
str_093,0.5715318391447237,False,False
|
| 112 |
+
str_094,0.4522681337218148,False,False
|
| 113 |
+
str_095,0.9454238896783327,False,False
|
| 114 |
+
str_096,0.5427189158300856,False,False
|
| 115 |
+
str_097,0.1314748789741515,False,False
|
| 116 |
+
str_098,0.17700885318077297,False,False
|
| 117 |
+
str_099,1.4428464968242718,False,False
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
anndata
|
| 2 |
+
carabiner-tools[pd,mpl]>=0.0.5.post3
|
| 3 |
+
gradio==5.50.0
|
| 4 |
+
nemony
|
| 5 |
+
numpy
|
| 6 |
+
scipy
|
| 7 |
+
scikit-learn
|
| 8 |
+
statsmodels
|