Using natural language to build models

In this tutorial we build a simple model using natural language, and export it into different formats.

Read INDRA Statements from a natural language string

First we import INDRA’s API to the TRIPS reading system. We then define a block of text which serves as the description of the mechanism to be modeled in the model_text variable. Finally, indra.sources.trips.process_text is called which sends a request to the TRIPS web service, gets a response and processes the extraction knowledge base to obtain a list of INDRA Statements

In [1]: from indra.sources import trips

In [2]: model_text = 'MAP2K1 phosphorylates MAPK1 and DUSP6 dephosphorylates MAPK1.'

In [3]: tp = trips.process_text(model_text)

At this point tp.statements should contain 2 INDRA Statements: a Phosphorylation Statement and a Dephosphorylation Statement. Note that the evidence sentence for each Statement is propagated:

In [4]: for st in tp.statements:
   ...:     print('%s with evidence "%s"' % (st, st.evidence[0].text))
Phosphorylation(MAP2K1(), MAPK1()) with evidence "MAP2K1 phosphorylates MAPK1 and DUSP6 dephosphorylates MAPK1."
Dephosphorylation(DUSP6(), MAPK1()) with evidence "MAP2K1 phosphorylates MAPK1 and DUSP6 dephosphorylates MAPK1."

Assemble the INDRA Statements into a rule-based executable model

We next use INDRA’s PySB Assembler to automatically assemble a rule-based model representing the biochemical mechanisms described in model_text. First a PysbAssembler object is instantiated, then the list of INDRA Statements is added to the assembler. Finally, the assembler’s make_model method is called which assembles the model and returns it, while also storing it in pa.model. Notice that we are using policies=’two_step’ as an argument of make_model. This directs the assemble to use rules in which enzymatic catalysis is modeled as a two-step process in which enzyme and substrate first reversibly bind and the enzyme-substrate complex produces and releases a product irreversibly.

In [5]: from indra.assemblers.pysb_assembler import PysbAssembler

In [6]: pa = PysbAssembler()

In [7]: pa.add_statements(tp.statements)

In [8]: pa.make_model(policies='two_step')
ImportError                               Traceback (most recent call last)
<ipython-input-8-86a5e2ac6f7f> in <module>()
----> 1 pa.make_model(policies='two_step')

~/checkouts/ in make_model(self, policies, initial_conditions, reverse_effects)
    797         # Iterate over the statements to generate rules
--> 798         self._assemble()
    799         # Add initial conditions
    800         if initial_conditions:

~/checkouts/ in _assemble(self)
    999         for stmt in self.statements:
   1000             if _is_whitelisted(stmt):
-> 1001                 self._dispatch(stmt, 'assemble', self.model, self.agent_set)

~/checkouts/ in _dispatch(self, stmt, stage, *args)
    987                 raise UnknownPolicyError('%s function %s not defined' %
    988                                          (stage, func_name))
--> 989         return func(stmt, *args)
    991     def _monomers(self):

~/checkouts/ in modification_assemble_two_step(stmt, model, agent_set)
   1347     r = Rule(rule_name,
   1348         enz_unbound() + \
-> 1349         sub_pattern(**{mod_site: unmod_site_state, enz_bs: None}) >>
   1350         enz_bound() % \
   1351         sub_pattern(**{mod_site: unmod_site_state, enz_bs: 1}),

~/checkouts/ in __add__(self, other)
    465     def __add__(self, other):
    466         if isinstance(other, MonomerPattern):
--> 467             return ReactionPattern([ComplexPattern([self], None), ComplexPattern([other], None)])
    468         if isinstance(other, ComplexPattern):
    469             return ReactionPattern([ComplexPattern([self], None), other])

~/checkouts/ in __init__(self, complex_patterns)
    914     def __init__(self, complex_patterns):
    915         self.complex_patterns = complex_patterns
--> 916         from pysb.pattern import check_dangling_bonds
    917         check_dangling_bonds(self)

~/checkouts/ in <module>()
      3     ReactionPattern, ANY, as_complex_pattern, DanglingBondError
      4 import networkx as nx
----> 5 from networkx.algorithms.isomorphism.vf2userfunc import GraphMatcher
      6 from networkx.algorithms.isomorphism import categorical_node_match
      7 import numpy as np

ImportError: No module named 'networkx.algorithms.isomorphism'; 'networkx.algorithms' is not a package

At this point pa.model contains a PySB model object with 3 monomers,

In [9]: for monomer in pa.model.monomers:
   ...:     print(monomer)
Monomer('MAPK1', ['phospho', 'map2k1', 'dusp6'], {'phospho': ['u', 'p']})
Monomer('DUSP6', ['mapk1'])
Monomer('MAP2K1', ['mapk1'])

6 rules,

In [10]: for rule in pa.model.rules:
   ....:     print(rule)

and 9 parameters (6 kinetic rate constants and 3 total protein amounts) that are set to nominal but plausible values,

In [11]: for parameter in pa.model.parameters:
   ....:     print(parameter)
Parameter('kf_mm_bind_1', 1e-06)
Parameter('kr_mm_bind_1', 0.1)
Parameter('kc_mm_phosphorylation_1', 100.0)

The model also contains extensive annotations that tie the monomers to database identifiers and also annotate the semantics of each component of each rule.

In [12]: for annotation in pa.model.annotations:
   ....:     print(annotation)
Annotation(MAPK1, '', 'is')
Annotation(MAPK1, '', 'is')
Annotation(MAPK1, '', 'is')
Annotation(DUSP6, '', 'is')
Annotation(DUSP6, '', 'is')
Annotation(DUSP6, '', 'is')
Annotation(MAP2K1, '', 'is')
Annotation(MAP2K1, '', 'is')
Annotation(MAP2K1, '', 'is')

Exporting the model into other common formats

From the assembled PySB format it is possible to export the model into other common formats such as SBML, BNGL and Kappa. One can also generate a Matlab or Mathematica script with ODEs corresponding to the model.


One can also pass a file name argument to the export_model function to save the exported model directly into a file:

pa.export_model('sbml', 'example_model.sbml')