Skip to content

Commit

Permalink
bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
SamiralVdB committed Jan 28, 2025
1 parent f58f9e1 commit 1c0898c
Show file tree
Hide file tree
Showing 4 changed files with 357 additions and 111 deletions.
34 changes: 20 additions & 14 deletions src/PAModelpy/Enzyme.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from optlang.symbolics import Zero

from .CatalyticEvent import CatalyticEvent
from typing import Dict, Union, Optional
from typing import Dict, Union, Optional, Literal
from warnings import warn

def _change_catalytic_event_list_to_dictlist_after_unpickling(self):
Expand Down Expand Up @@ -86,6 +86,7 @@ def __init__(
self.annotation = {
"type": "Constraint"
} # you can add an annotation for an enzyme

@property
def kcat_values(self):
"""Returns a dictionary with kcat values for each associated reaction.
Expand All @@ -97,7 +98,7 @@ def kcat_values(self):

@property
def concentration(
self, units: str = "mmol/gDW", return_units: bool = False
self, units: Literal['mmol/gDW', 'g/gDW'] = "mmol/gDW", return_units: bool = False
) -> float:
"""Returns the enzyme's total concentration considering any associated reactions.
Expand All @@ -113,14 +114,14 @@ def concentration(
concentration = self.enzyme_variable.concentration
if units == 'g/gDW':
#converting mmol to grams of protein:
# [g] = [mmol]* 1e-3 [mol/mmol] * MW[g/mol] *1e-6 [solver tolerance conversion factor]
concentration = concentration * 1e-3 * self.molmass*1e-6
# [g] = [mmol]* 1e-3 [mol/mmol] * MW[g/mol]
concentration = concentration * 1e-3 * self.molmass
if return_units:
return concentration*1e-6, units
return concentration*1e-6
return concentration, units
return concentration

@concentration.setter
def concentration(self, conc):
def concentration(self, conc:float):
self.enzyme_variable.concentration = conc

@property
Expand All @@ -132,10 +133,10 @@ def model(self, model):
self._model = model
self.enzyme_id_regex = model.ENZYME_ID_REGEX

def set_forward_concentration(self, conc):
def set_forward_concentration(self, conc:float):
self.enzyme_variable.set_forward_concentration(conc)

def set_reverse_concentration(self, conc):
def set_reverse_concentration(self, conc:float):
self.enzyme_variable.set_reverse_concentration(conc)

def create_constraint(self, extension: str = None):
Expand Down Expand Up @@ -345,6 +346,7 @@ def __getstate__(self):
# Return the state to be pickled
state = self.__dict__.copy()
state['catalytic_events'] = list(self.catalytic_events)
state['transcripts'] = list(self.transcripts)
# Handle any non-serializable attributes here
return state

Expand Down Expand Up @@ -379,11 +381,11 @@ def __init__(
self,
id: str,
rxn2kcat: Dict,
enzymes: DictList = DictList(),
enzymes: DictList = DictList(),
genes: list = [],
upper_bound: Union[int, float] = 1000.0,
name: Optional[str] = None,
molmass: Union[int, float] = DEFAULT_ENZYME_MOL_MASS, ):
upper_bound: Union[int, float] = 1000.0,
name: Optional[str] = None,
molmass: Union[int, float] = DEFAULT_ENZYME_MOL_MASS, ):
super().__init__(
id=id,
rxn2kcat=rxn2kcat,
Expand All @@ -398,6 +400,10 @@ def __init__(
self.add_enzymes(enzymes)

def add_enzymes(self, enzymes: DictList):
#if required: recover dictlist after pickle
if not isinstance(self.enzymes, DictList):
self.enzymes = DictList(self.enzymes)

for enzyme in enzymes:
if enzyme not in self.enzymes:# and not isinstance(enzyme, EnzymeComplex):
self.enzymes.append(enzyme)
Expand Down Expand Up @@ -450,7 +456,7 @@ def __getstate__(self):
# Return the state to be pickled
state = self.__dict__.copy()
state['catalytic_events'] = list(self.catalytic_events)

state['enzymes'] = list(self.enzymes)
# Handle any non-serializable attributes here
return state

Expand Down
21 changes: 16 additions & 5 deletions src/PAModelpy/EnzymeSectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ def add(self, model):
if rxn_id in rxn2protein.keys():
del rxn2protein[rxn_id]
except:
print(model.reactions.query(rxn_id))
warn(
f"Reaction {rxn_id} is not in the model, this reaction will be skipped"
)
Expand Down Expand Up @@ -194,6 +193,13 @@ def add(self, model):
if enzyme_id in model.enzyme_variables and not self._enzyme_is_enzyme_complex(protein_reaction, enzyme_id):
enzyme = model.enzymes.get_by_id(enzyme_id)
self._add_reaction_to_enzyme(model, enzyme, rxn_id, kcat)
self.rxn2protein[rxn_id].update({
enzyme_id: {
**kcat,
'genes': enzyme.genes,
'protein_reaction_association': protein_reaction
}
})

else:
if self.protein2gene != {}:
Expand All @@ -208,15 +214,14 @@ def add(self, model):
molmass=molmass,
genes=gene_list
)

if self._enzyme_is_enzyme_complex(protein_reaction, enzyme_id):
for pr in protein_reaction:
if len(pr) > 1:
#need to sort so the order of the id does not make the enzyme complex unique
#e.g.: B1_B2_B3 should not be added if B3_B1_B2 is already in the model
enzyme_complex_id = '_'.join(sorted(pr))

if enzyme_complex_id not in model.enzymes:
if enzyme_complex_id not in model.enzyme_variables:
enzyme = EnzymeComplex(
id=enzyme_complex_id,
rxn2kcat={rxn_id: kcat},
Expand All @@ -242,6 +247,7 @@ def add(self, model):
enz_complex.add_enzymes([enzyme])

else:

model.add_enzymes([enzyme])

self.constraints += [enzyme]
Expand All @@ -252,7 +258,6 @@ def add(self, model):

# adding to the enzyme sector object for easy removal
model.tpc += 1

return model

def check_kcat_values(self, model, reaction, enzyme_dict):
Expand Down Expand Up @@ -340,7 +345,12 @@ def _add_reaction_to_enzyme(self, model, enzyme:Union[Enzyme, EnzymeComplex], rx
model.add_catalytic_events([enzyme.catalytic_events.get_by_id(f'CE_{rxn_id}')])

def _enzyme_is_enzyme_complex(self, protein_reaction, enzyme_id):
return any([((enzyme_id in pr) & (len(pr) > 1)) for pr in protein_reaction])
return any(
[all(
[sorted(pr) == sorted(enzyme_id.split('_')) and #enzyme should take part in enzyme complex
len(pr)>1] # enzyme complex needs to have at least 2 proteins
) for pr in protein_reaction]
)

def _get_model_genes_from_enzyme(self, enzyme_id: str, model: Model) -> list:
"""
Expand All @@ -358,6 +368,7 @@ def _get_model_genes_from_enzyme(self, enzyme_id: str, model: Model) -> list:
gene_list = []
for genes_or in gene_id_list:
genes_and_list = []
# print(genes_or, enzyme_id)
for gene_and in genes_or:
#check if there is an and relation (then gene and should be a list and not a string)
if isinstance(gene_and, list):
Expand Down
Loading

0 comments on commit 1c0898c

Please sign in to comment.