opencobra / cobrapy

COBRApy is a package for constraint-based modeling of metabolic networks.
http://opencobra.github.io/cobrapy/
GNU General Public License v2.0
465 stars 218 forks source link

cobra.io.write_sbml_file ignoring default upper bound from cobra.Configuration() #1101

Closed Devlin-Moyer closed 1 year ago

Devlin-Moyer commented 3 years ago

Starting with the Recon3D model straight from BiGG, which has all reactions set to a default upper bound of 1000, I changed some reactions to have upper bounds larger than 1000 and noticed that, after writing the model to an SBML file and reading it back in, the upper bounds on all of the reactions I had left with the default upper bound of 1000 had much higher upper bounds. Following the documentation here, I verified that the default upper bound set in the global configuration object was 1000 even while this was happening. I then found this in the _model_to_sbml function:

    # minimum and maximum value from model
    if len(cobra_model.reactions) > 0:
        min_value = min(cobra_model.reactions.list_attr("lower_bound"))
        max_value = max(cobra_model.reactions.list_attr("upper_bound"))
    else:
        min_value = config.lower_bound
        max_value = config.upper_bound

    _create_parameter(
        model, pid=LOWER_BOUND_ID, value=min_value, sbo=SBO_DEFAULT_FLUX_BOUND
    )
    _create_parameter(
        model, pid=UPPER_BOUND_ID, value=max_value, sbo=SBO_DEFAULT_FLUX_BOUND
    )

which seems to show that the default lower and upper bounds specified in the global configuration object are only used when writing models that have no reactions in them. If the model being written has any reactions in it, the default upper bound of the generated SBML file is set to the largest upper bound of any reaction in the model instead of the default upper bound in the global configuration object, and I can't really imagine that being the behavior anyone wants or expects. Let me know if I'm missing something here.

A reproducible example using the Recon3D from BiGG:

import cobra
cobra_config = cobra.Configuration() 
cobra_config.upper_bound
# 1000.0
cobra_config.lower_bound
# -1000.0
Recon3D = cobra.io.read_sbml_model('Recon3D.xml')
len([r.upper_bound for r in Recon3D.reactions if r.upper_bound > 1000])
# 0
Recon3D.reactions[100].upper_bound = 5000
len([r.upper_bound for r in Recon3D.reactions if r.upper_bound > 1000])
# 1
cobra.io.write_sbml_model(Recon3D, 'temp/test_file.xml')
cobra_config = cobra.Configuration()
cobra_config.upper_bound
# 1000.0
cobra_config.lower_bound
# -1000.0
test_model = cobra.io.read_sbml_model('temp/test_file.xml')
len([r.upper_bound for r in test_model.reactions if r.upper_bound > 1000])
# 10566
cobra_config = cobra.Configuration()
cobra_config.upper_bound
# 1000.0
cobra_config.lower_bound
# -1000.0
len([r.upper_bound for r in Recon3D.reactions if r.upper_bound > 1000])
# 1

Context

``` System Information ================== OS Linux OS-release 3.10.0-1160.25.1.el7.x86_64 Python 3.7.5 Package Versions ================ appdirs 1.4.4 black ; extra == 'development' not installed bumpversion ; extra == 'development' not installed cobra 0.21.0 depinfo 1.7.0 diskcache 5.2.1 future 0.18.2 httpx 0.17.1 importlib-resources 5.1.2 isort ; extra == 'development' not installed numpy 1.20.2 optlang 1.4.4 pandas 1.2.4 pip 21.1.2 pydantic 1.8.1 python-libsbml 5.19.0 rich 6.2.0 ruamel.yaml 0.17.2 scipy 1.6.2 setuptools 46.4.0 six 1.15.0 swiglpk 5.0.3 tox ; extra == 'development' not installed wheel 0.34.2 ```
matthiaskoenig commented 3 years ago

@Devlin-Moyer Thanks for the detailed report. Yes, looks clearly like a bug. I will commit a fix asap. Best Matthias

ym2877 commented 1 year ago

@matthiaskoenig Has this been fixed? https://github.com/opencobra/cobrapy/issues/1300

cdiener commented 1 year ago

This seems to have been fixed in #1300. Feel free to reopen if the problem persists.