Skip to content

Commit d1882b6

Browse files
committed
Merge branch 'develop' of github.com:HelikarLab/COMO into develop
2 parents 9bb415d + a36d05d commit d1882b6

15 files changed

Lines changed: 1899 additions & 681 deletions

.github/workflows/continuous_integration.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
uses: actions/checkout@v4
1515

1616
- name: Install uv
17-
uses: astral-sh/setup-uv@v3
17+
uses: astral-sh/setup-uv@v4
1818

1919
- name: Create Virtual Environment
2020
run: uv venv
@@ -26,17 +26,17 @@ jobs:
2626
run: uv run jupyter nbconvert --clear-output --inplace "main/COMO.ipynb"
2727

2828
- name: Format Python Imports
29-
uses: astral-sh/ruff-action@v1
29+
uses: astral-sh/ruff-action@v2
3030
with:
3131
args: "check --fix --select I"
3232

3333
- name: Format code
34-
uses: astral-sh/ruff-action@v1
34+
uses: astral-sh/ruff-action@v2
3535
with:
3636
args: "format"
3737

3838
- name: Format Notebook
39-
uses: astral-sh/ruff-action@v1
39+
uses: astral-sh/ruff-action@v2
4040
with:
4141
args: "format main/COMO.ipynb"
4242

@@ -54,7 +54,7 @@ jobs:
5454
uses: actions/checkout@v4
5555

5656
- name: Check Lint
57-
uses: astral-sh/ruff-action@v1
57+
uses: astral-sh/ruff-action@v2
5858
with:
5959
args: "check --no-fix --verbose"
6060

.pre-commit-config.yaml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
# See https://pre-commit.com for more information
2-
# See https://pre-commit.com/hooks.html for more hooks
31
repos:
4-
- repo: https://github.com/opensource-nepal/commitlint
5-
rev: v1.2.0
2+
- repo: https://github.com/commitizen-tools/commitizen
3+
rev: master
64
hooks:
7-
- id: commitlint
8-
name: Commit Lint
5+
- id: commitizen
6+
stages: [ commit-msg ]

main/COMO.ipynb

Lines changed: 124 additions & 197 deletions
Large diffs are not rendered by default.

main/como/merge_xomics.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from como import proteomics_gen, return_placeholder_data
1818
from como.combine_distributions import _combine_zscores
19-
from como.custom_types import RNASeqPreparationMethod
19+
from como.custom_types import RNAPrepMethod
2020
from como.project import Config
2121
from como.utils import split_gene_expression_data
2222

@@ -93,7 +93,7 @@ def __post_init__(self):
9393
raise ValueError("Adjust method must be either 'progressive', 'regressive', 'flat', or 'custom'")
9494

9595

