index.html 15.8 KB
Newer Older
Documenter.jl's avatar
Documenter.jl committed
1
<!DOCTYPE html>
Documenter.jl's avatar
Documenter.jl committed
2
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Working with custom models · COBREXA.jl</title><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.11.1/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="../.."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../../assets/documenter.js"></script><script src="../../siteinfo.js"></script><script src="../../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../../assets/themeswap.js"></script><link href="../../assets/favicon.ico" rel="icon" type="image/x-icon"/></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="../../"><img class="docs-light-only" src="../../assets/logo.svg" alt="COBREXA.jl logo"/><img class="docs-dark-only" src="../../assets/logo-dark.svg" alt="COBREXA.jl logo"/></a><div class="docs-package-name"><span class="docs-autofit">COBREXA.jl</span></div><form class="docs-search" action="../../search/"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="../../">Home</a></li><li><span class="tocitem">User guide</span><ul><li><input class="collapse-toggle" id="menuitem-2-1" type="checkbox"/><label class="tocitem" for="menuitem-2-1"><span class="docs-label">Quickstart tutorials</span><i class="docs-chevron"></i></label><ul class="collapsed"><li><a class="tocitem" href="../../tutorials/">All tutorials</a></li><li><a class="tocitem" href="../../tutorials/1_loading/">Loading and converting model data</a></li><li><a class="tocitem" href="../../tutorials/2_analysis/">Basic analysis of constraint-based models</a></li><li><a class="tocitem" href="../../tutorials/3_hpc/">Distributed processing and HPC environments</a></li><li><a class="tocitem" href="../../tutorials/4_modifying/">Modifying and saving the models</a></li></ul></li><li><input class="collapse-toggle" id="menuitem-2-2" type="checkbox" checked/><label class="tocitem" for="menuitem-2-2"><span class="docs-label">Advanced tutorials</span><i class="docs-chevron"></i></label><ul class="collapsed"><li><a class="tocitem" href="../">All advanced tutorials</a></li><li><a class="tocitem" href="../1_variants/">Exploring many model variants</a></li><li class="is-active"><a class="tocitem" href>Working with custom models</a><ul class="internal"><li><a class="tocitem" href="#Writing-the-generic-accessors"><span>Writing the generic accessors</span></a></li><li><a class="tocitem" href="#Writing-generic-model-modifications"><span>Writing generic model modifications</span></a></li></ul></li></ul></li><li><input class="collapse-toggle" id="menuitem-2-3" type="checkbox"/><label class="tocitem" for="menuitem-2-3"><span class="docs-label">Examples and notebooks</span><i class="docs-chevron"></i></label><ul class="collapsed"><li><a class="tocitem" href="../../notebooks/">All notebooks</a></li><li><a class="tocitem" href="../../notebooks/1_loading_converting_saving/">Loading, converting, and saving models</a></li><li><a class="tocitem" href="../../notebooks/2_finding_balance/">Finding balance and variability of constraint-based models</a></li><li><a class="tocitem" href="../../notebooks/3_basic_stdmodel_usage/">Basic usage of <code>StandardModel</code></a></li><li><a class="tocitem" href="../../notebooks/4_basic_core_coupled_usage/">Basic usage of <code>CoreModel</code> and <code>CoreModelCoupled</code></a></li><li><a class="tocitem" href="../../notebooks/5_basic_stdmodel_construction/">Model construction and modification</a></li><li><a class="tocitem" href="../../notebooks/6_screening/">Exploring model variants with <code>screen</code></a></li><li><a class="tocitem" href="../../notebooks/7_community_model/">Building and analysing a small community model</a></li><li><a class="tocitem" href="../../notebooks/8_custom_model/">Using a custom model data structure</a></li><li><a class="tocitem" href="../../notebooks/9_max_min_driving_force_analysis/">Maximum-minimum driving force analysis</a></li></ul></li></ul></li><li><span class="tocitem">Types and functions</span><ul><li><a class="tocitem" href="../../functions/">Contents</a></li><li><a class="tocitem" href="../../functions/analysis/">Analysis functions</a></li><li><a class="tocitem" href="../../functions/base/">Base functions</a></li><li><a class="tocitem" href="../../functions/io/">Input and output</a></li><li><a class="tocitem" href="../../functions/reconstruction/">Model construction functions</a></li><li><a class="tocitem" href="../../functions/types/">Types</a></li><li><a class="tocitem" href="../../functions/utils/">Utilities</a></li></ul></li><li><a class="tocitem" href="../../howToContribute/">How to contribute</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">User guide</a></li><li><a class="is-disabled">Advanced tutorials</a></li><li class="is-active"><a href>Working with custom models</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Working with custom models</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://github.com/lcsb-biocore/COBREXA.jl/blob/master/docs/src/advanced/2_custom_model.md" title="Edit on GitHub"><span class="docs-icon fab"></span><span class="docs-label is-hidden-touch">Edit on GitHub</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Working-with-custom-models"><a class="docs-heading-anchor" href="#Working-with-custom-models">Working with custom models</a><a id="Working-with-custom-models-1"></a><a class="docs-heading-anchor-permalink" href="#Working-with-custom-models" title="Permalink"></a></h1><p>It may happen that the intuitive representation of your data does not really match what is supported by a given COBRA package. COBREXA.jl attempts to avoid this problem by providing a flexible framework for containing any data structure that can, somehow, represent the constraint-based model.</p><p>The task of having such a polymorphic model definition can be split into 2 separate concerns:</p><ul><li>How to allow the analysis functions to gather the required information from any user-specified model data structure?</li><li>How to make the reconstruction functions (i.e., reaction or gene deletions) work properly on any data structure?</li></ul><p>To solve the first concern, COBREXA.jl specifies a set of generic accessors that work over the abstract type <a href="../../functions/types/#COBREXA.MetabolicModel"><code>MetabolicModel</code></a>. To use your data structure in a model, you just make it a subtype of <a href="../../functions/types/#COBREXA.MetabolicModel"><code>MetabolicModel</code></a> and overload the required accessors. The accessors are functions that extract some relevant information, such as <a href="../../functions/types/#COBREXA.stoichiometry-Tuple{CoreModel}"><code>stoichiometry</code></a> and <a href="../../functions/types/#COBREXA.bounds-Tuple{CoreModel}"><code>bounds</code></a>, returning a fixed simple data type that can be further used by COBREXA.  You may see a complete list of accessors <a href="../../functions/#Base-Types">here</a>.</p><p>A good solution to the second concern is a slightly more involved, as writing generic data modifiers is notoriously hard. Still, there is support for easily making small changes to the model using the modifications system, with functions such as <a href="../../functions/reconstruction/#COBREXA.with_added_reactions-Tuple"><code>with_added_reactions</code></a> and <a href="../../functions/reconstruction/#COBREXA.with_changed_bound-Tuple"><code>with_changed_bound</code></a>.</p><div class="admonition is-success"><header class="admonition-header">Notebook available</header><div class="admonition-body"><p>A better example of using a custom model structure is available <a href="../../notebooks/8_custom_model/">in a separate notebook</a>.</p></div></div><h2 id="Writing-the-generic-accessors"><a class="docs-heading-anchor" href="#Writing-the-generic-accessors">Writing the generic accessors</a><a id="Writing-the-generic-accessors-1"></a><a class="docs-heading-anchor-permalink" href="#Writing-the-generic-accessors" title="Permalink"></a></h2><p>Let&#39;s write a data structure that represents a very small model that contains N metabolites that are converted in a circle through N linear, coupled reactions. (E.g., for N=3, we would have a conversion of metabolites A, B and C ordered as A → B → C → A.) This may be useful for testing purposes; we will use it for a simple demonstration.</p><p>The whole model can thus be specified with a single integer N that represents the length of the reaction cycle:</p><pre><code class="language-julia">struct CircularModel &lt;: MetabolicModel
Documenter.jl's avatar
Documenter.jl committed
3
4
5
6
7
8
9
10
11
12
13
14
    size::Int
