Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
03dfc79
chore: bump zFPKM version requirement
JoshLoecker Mar 6, 2026
1e2e14f
chore: allow ruff to fix imports and `__all__` sections
JoshLoecker Mar 6, 2026
a6b25e9
chore: bump bioservices requirement
JoshLoecker Mar 6, 2026
027f97a
chore: remove the `log_and_raise_error` helper function for better vi…
JoshLoecker Mar 6, 2026
fa75fc6
chore: remove the internal `log_and_raise_error` helper function for …
JoshLoecker Mar 6, 2026
f59e21a
feat: add genomic conversion pipelines directly into COMO using `bios…
JoshLoecker Mar 6, 2026
3911880
feat: add genomic conversion pipelines directly into COMO using `bios…
JoshLoecker Mar 6, 2026
46f30cd
feat: add genomic conversion pipelines directly into COMO using `bios…
JoshLoecker Mar 6, 2026
f2b3277
feat: add genomic conversion pipelines directly into COMO using `bios…
JoshLoecker Mar 6, 2026
d4e7ea8
feat: extract gene-info building as a pipeline component
JoshLoecker Mar 6, 2026
b75e126
chore: add types for ModelBuildSettings
JoshLoecker Mar 6, 2026
e06f640
feat: add TPM processing from Salmon quantification
JoshLoecker Mar 6, 2026
8c18566
feat: refactor filtering and normalization
JoshLoecker Mar 6, 2026
0f66f12
feat: simplify merging logic
JoshLoecker Mar 6, 2026
85434fd
fix: z-score combination logic
JoshLoecker Mar 6, 2026
2db1fc4
refactor: remove async/await and simplify I/O operations
JoshLoecker Mar 6, 2026
5a99d13
refactor: inline setting boundary reaction conditions
JoshLoecker Mar 6, 2026
b9c773e
refactor: update `_map_expression_to_reaction` signature
JoshLoecker Mar 6, 2026
41d1b56
refactor: add and update types for model build functions
JoshLoecker Mar 6, 2026
4b28e85
fix: correct iMAT implementation with Troppo
JoshLoecker Mar 6, 2026
78f62f8
fix: update boundary reaction collection logic
JoshLoecker Mar 6, 2026
bf30d2d
feat: add `close_unlisted_exchanges` to forcibly set bounds to 0 for …
JoshLoecker Mar 6, 2026
b92b555
refactor: streamline GIMME model reconstruction and expression handling
JoshLoecker Mar 6, 2026
46b89aa
refactor: improve context-specific model creation logic
JoshLoecker Mar 6, 2026
f2d7199
chore: add type hints for reconstructing with tINIT
JoshLoecker Mar 6, 2026
98a5436
chore: do not use match case; reduces indentation
JoshLoecker Mar 6, 2026
b83842c
perf: pass in cobra.Model object to prevent reading multiple times
JoshLoecker Mar 6, 2026
a419bce
refactor: enhance reaction expression mapping and logging for missing…
JoshLoecker Mar 6, 2026
3a8f131
refactor: streamline reaction expression handling in model creation
JoshLoecker Mar 6, 2026
4cab288
refactor: improve reaction index handling and expression vector initi…
JoshLoecker Mar 6, 2026
e4b90b5
refactor: update reaction subsystem assignment and optimize flux outp…
JoshLoecker Mar 6, 2026
2f6e09e
refactor: simplify DataFrame creation by replacing async file read wi…
JoshLoecker Mar 6, 2026
d224639
refactor: update parameter names for clarity and improve docstring fo…
JoshLoecker Mar 6, 2026
e1b2e79
refactor: improve error handling and streamline file path assignments…
JoshLoecker Mar 6, 2026
f7de63b
refactor: enhance model building parameters for clarity and consistency
JoshLoecker Mar 6, 2026
d178491
refactor: streamline context model creation and improve logging output
JoshLoecker Mar 6, 2026
cae84ea
chore: use proper NumPy types for better compatibility
JoshLoecker Mar 6, 2026
53b1830
chore: use `mod.get_remaining_identifiers` in replacement of `mod.con…
JoshLoecker Mar 6, 2026
b661349
chore: update built-in boundary reaction bounds to match expected format
JoshLoecker Mar 6, 2026
2628568
chore: ruff formatting
JoshLoecker Mar 6, 2026
cd61f79
chore: update identifier pipeline tests
JoshLoecker Mar 6, 2026
54b4bc2
Merge branch 'develop' into refactor-pipelines
JoshLoecker Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 90 additions & 66 deletions main/como/combine_distributions.py

Large diffs are not rendered by default.

772 changes: 453 additions & 319 deletions main/como/create_context_specific_model.py

Large diffs are not rendered by default.

122 changes: 107 additions & 15 deletions main/como/data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
from dataclasses import dataclass, field, fields
from enum import Enum
from pathlib import Path
from typing import ClassVar, NamedTuple
from typing import ClassVar, NamedTuple, NotRequired, TypedDict

import cobra
import numpy as np
import numpy.typing as npt
import pandas as pd
from loguru import logger

Expand Down Expand Up @@ -78,11 +80,6 @@ class SourceTypes(str, Enum):
proteomics = "proteomics"


class PeakIdentificationParameters(NamedTuple):
height: float = 0.02
distance: float = 1.0


class CobraCompartments:
"""Convert from compartment "long-hand" to "short-hand".

Expand Down Expand Up @@ -135,7 +132,9 @@ class CobraCompartments:
"s": ["eyespot", "eyespot apparatus", "stigma"],
}

_REVERSE_LOOKUP: ClassVar[dict[str, list[str]]] = {value.lower(): key for key, values in SHORTHAND.items() for value in values}
_REVERSE_LOOKUP: ClassVar[dict[str, list[str]]] = {
value.lower(): key for key, values in SHORTHAND.items() for value in values
}

@classmethod
def get_shorthand(cls, longhand: str) -> str | None:
Expand Down Expand Up @@ -163,14 +162,6 @@ def get_longhand(cls, shorthand: str) -> str | None:
return longhand[0] if longhand else None


class _BuildResults(NamedTuple):
"""Results of building a context specific model."""

model: cobra.Model
expression_index_list: list[int]
infeasible_reactions: pd.DataFrame


class _BoundaryReactions(NamedTuple):
"""Boundary reactions to be used in the context specific model."""

Expand Down Expand Up @@ -269,3 +260,104 @@ class _SourceWeights(_BaseDataType):
mrna: int
scrna: int
proteomics: int


@dataclass
class ModelBuildSettings:
troppo_epsilon: float = 1e-4
min_reaction_flux: float = 1e-7
solver_timeout: int = 1800 # time in seconds, defaults to 30 minutes

"""
Verbosity
Type: int
Default value: 0
Range: [0, 3]
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#csclientlog
"""
solver_verbosity: int = 0

"""
Feasibility
Type: double
Default value: 1e-6
Range: [1e-9, 1e-2]
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#feasibilitytol
"""
solver_feasibility: float = 1e-6

"""
OptimalityTol
Type: double
Default value: 1e-6
Range: [1e-9, 1e-2]
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#optimalitytol
"""
solver_optimality: float = 1e-6

"""
IntFeasTol
Type: double
Default value: 1e-5
Range: [1e-9, 1e-1]
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#intfeastol
"""
solver_integrality: float = 1e-6

"""
MIPGap
Relative MIP optimality gap
Default value: 1e-4
Range: [0, inf)
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#mipgap
"""
gurobi_mipgap: float = 1e-4

"""
IntegralityFocus
Type: int
Default value: 0
Range: [0, 1]
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#integralityfocus
"""
gurobi_integrality_focus: int = 0

"""
NumericFocus
Type: int
Default value: 0
Range: [0, 3]
From: https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#numericfocus
"""
gurobi_numeric_focus: int = 2

def __post_init__(self): # noqa: C901
"""Validate provided arguments.

:raises: ValueError if any check fails.
"""
if self.troppo_epsilon < 0:
raise ValueError("ModelBuildSettings: `troppo_epsilon` must be a non-negative float")
if self.min_reaction_flux < 0:
raise ValueError("ModelBuildSettings: `min_reaction_flux` must be a non-negative float")
if self.solver_verbosity not in {0, 1, 2, 3} or not isinstance(self.solver_verbosity, int):
raise ValueError("ModelBuildSettings: `solver_verbosity` must be an integer in the range [0, 3]")
if self.solver_timeout < 0 or not isinstance(self.solver_timeout, int):
raise ValueError("ModelBuildSettings: `solver_timeout` must be a non-negative integer")
if not (1e-9 < self.solver_feasibility < 1e-2):
raise ValueError("ModelBuildSettings: `solver_feasibility` must be a float in the range [1e-9, 1e-2]")
if not (1e-9 < self.solver_optimality < 1e-2):
raise ValueError("ModelBuildSettings: `solver_optimality` must be a float in the range [1e-9, 1e-2]")
if not (1e-9 < self.solver_integrality < 1e-1):
raise ValueError("ModelBuildSettings: `solver_integrality` must be a float in the range [1e-9, 1e-1]")
if self.gurobi_mipgap < 0:
raise ValueError("ModelBuildSettings: `gurobi_mipgap` must be a float in the range [1e-4, inf.)")
if self.gurobi_integrality_focus not in {0, 1} or not isinstance(self.gurobi_integrality_focus, int):
raise ValueError("ModelBuildSettings: `gurobi_integrality_focus` must be an integer in the range [0, 1]")
if self.gurobi_numeric_focus not in {0, 1, 2, 3} or not isinstance(self.gurobi_numeric_focus, int):
raise ValueError("ModelBuildSettings: `gurobi_numeric_focus` must be an integer in the range [0, 3]")
if self.troppo_epsilon < self.min_reaction_flux * 1000:
logger.warning(
"ModelBuildSettings: `troppo_epsilon` and `min_reaction_flux` have similar values. "
"This can cause inconsistent model builds. Consider ~1000x fold change between the two. "
)
Loading