imatpy


Nameimatpy JSON
Version 0.1.0 PyPI version JSON
download
home_page
Summary"Python implementation of the Integrative Metabolic Analysis Tool (iMAT) algorithm for context specific metabolic modeling."
upload_time2023-11-07 22:54:49
maintainer
docs_urlNone
authorBraden Griebel
requires_python>3.9,<3.11
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Readme

<img src="./imatpy_logo.png" height="60" alt="logo" />

[![Documentation
Status](https://readthedocs.org/projects/imatpy/badge/?version=latest.png)](https://imatpy.readthedocs.io/en/latest/?badge=latest)  
![Tests](https://github.com/Braden-Griebel/imatpy/actions/workflows/tests.yml/badge.svg)

## About

iMATpy is a python package implementing the iMAT algorithm for
integrating gene expression information with a genome scale metabolic
model, described in [(Shlomi T, et al. Network-based prediction of human
tissue-specific metabolism, Nat. Biotechnol., 2008, vol. 26 (pg.
1003-1010))](https://www.nature.com/articles/nbt.1487).

## Background

The iMAT algorithm takes a genome scale metabolic model (GSM), and gene
expression weights, then tries to find a feasible flux distribution
which maximizes the sum of reactions with high expression which have a
flux above `epsilon`, and reactions with low expression which have a
flux below `threshold`.

## Installation

This package can be installed via pip

``` python
pip install imatpy
```

## Solvers

In order to solve the optimization problems associated with iMAT, a
LP/MILP solver is required. By default this package uses the
[GLPK](https://www.gnu.org/software/glpk/) solver which is installed
automatically by COBRApy, but [Gurobi](https://www.gurobi.com/) and
[CPLEX](https://www.ibm.com/products/ilog-cplex-optimization-studio/cplex-optimizer).
Both Gurobi and CPLEX have free academic licenses available.

## Workflow

The general workflow for using this package is as follows:

1.  Normalize gene expression data for sequencing depth and gene length
    (TPM or RPKM both work well)
2.  Quantile normalize the gene expression data (for example with the
    [`qnorm` package](https://pypi.org/project/qnorm/)) (This is
    optional, but can help make the results less sensitive to
    parameters)
3.  Combine gene expression values accross samples, for example by
    taking the mean or median
4.  Convert the gene expression data into qualitative weights, of -1, 0,
    or 1, where -1 represents low expression, 1 represents high
    expression, and 0 represents all other genes. This can be done by
    setting the bottom 15% of genes to -1, the top 15% of genes to 1,
    and all other genes to 0. Other percentiles can be used, but 15% is
    a decent starting point.
5.  Using the `parse_gpr` submodule, specifically the
    `gene_to_rxn_weights` function, convert the gene weights into
    reaction weights using the GPR rules in the model.
6.  Either generate a flux distribution with the iMAT algorithm, or
    construct a new model with restrictions based on iMAT results.
    - To generate a flux distribution, use the `imatpy.imat` submodule,
      specifically the `imat` function. This function takes a model, and
      a series of reaction weights, and returns a flux distribution
      which maximizes the sum of reactions with high expression which
      have a flux above `epsilon`, and reactions with low expression
      which have a flux below `threshold`.  
    - To generate a model with restrictions based on the iMAT results,
      use the `model_creation` submodule. It includes a variety of
      different methods for generating models based on iMAT, with a
      wrapper function `generate_model` for convinience.

## Parse GPR

The `parse_gpr` submodule has functions for applying the
gene-protien-reaction (GPR) rules in a model to gene weights in order to
convert gene weights into reaction weights which can act as input to the
iMAT algorithm.

The input to this method is a pandas Series with the index being the
gene identifiers, and the values being the gene weights. The output is a
pandas Series with the index being the reaction identifiers, and the
values being the reaction weights. This method only handles a single
series, so the gene expression data must be processed into single
weights (with -1 representing lowly expressed genes, 1 representing
highly expressed genes, and 0 for all other genes).

Here is an example of how to use this method:

``` python
# External imports
import pandas as pd

# iMATpy imports
from imatpy.model_utils import read_model
from imatpy.parse_gpr import gene_to_rxn_weights

# Read in the model
model = read_model("./tests/data/test_model.xml")

# Create a pandas Series representing gene expression weights
model_weights = pd.Series({
            "g_A_imp": 1,
            "g_B_imp": -1,
            "g_C_imp": -1,
            "g_F_exp": 0,
            "g_G_exp": -1,
            "g_H_exp": 0,
            "g_A_B_D_E": 0,
            "g_C_E_F": -1,
            "g_C_H": 0,
            "g_D_G": 1,
        })

# Convert the gene weights into reaction weights
reaction_weights = gene_to_rxn_weights(model=model, gene_weights=model_weights)

# Print the reaction weights
print(reaction_weights)
```

    R_A_e_ex     0.0
    R_B_e_ex     0.0
    R_C_e_ex     0.0
    R_F_e_ex     0.0
    R_G_e_ex     0.0
    R_H_e_ex     0.0
    R_A_imp      1.0
    R_B_imp     -1.0
    R_C_imp     -1.0
    R_F_exp      0.0
    R_G_exp     -1.0
    R_H_exp      0.0
    r_A_B_D_E    0.0
    r_C_E_F     -1.0
    r_C_H        0.0
    r_D_G        1.0
    dtype: float64

## iMAT Methods

The `imat` submodule contains functions for running the iMAT algorithm.
The main function is `imat`, which takes a model, and a series of
reaction weights, and returns a flux distribution which maximizes the
sum of reactions with high expression which have a flux above `epsilon`,
and reactions with low expression which have a flux below `threshold`.

Here is an example of how to use this method:

``` python
# External imports
import pandas as pd

# iMATpy imports
from imatpy.model_utils import read_model
from imatpy.imat import imat

# Read in the model
model = read_model("./tests/data/test_model.xml")

# Read in the reaction weights
rxn_weights = pd.read_csv("./tests/data/test_model_reaction_weights.csv", index_col=0).squeeze()

# Run iMAT
imat_results = imat(model=model, rxn_weights=rxn_weights, epsilon=1, threshold=0.01)

# Print the imat objective
print(f"iMAT Objective: {imat_results.objective_value}")

# Print the imat flux distribution
print(f"iMAT Flux Distribution: \n{imat_results.fluxes}")
```

    iMAT Objective: 3.0
    iMAT Flux Distribution: 
    R_A_e_ex    -1.0
    R_B_e_ex    -1.0
    R_C_e_ex    -1.0
    R_F_e_ex     1.0
    R_G_e_ex     1.0
    R_H_e_ex    -0.0
    R_A_imp      1.0
    R_B_imp      1.0
    R_C_imp      1.0
    R_F_exp      1.0
    R_G_exp      1.0
    R_H_exp      0.0
    r_A_B_D_E    1.0
    r_C_E_F      1.0
    r_C_H        0.0
    r_D_G        1.0
    Name: fluxes, dtype: float64

## Model Creation

The `model_creation` submodule contains functions for creating new
models based on the results of iMAT. The main function is
`generate_model`, which takes a model, and a series of reaction weights,
and returns a new model with restrictions based on the iMAT results.

The available methods for creating a model based on an iMAT flux
distribution is:  
- `imat_restrictions` Adds the binary variables and constraints used in
the iMAT algorithm, as well as an additional constraint ensuring that
the flux distribution is within tolerance of the optimal iMAT objective
value. This method stays closest to the iMAT objective, but the included
indicator (binary) variables mean that is unsuitable for sampling.

- `simple_bounds` Adds bounds on the reactions found to be “on”, and
  “off” in iMAT. For all the highly expressed reactions found to be
  “on”, the flux is constrained to be at least `epsilon`. For all the
  lowly expressed reactions found to be “off”, the flux is constrained
  to be below `threshold`.

- `subset` Removes reactions from the model which are found to be “off”.
  For all the lowly expressed reactions found to be off, they are
  constrained to have a flux below `threshold`.

- `fva` Finds bounds using an FVA like approach. A temporary model is
  created in a simmilar way to the

- `imat_restrictions` method above, which includes the imat variables,
  constraints, and which also constrains the flux distribution to be
  near optimal for iMAT. The maximum and minimum fluxes allowed through
  each reaction (while still maintaining the optimal iMAT objective) is
  found. These values are used as the new reaction bounds. It should be
  noted, that although the individual upper and lower bounds for the
  reaction are achievable for each reation while being consistant with
  the optimal iMAT objective, this doesn’t guarantee that the flux
  distribution overall is consistant with the optimal iMAT objective.

- `milp` Uses a set of mixed integer linear programs to find whether a
  reaction should be forced off, forward, or reverse. Each reaction in
  turn is forced to be off, active in the forward direction, and active
  in the reverse direction, and the iMAT objective is maximized. Whether
  a reaction should be forced off, or active in either the forward or
  reverse direction is then determined by which direction maximizes the
  iMAT objective. Again, it should be noted that this doesn’t guarantee
  that the iMAT objective is overall maximized by solutions to this
  model.

Below is an example of how to generate a model with iMAT restrictions:

``` python
# External imports
import pandas as pd

# iMATpy imports
from imatpy.model_utils import read_model
from imatpy.model_creation import generate_model

# Read in the model
model = read_model("./tests/data/test_model.xml")

# Read in the reaction weights
rxn_weights = pd.read_csv("./tests/data/test_model_reaction_weights.csv", index_col=0).squeeze()

# Generate a model with iMAT restrictions
imat_model = generate_model(model=model, rxn_weights=rxn_weights, method="fva", epsilon=1, threshold=0.01)

# This model can be used for sampling, finding optimal biomass generation, finding essential genes, etc.
optimal_biomass = imat_model.slim_optimize()

print(f"Optimal Biomass: {optimal_biomass}")
```

    Optimal Biomass: 50.0

## Model Utils

The `model_utils` submodule contains several utility functions for
working with COBRApy models. Specifically, it contains functions for: -
Reading and writing models in various formats with a single function,
specifically `read_model`/`write_model`. - Determining if two models are
equivalent, using `model_eq`.

Here is an example of how to use the model IO methods:

``` python
# iMATpy imports
from imatpy.model_utils import read_model, write_model, model_eq

# You can read in a model from a file
model = read_model("./tests/data/test_model.xml") # in SBML
model = read_model("./tests/data/test_model.json") # in JSON
model = read_model("./tests/data/test_model.yml") # in YAML
model = read_model("./tests/data/test_model.mat") # in Matlab

# You can also write a model to a file
write_model(model, "./tests/data/test_model.xml") # in SBML
write_model(model, "./tests/data/test_model.json") # in JSON
write_model(model, "./tests/data/test_model.yml") # in YAML
write_model(model, "./tests/data/test_model.mat") # in Matlab
```

Here is an example of using the model comparison method:

``` python
# iMATpy imports
from imatpy.model_utils import read_model, model_eq

# Read a model
model = read_model("./tests/data/test_model.xml")

# Create a copy of the model
model_copy = model.copy()

# Check that the models are equivalent
print(f"Models are equivalent: {model_eq(model, model_copy)}")

# Change the copy model
model_copy.reactions.get_by_id("r_A_B_D_E").lower_bound = -314

# Check that the models are no longer equivalent
print(f"Models are equivalent: {model_eq(model, model_copy)}")
```

    Models are equivalent: True
    Models are equivalent: False

## License

This package itself is relased under an MIT license. It makes use of
several libraries which are listed below:  
- COBRApy: Released under the LGPL-2.0-or-later license see
[here](https://github.com/opencobra/cobrapy/blob/devel/LICENSE)  
- Numpy: Released under the BSD-3-Clause license see
[here](https://github.com/numpy/numpy/blob/main/LICENSE.txt)  
- Optlang: Released under the Apache-2.0 lisence see
[here](https://github.com/opencobra/optlang/blob/master/LICENSE)  
- Pandas: Released under the BSD-3-Clause license see
[here](https://github.com/pandas-dev/pandas/blob/main/LICENSE)  
- Scipy: Released under the BSD-3-Clause license see
[here](https://github.com/scipy/scipy/blob/main/LICENSE.txt)  
- Sympy: Released under the BSD-3-Clause license see
[here](https://github.com/sympy/sympy/blob/master/LICENSE)

In addition, these libraries were used during developement:  
- black: Used for autoformating  
- jupyter: Used for rendering quarto documents - flake8: Used for
linting - pytest: Used for running unittests  
- Sphinx: Used for generating documentation  
- sphinx-rtd-theme: Used for formating the documentation


            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "imatpy",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">3.9,<3.11",
    "maintainer_email": "",
    "keywords": "",
    "author": "Braden Griebel",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/ea/4e/115b03e2b8a6cae6bdb1d60c04acc7ee0bbd293ee33b6edb9b0e7d88e89f/imatpy-0.1.0.tar.gz",
    "platform": null,
    "description": "# Readme\n\n<img src=\"./imatpy_logo.png\" height=\"60\" alt=\"logo\" />\n\n[![Documentation\nStatus](https://readthedocs.org/projects/imatpy/badge/?version=latest.png)](https://imatpy.readthedocs.io/en/latest/?badge=latest)  \n![Tests](https://github.com/Braden-Griebel/imatpy/actions/workflows/tests.yml/badge.svg)\n\n## About\n\niMATpy is a python package implementing the iMAT algorithm for\nintegrating gene expression information with a genome scale metabolic\nmodel, described in [(Shlomi T, et al.\u00a0Network-based prediction of human\ntissue-specific metabolism, Nat. Biotechnol., 2008, vol.\u00a026 (pg.\n1003-1010))](https://www.nature.com/articles/nbt.1487).\n\n## Background\n\nThe iMAT algorithm takes a genome scale metabolic model (GSM), and gene\nexpression weights, then tries to find a feasible flux distribution\nwhich maximizes the sum of reactions with high expression which have a\nflux above `epsilon`, and reactions with low expression which have a\nflux below `threshold`.\n\n## Installation\n\nThis package can be installed via pip\n\n``` python\npip install imatpy\n```\n\n## Solvers\n\nIn order to solve the optimization problems associated with iMAT, a\nLP/MILP solver is required. By default this package uses the\n[GLPK](https://www.gnu.org/software/glpk/) solver which is installed\nautomatically by COBRApy, but [Gurobi](https://www.gurobi.com/) and\n[CPLEX](https://www.ibm.com/products/ilog-cplex-optimization-studio/cplex-optimizer).\nBoth Gurobi and CPLEX have free academic licenses available.\n\n## Workflow\n\nThe general workflow for using this package is as follows:\n\n1.  Normalize gene expression data for sequencing depth and gene length\n    (TPM or RPKM both work well)\n2.  Quantile normalize the gene expression data (for example with the\n    [`qnorm` package](https://pypi.org/project/qnorm/)) (This is\n    optional, but can help make the results less sensitive to\n    parameters)\n3.  Combine gene expression values accross samples, for example by\n    taking the mean or median\n4.  Convert the gene expression data into qualitative weights, of -1, 0,\n    or 1, where -1 represents low expression, 1 represents high\n    expression, and 0 represents all other genes. This can be done by\n    setting the bottom 15% of genes to -1, the top 15% of genes to 1,\n    and all other genes to 0. Other percentiles can be used, but 15% is\n    a decent starting point.\n5.  Using the `parse_gpr` submodule, specifically the\n    `gene_to_rxn_weights` function, convert the gene weights into\n    reaction weights using the GPR rules in the model.\n6.  Either generate a flux distribution with the iMAT algorithm, or\n    construct a new model with restrictions based on iMAT results.\n    - To generate a flux distribution, use the `imatpy.imat` submodule,\n      specifically the `imat` function. This function takes a model, and\n      a series of reaction weights, and returns a flux distribution\n      which maximizes the sum of reactions with high expression which\n      have a flux above `epsilon`, and reactions with low expression\n      which have a flux below `threshold`.  \n    - To generate a model with restrictions based on the iMAT results,\n      use the `model_creation` submodule. It includes a variety of\n      different methods for generating models based on iMAT, with a\n      wrapper function `generate_model` for convinience.\n\n## Parse GPR\n\nThe `parse_gpr` submodule has functions for applying the\ngene-protien-reaction (GPR) rules in a model to gene weights in order to\nconvert gene weights into reaction weights which can act as input to the\niMAT algorithm.\n\nThe input to this method is a pandas Series with the index being the\ngene identifiers, and the values being the gene weights. The output is a\npandas Series with the index being the reaction identifiers, and the\nvalues being the reaction weights. This method only handles a single\nseries, so the gene expression data must be processed into single\nweights (with -1 representing lowly expressed genes, 1 representing\nhighly expressed genes, and 0 for all other genes).\n\nHere is an example of how to use this method:\n\n``` python\n# External imports\nimport pandas as pd\n\n# iMATpy imports\nfrom imatpy.model_utils import read_model\nfrom imatpy.parse_gpr import gene_to_rxn_weights\n\n# Read in the model\nmodel = read_model(\"./tests/data/test_model.xml\")\n\n# Create a pandas Series representing gene expression weights\nmodel_weights = pd.Series({\n            \"g_A_imp\": 1,\n            \"g_B_imp\": -1,\n            \"g_C_imp\": -1,\n            \"g_F_exp\": 0,\n            \"g_G_exp\": -1,\n            \"g_H_exp\": 0,\n            \"g_A_B_D_E\": 0,\n            \"g_C_E_F\": -1,\n            \"g_C_H\": 0,\n            \"g_D_G\": 1,\n        })\n\n# Convert the gene weights into reaction weights\nreaction_weights = gene_to_rxn_weights(model=model, gene_weights=model_weights)\n\n# Print the reaction weights\nprint(reaction_weights)\n```\n\n    R_A_e_ex     0.0\n    R_B_e_ex     0.0\n    R_C_e_ex     0.0\n    R_F_e_ex     0.0\n    R_G_e_ex     0.0\n    R_H_e_ex     0.0\n    R_A_imp      1.0\n    R_B_imp     -1.0\n    R_C_imp     -1.0\n    R_F_exp      0.0\n    R_G_exp     -1.0\n    R_H_exp      0.0\n    r_A_B_D_E    0.0\n    r_C_E_F     -1.0\n    r_C_H        0.0\n    r_D_G        1.0\n    dtype: float64\n\n## iMAT Methods\n\nThe `imat` submodule contains functions for running the iMAT algorithm.\nThe main function is `imat`, which takes a model, and a series of\nreaction weights, and returns a flux distribution which maximizes the\nsum of reactions with high expression which have a flux above `epsilon`,\nand reactions with low expression which have a flux below `threshold`.\n\nHere is an example of how to use this method:\n\n``` python\n# External imports\nimport pandas as pd\n\n# iMATpy imports\nfrom imatpy.model_utils import read_model\nfrom imatpy.imat import imat\n\n# Read in the model\nmodel = read_model(\"./tests/data/test_model.xml\")\n\n# Read in the reaction weights\nrxn_weights = pd.read_csv(\"./tests/data/test_model_reaction_weights.csv\", index_col=0).squeeze()\n\n# Run iMAT\nimat_results = imat(model=model, rxn_weights=rxn_weights, epsilon=1, threshold=0.01)\n\n# Print the imat objective\nprint(f\"iMAT Objective: {imat_results.objective_value}\")\n\n# Print the imat flux distribution\nprint(f\"iMAT Flux Distribution: \\n{imat_results.fluxes}\")\n```\n\n    iMAT Objective: 3.0\n    iMAT Flux Distribution: \n    R_A_e_ex    -1.0\n    R_B_e_ex    -1.0\n    R_C_e_ex    -1.0\n    R_F_e_ex     1.0\n    R_G_e_ex     1.0\n    R_H_e_ex    -0.0\n    R_A_imp      1.0\n    R_B_imp      1.0\n    R_C_imp      1.0\n    R_F_exp      1.0\n    R_G_exp      1.0\n    R_H_exp      0.0\n    r_A_B_D_E    1.0\n    r_C_E_F      1.0\n    r_C_H        0.0\n    r_D_G        1.0\n    Name: fluxes, dtype: float64\n\n## Model Creation\n\nThe `model_creation` submodule contains functions for creating new\nmodels based on the results of iMAT. The main function is\n`generate_model`, which takes a model, and a series of reaction weights,\nand returns a new model with restrictions based on the iMAT results.\n\nThe available methods for creating a model based on an iMAT flux\ndistribution is:  \n- `imat_restrictions` Adds the binary variables and constraints used in\nthe iMAT algorithm, as well as an additional constraint ensuring that\nthe flux distribution is within tolerance of the optimal iMAT objective\nvalue. This method stays closest to the iMAT objective, but the included\nindicator (binary) variables mean that is unsuitable for sampling.\n\n- `simple_bounds` Adds bounds on the reactions found to be \u201con\u201d, and\n  \u201coff\u201d in iMAT. For all the highly expressed reactions found to be\n  \u201con\u201d, the flux is constrained to be at least `epsilon`. For all the\n  lowly expressed reactions found to be \u201coff\u201d, the flux is constrained\n  to be below `threshold`.\n\n- `subset` Removes reactions from the model which are found to be \u201coff\u201d.\n  For all the lowly expressed reactions found to be off, they are\n  constrained to have a flux below `threshold`.\n\n- `fva` Finds bounds using an FVA like approach. A temporary model is\n  created in a simmilar way to the\n\n- `imat_restrictions` method above, which includes the imat variables,\n  constraints, and which also constrains the flux distribution to be\n  near optimal for iMAT. The maximum and minimum fluxes allowed through\n  each reaction (while still maintaining the optimal iMAT objective) is\n  found. These values are used as the new reaction bounds. It should be\n  noted, that although the individual upper and lower bounds for the\n  reaction are achievable for each reation while being consistant with\n  the optimal iMAT objective, this doesn\u2019t guarantee that the flux\n  distribution overall is consistant with the optimal iMAT objective.\n\n- `milp` Uses a set of mixed integer linear programs to find whether a\n  reaction should be forced off, forward, or reverse. Each reaction in\n  turn is forced to be off, active in the forward direction, and active\n  in the reverse direction, and the iMAT objective is maximized. Whether\n  a reaction should be forced off, or active in either the forward or\n  reverse direction is then determined by which direction maximizes the\n  iMAT objective. Again, it should be noted that this doesn\u2019t guarantee\n  that the iMAT objective is overall maximized by solutions to this\n  model.\n\nBelow is an example of how to generate a model with iMAT restrictions:\n\n``` python\n# External imports\nimport pandas as pd\n\n# iMATpy imports\nfrom imatpy.model_utils import read_model\nfrom imatpy.model_creation import generate_model\n\n# Read in the model\nmodel = read_model(\"./tests/data/test_model.xml\")\n\n# Read in the reaction weights\nrxn_weights = pd.read_csv(\"./tests/data/test_model_reaction_weights.csv\", index_col=0).squeeze()\n\n# Generate a model with iMAT restrictions\nimat_model = generate_model(model=model, rxn_weights=rxn_weights, method=\"fva\", epsilon=1, threshold=0.01)\n\n# This model can be used for sampling, finding optimal biomass generation, finding essential genes, etc.\noptimal_biomass = imat_model.slim_optimize()\n\nprint(f\"Optimal Biomass: {optimal_biomass}\")\n```\n\n    Optimal Biomass: 50.0\n\n## Model Utils\n\nThe `model_utils` submodule contains several utility functions for\nworking with COBRApy models. Specifically, it contains functions for: -\nReading and writing models in various formats with a single function,\nspecifically `read_model`/`write_model`. - Determining if two models are\nequivalent, using `model_eq`.\n\nHere is an example of how to use the model IO methods:\n\n``` python\n# iMATpy imports\nfrom imatpy.model_utils import read_model, write_model, model_eq\n\n# You can read in a model from a file\nmodel = read_model(\"./tests/data/test_model.xml\") # in SBML\nmodel = read_model(\"./tests/data/test_model.json\") # in JSON\nmodel = read_model(\"./tests/data/test_model.yml\") # in YAML\nmodel = read_model(\"./tests/data/test_model.mat\") # in Matlab\n\n# You can also write a model to a file\nwrite_model(model, \"./tests/data/test_model.xml\") # in SBML\nwrite_model(model, \"./tests/data/test_model.json\") # in JSON\nwrite_model(model, \"./tests/data/test_model.yml\") # in YAML\nwrite_model(model, \"./tests/data/test_model.mat\") # in Matlab\n```\n\nHere is an example of using the model comparison method:\n\n``` python\n# iMATpy imports\nfrom imatpy.model_utils import read_model, model_eq\n\n# Read a model\nmodel = read_model(\"./tests/data/test_model.xml\")\n\n# Create a copy of the model\nmodel_copy = model.copy()\n\n# Check that the models are equivalent\nprint(f\"Models are equivalent: {model_eq(model, model_copy)}\")\n\n# Change the copy model\nmodel_copy.reactions.get_by_id(\"r_A_B_D_E\").lower_bound = -314\n\n# Check that the models are no longer equivalent\nprint(f\"Models are equivalent: {model_eq(model, model_copy)}\")\n```\n\n    Models are equivalent: True\n    Models are equivalent: False\n\n## License\n\nThis package itself is relased under an MIT license. It makes use of\nseveral libraries which are listed below:  \n- COBRApy: Released under the LGPL-2.0-or-later license see\n[here](https://github.com/opencobra/cobrapy/blob/devel/LICENSE)  \n- Numpy: Released under the BSD-3-Clause license see\n[here](https://github.com/numpy/numpy/blob/main/LICENSE.txt)  \n- Optlang: Released under the Apache-2.0 lisence see\n[here](https://github.com/opencobra/optlang/blob/master/LICENSE)  \n- Pandas: Released under the BSD-3-Clause license see\n[here](https://github.com/pandas-dev/pandas/blob/main/LICENSE)  \n- Scipy: Released under the BSD-3-Clause license see\n[here](https://github.com/scipy/scipy/blob/main/LICENSE.txt)  \n- Sympy: Released under the BSD-3-Clause license see\n[here](https://github.com/sympy/sympy/blob/master/LICENSE)\n\nIn addition, these libraries were used during developement:  \n- black: Used for autoformating  \n- jupyter: Used for rendering quarto documents - flake8: Used for\nlinting - pytest: Used for running unittests  \n- Sphinx: Used for generating documentation  \n- sphinx-rtd-theme: Used for formating the documentation\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\"Python implementation of the Integrative Metabolic Analysis Tool (iMAT) algorithm for context specific metabolic modeling.\"",
    "version": "0.1.0",
    "project_urls": null,
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d42a9c4874b74fbb5cb7c40c4356bb9369b9e9e53a2c27a01ff37a46231e1032",
                "md5": "dfe3486f6219fe46b0167d0ee725fa7b",
                "sha256": "b0d8051ed9d60f2ebc339a3774f779a11dcd46132ae1197f40cd2cf49b6f4462"
            },
            "downloads": -1,
            "filename": "imatpy-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "dfe3486f6219fe46b0167d0ee725fa7b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">3.9,<3.11",
            "size": 16433,
            "upload_time": "2023-11-07T22:54:48",
            "upload_time_iso_8601": "2023-11-07T22:54:48.577685Z",
            "url": "https://files.pythonhosted.org/packages/d4/2a/9c4874b74fbb5cb7c40c4356bb9369b9e9e53a2c27a01ff37a46231e1032/imatpy-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ea4e115b03e2b8a6cae6bdb1d60c04acc7ee0bbd293ee33b6edb9b0e7d88e89f",
                "md5": "5080c00a6c1befee01cd54317f88d9a3",
                "sha256": "a444fb8662342e933c53b3bdacefd43b0eb8101b0f0c301b7c354d8241f3491f"
            },
            "downloads": -1,
            "filename": "imatpy-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "5080c00a6c1befee01cd54317f88d9a3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">3.9,<3.11",
            "size": 18162,
            "upload_time": "2023-11-07T22:54:49",
            "upload_time_iso_8601": "2023-11-07T22:54:49.990554Z",
            "url": "https://files.pythonhosted.org/packages/ea/4e/115b03e2b8a6cae6bdb1d60c04acc7ee0bbd293ee33b6edb9b0e7d88e89f/imatpy-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-07 22:54:49",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "imatpy"
}
        
Elapsed time: 0.27903s