end</code></pre><p>First, define the reactions and metabolites:</p><pre><code class="language-julia">COBREXA.n_reactions(m::CircularModel) = m.size
COBREXA.n_metabolites(m::CircularModel) = m.size

COBREXA.reactions(m::CircularModel) = [&quot;rxn$i&quot; for i in 1:n_reactions(m)]
COBREXA.metabolites(m::CircularModel) = [&quot;met$i&quot; for i in 1:n_metabolites(m)]</code></pre><p>It is useful to re-use the already defined functions, as that improves the code maintainability.</p><p>We can continue with the actual linear model properties:</p><pre><code class="language-julia">function COBREXA.objective(m::CircularModel)
    c = spzeros(n_reactions(m))
    c[1] = 1 #optimize the first reaction
    return c
end

COBREXA.bounds(m::CircularModel) = (
Documenter.jl's avatar
Documenter.jl committed
15
16
    zeros(n_reactions(m)), # lower bounds
    ones(n_reactions(m)), # upper bounds
Documenter.jl's avatar
Documenter.jl committed
17
18
19
20
21
22
23
)

function COBREXA.stoichiometry(m::CircularModel)
    nr = n_reactions(m)
    stoi(i,j) =
        i == j ? 1.0 :
        (i % nr + 1) == j  ? -1.0 :