96-
def _load_rnaseq_tests(filename, context_name, prep_method: RNASeqPreparationMethod) -> tuple[str, pd.DataFrame]:
96+
def _load_rnaseq_tests(filename, context_name, prep_method: RNAPrepMethod) -> tuple[str, pd.DataFrame]:
9797
"""Load rnaseq results.
9898
9999
Returns a dictionary of test (context, context, cell, etc ) names and rnaseq expression data
@@ -112,11 +112,11 @@ def load_dummy_dict():
112112
raise FileNotFoundError(f"Error: Config file not found at {inquiry_full_path}")
113113

114114
match prep_method:
115-
case RNASeqPreparationMethod.TOTAL:
115+
case RNAPrepMethod.TOTAL:
116116
filename = f"rnaseq_total_{context_name}.csv"
117-
case RNASeqPreparationMethod.MRNA:
117+
case RNAPrepMethod.MRNA:
118118
filename = f"rnaseq_mrna_{context_name}.csv"
119-
case RNASeqPreparationMethod.SCRNA:
119+
case RNAPrepMethod.SCRNA:
120120
filename = f"rnaseq_scrna_{context_name}.csv"
121121
case _:
122122
raise ValueError(
@@ -344,15 +344,9 @@ async def _merge_xomics(
344344
config = Config()
345345
logger.info(f"Merging data for {context_name}")
346346
# load data for each source if it exists. IF not load an empty dummy dataset
347-
trnaseq = _load_rnaseq_tests(
348-
filename=trnaseq_file, context_name=context_name, prep_method=RNASeqPreparationMethod.TOTAL
349-
)
350-
mrnaseq = _load_rnaseq_tests(
351-
filename=mrnaseq_file, context_name=context_name, prep_method=RNASeqPreparationMethod.MRNA
352-
)
353-
scrnaseq = _load_rnaseq_tests(
354-
filename=scrnaseq_file, context_name=context_name, prep_method=RNASeqPreparationMethod.SCRNA
355-
)
347+
trnaseq = _load_rnaseq_tests(filename=trnaseq_file, context_name=context_name, prep_method=RNAPrepMethod.TOTAL)
348+
mrnaseq = _load_rnaseq_tests(filename=mrnaseq_file, context_name=context_name, prep_method=RNAPrepMethod.MRNA)
349+
scrnaseq = _load_rnaseq_tests(filename=scrnaseq_file, context_name=context_name, prep_method=RNAPrepMethod.SCRNA)
356350
proteomics = proteomics_gen.load_proteomics_tests(filename=proteomics_file, context_name=context_name)
357351

358352
expression_list = []

main/como/rnaseq.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@
2727
from scipy.signal import find_peaks
2828
from sklearn.neighbors import KernelDensity
2929

30-
from como.custom_types import RNASeqPreparationMethod
3130
from como.migrations import gene_info_migrations
32-
from como.project import Config
31+
from como.types import RNAPrepMethod
3332
from como.utils import convert_gene_data
3433

3534

@@ -525,20 +524,17 @@ def calculate_z_score(metrics: NamedMetrics) -> NamedMetrics:
525524

526525
def cpm_filter(
527526
*,
528-
context_name: str,
529527
metrics: NamedMetrics,
530528
filtering_options: _FilteringOptions,
531-
prep: RNASeqPreparationMethod,
529+
output_csv_filepath: Path,
532530
) -> NamedMetrics:
533531
"""Apply Counts Per Million (CPM) filtering to the count matrix for a given sample."""
534-
config = Config()
535532
n_exp = filtering_options.replicate_ratio
536533
n_top = filtering_options.high_replicate_ratio
537534
cut_off = filtering_options.cut_off
538535

539-
sample: str
540536
metric: _StudyMetrics
541-
for sample, metric in metrics.items():
537+
for metric in metrics.values():
542538
counts: pd.DataFrame = metric.count_matrix
543539
entrez_ids: list[str] = metric.entrez_gene_ids
544540
library_size: pd.DataFrame = counts.sum(axis=1)
@@ -548,12 +544,11 @@ def cpm_filter(
548544
# thus, (0 / 1) * 1_000_000 = 0
549545
library_size[library_size == 0] = 1
550546

551-
output_filepath = config.result_dir / context_name / prep.value / f"CPM_Matrix_{prep.value}_{sample}.csv"
552-
output_filepath.parent.mkdir(parents=True, exist_ok=True)
547+
output_csv_filepath.parent.mkdir(parents=True, exist_ok=True)
553548
counts_per_million: pd.DataFrame = (counts / library_size) * 1_000_000
554549
counts_per_million.insert(0, "entrez_gene_ids", pd.Series(entrez_ids))
555-
logger.debug(f"Writing CPM matrix to {output_filepath}")
556-
counts_per_million.to_csv(output_filepath, index=False)
550+
logger.debug(f"Writing CPM matrix to {output_csv_filepath}")
551+
counts_per_million.to_csv(output_csv_filepath, index=False)
557552

558553
# TODO: Counts per million is adding ~61,500 columns (equal to the number of genes) for some reason.
559554
# Most likely due to multiplying by 1_000_000, not exactly sure why
@@ -656,24 +651,31 @@ def zfpkm_filter(*, metrics: NamedMetrics, filtering_options: _FilteringOptions,
656651

657652
def filter_counts(
658653
*,
659-
context_name: str,
660654
metrics: NamedMetrics,
661655
technique: FilteringTechnique,
662656
filtering_options: _FilteringOptions,
663-
prep: RNASeqPreparationMethod,
657+
cpm_output_filepath: Path | None = None,
664658
) -> NamedMetrics:
665659
"""Filter the count matrix based on the specified technique."""
666660
match technique:
667661
case FilteringTechnique.cpm:
662+
if cpm_output_filepath is None:
663+
raise ValueError("CPM output filepath must be provided")
668664
return cpm_filter(
669-
context_name=context_name, metrics=metrics, filtering_options=filtering_options, prep=prep
665+
metrics=metrics,
666+
filtering_options=filtering_options,
667+
output_csv_filepath=cpm_output_filepath,
670668
)
669+
671670
case FilteringTechnique.tpm:
672671
return tpm_quantile_filter(metrics=metrics, filtering_options=filtering_options)
672+
673673
case FilteringTechnique.zfpkm:
674674
return zfpkm_filter(metrics=metrics, filtering_options=filtering_options, calcualte_fpkm=True)
675+
675676
case FilteringTechnique.umi:
676677
return zfpkm_filter(metrics=metrics, filtering_options=filtering_options, calcualte_fpkm=False)
678+
677679
case _:
678680
raise ValueError(f"Technique must be one of {FilteringTechnique}")
679681

@@ -684,7 +686,7 @@ async def save_rnaseq_tests(
684686
config_filepath: Path,
685687
gene_info_filepath: Path,
686688
output_filepath: Path,
687-
prep: RNASeqPreparationMethod,
689+
prep: RNAPrepMethod,
688690
taxon_id: Taxon,
689691
replicate_ratio: float,
690692
batch_ratio: float,
@@ -702,7 +704,7 @@ async def save_rnaseq_tests(
702704
high_batch_ratio=high_batch_ratio,
703705
)
704706

705-
if prep == RNASeqPreparationMethod.SCRNA:
707+
if prep == RNAPrepMethod.SCRNA:
706708
technique = FilteringTechnique.umi
707709
logger.warning(
708710
"Single cell filtration does not normalize and assumes "
@@ -721,11 +723,9 @@ async def save_rnaseq_tests(
721723
entrez_gene_ids = read_counts_results.entrez_gene_ids
722724

723725
metrics = filter_counts(
724-
context_name=context_name,
725726
metrics=metrics,
726727
technique=technique,
727728
filtering_options=filtering_options,
728-
prep=prep,
729729
)
730730

731731
expressed_genes: list[str] = []
@@ -758,6 +758,7 @@ async def save_rnaseq_tests(
758758

759759
boolean_matrix.to_csv(output_filepath, index=False)
760760
logger.info(
761-
f"{context_name} - Found {expressed_count} expressed and {high_confidence_count} confidently expressed genes"
761+
f"{context_name} - Found {expressed_count} expressed genes, "
762+
f"{high_confidence_count} of which are confidently expressed"
762763
)
763764
logger.success(f"Wrote boolean matrix to {output_filepath}")

main/como/rnaseq_gen.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from loguru import logger
1010

1111
from como import Config
12-
from como.custom_types import RNASeqPreparationMethod
12+
from como.custom_types import RNAPrepMethod
1313
from como.rnaseq import FilteringTechnique, save_rnaseq_tests
1414

1515

@@ -22,11 +22,11 @@ class _Arguments:
2222
high_batch_ratio: float
2323
filtering_technique: FilteringTechnique
2424
minimum_cutoff: int | str
25-
library_prep: RNASeqPreparationMethod
25+
library_prep: RNAPrepMethod
2626
taxon: Taxon
2727

2828
def __post_init__(self):
29-
self.library_prep = RNASeqPreparationMethod.from_string(str(self.library_prep))
29+
self.library_prep = RNAPrepMethod.from_string(str(self.library_prep))
3030
self.filtering_technique = FilteringTechnique.from_string(str(self.filtering_technique))
3131

3232
if self.minimum_cutoff is None:
@@ -46,7 +46,7 @@ async def _handle_context_batch(
4646
batch_ratio_high: float,
4747
technique: FilteringTechnique,
4848
cut_off: int | float | str,
49-
prep: RNASeqPreparationMethod,
49+
prep: RNAPrepMethod,
5050
taxon: Taxon,
5151
) -> None:
5252
"""Iterate through each context type and create rnaseq expression file.
@@ -81,9 +81,9 @@ async def _handle_context_batch(
8181
rnaseq_input_filepath = (
8282
config.data_dir / "data_matrices" / context_name / f"gene_counts_matrix_{prep.value}_{context_name}"
8383
)
84-
if prep == RNASeqPreparationMethod.SCRNA:
84+
if prep == RNAPrepMethod.SCRNA:
8585
rnaseq_input_filepath = rnaseq_input_filepath.with_suffix(".h5ad")
86-
elif prep in {RNASeqPreparationMethod.TOTAL, RNASeqPreparationMethod.MRNA}:
86+
elif prep in {RNAPrepMethod.TOTAL, RNAPrepMethod.MRNA}:
8787
rnaseq_input_filepath = rnaseq_input_filepath.with_suffix(".csv")
8888

8989
if not rnaseq_input_filepath.exists():
@@ -117,7 +117,7 @@ async def _handle_context_batch(
117117
async def rnaseq_gen(
118118
# config_filepath: Path,
119119
config_filename: str,
120-
prep: RNASeqPreparationMethod,
120+
prep: RNAPrepMethod,
121121
taxon_id: int | str | Taxon,
122122
replicate_ratio: float = 0.5,
123123
high_replicate_ratio: float = 1.0,

0 commit comments

Comments
 (0)