Documenter.jl's avatar
Documenter.jl committed
24
        0.0
Documenter.jl's avatar
Documenter.jl committed
25
26

    sparse([stoi(i,j) for i in 1:nr, j in 1:nr])
Documenter.jl's avatar
Documenter.jl committed
27
end</code></pre><p>You may check that the result now works just as with <a href="../../functions/types/#COBREXA.CoreModel"><code>CoreModel</code></a> and <a href="../../functions/types/#COBREXA.StandardModel"><code>StandardModel</code></a>:</p><pre><code class="language-julia">julia&gt; m = CircularModel(5)
Documenter.jl's avatar
Documenter.jl committed
28
29
Metabolic model of type CircularModel

Documenter.jl's avatar
Documenter.jl committed
30
31
32
  1.0  -1.0    ⋅     ⋅     ⋅
   ⋅    1.0  -1.0    ⋅     ⋅
   ⋅     ⋅    1.0  -1.0    ⋅
Documenter.jl's avatar
Documenter.jl committed
33
34
35
36
37
38
39
40
41
42
43
   ⋅     ⋅     ⋅    1.0  -1.0
 -1.0    ⋅     ⋅     ⋅    1.0
Number of reactions: 5
Number of metabolites: 5
</code></pre><p>This interface is sufficient to run most of the basic analyses, especially the flux balance finding ones:</p><pre><code class="language-julia">julia&gt; flux_balance_analysis_dict(m, Tulip.Optimizer)
Dict{String, Float64} with 5 entries:
  &quot;rxn5&quot; =&gt; 1.0
  &quot;rxn2&quot; =&gt; 1.0
  &quot;rxn1&quot; =&gt; 1.0
  &quot;rxn3&quot; =&gt; 1.0
  &quot;rxn4&quot; =&gt; 1.0
Documenter.jl's avatar
Documenter.jl committed
44
</code></pre><h2 id="Writing-generic-model-modifications"><a class="docs-heading-anchor" href="#Writing-generic-model-modifications">Writing generic model modifications</a><a id="Writing-generic-model-modifications-1"></a><a class="docs-heading-anchor-permalink" href="#Writing-generic-model-modifications" title="Permalink"></a></h2><p>The custom model structure can also be made compatible with many of the existing variant-generating functions and analysis modifiers.</p><p>The functions prepared for use as &quot;variants&quot; in <a href="../../functions/analysis/#COBREXA.screen-Tuple"><code>screen</code></a>, usually prefixed by <code>with_</code>, have their generic variants that only call simpler, overloadable functions for each specific model. This choice is based on the overloading dispatch system of Julia. For example,<a href="../../functions/reconstruction/#COBREXA.with_removed_metabolites-Tuple"><code>with_removed_metabolites</code></a> is implemented very generically by reducing the problem to some specific <a href="../../functions/reconstruction/#COBREXA.remove_metabolites-Tuple{CoreModel, AbstractVector{Int64}}"><code>remove_metabolites</code></a> functions selected by the dispatch, as follows:</p><pre><code class="language-julia">with_removed_metabolites(args...; kwargs...) =
Documenter.jl's avatar
Documenter.jl committed
45
    m -&gt; remove_metabolites(m, args...; kwargs...)</code></pre><p>To be able to use <a href="../../functions/reconstruction/#COBREXA.with_removed_metabolites-Tuple"><code>with_removed_metabolites</code></a> in your model, we can just overload the actual inner function. For the simple circular model, the modification might as well look like this:</p><pre><code class="language-julia">COBREXA.remove_metabolites(m::CircularModel, n::Int) =
Documenter.jl's avatar
Documenter.jl committed
46
    return CircularModel(m.size - n)</code></pre><div class="admonition is-danger"><header class="admonition-header">Functions that generate model variants must be pure</header><div class="admonition-body"><p>Notice that the function is &quot;pure&quot;, i.e., does not make any in-place modifications to the original model structure. That property is required for <a href="../../functions/analysis/#COBREXA.screen-Tuple"><code>screen</code></a> and other functions to properly and predictably apply the modifications to the model. To expose potential in-place modifications to your codebase, you should instead overload the &quot;bang&quot; counterpart of remove metabolites, called <a href="../../functions/reconstruction/#COBREXA.remove_metabolites!-Tuple{CoreModel, AbstractVector{Int64}}"><code>remove_metabolites!</code></a>.</p></div></div></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../1_variants/">« Exploring many model variants</a><a class="docs-footer-nextpage" href="../../notebooks/">All notebooks »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> on <span class="colophon-date" title="Monday 16 May 2022 19:38">Monday 16 May 2022</span>. Using Julia version 1.7.0.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>