Skip to content

Commit

Permalink
Merge pull request #229 from dianakolusheva/gromet
Browse files Browse the repository at this point in the history
EMMAA to GroMEt
  • Loading branch information
bgyori committed Jun 8, 2021
2 parents 8243b60 + cb470df commit 7679ba5
Show file tree
Hide file tree
Showing 7 changed files with 16,435 additions and 6 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ jobs:
cd ../indralab_web_templates
pip install .
cd ../..
git clone https://github.com/ml4ai/automates.git
cd automates
git checkout claytonm/gromet
cd ..
pip install boto3 jsonpickle pygraphviz fnvhash inflection pybel==0.15 flask_jwt_extended==3.25.0 gilda tweepy nose coverage moto[iam] sqlalchemy_utils termcolor flask-cors
pip install --no-dependencies .
pip install -U sqlalchemy==1.3.23
Expand All @@ -69,7 +73,7 @@ jobs:
export AWS_DEFAULT_REGION='us-east-1'
export NOSEATTR="!notravis"
export NOSEATTR=$(if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then echo $NOSEATTR,!nonpublic; else echo $NOSEATTR; fi)
export PYTHONPATH=$PYTHONPATH:`pwd`/covid-19:`pwd`/kappy:`pwd`/indra_world
export PYTHONPATH=$PYTHONPATH:`pwd`/covid-19:`pwd`/kappy:`pwd`/indra_world:`pwd`/automates/scripts
export BNGPATH=`pwd`/BioNetGen-2.4.0
export INDRA_WM_CACHE="."
nosetests -v -a $NOSEATTR emmaa/tests/test_s3.py
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,4 @@ emmaa/tests/test_query_delta.html
emmaa/tests/new_test_query_delta.txt
emmaa/tests/trips_output.xml
trips_output.xml
emmaa/tests/gromet_test.json
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ RUN git clone https://github.com/pagreene/pgcopy.git && \
# Install covid-19
RUN git clone https://github.com/indralab/covid-19.git

# Install automates
RUN git clone https://github.com/ml4ai/automates.git && \
cd automates && \
git checkout claytonm/gromet && \
cd ..

# Clone and install EMMAA
RUN pip install git+https://github.com/indralab/indra_db.git[misc] && \
pip install git+https://github.com/sorgerlab/bioagents.git && \
Expand Down
2 changes: 1 addition & 1 deletion doc/model_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ First level fields of config.json

- `export_formats` : list[str], optional
A list of formats the model can be exported to. Accepted values include:
`indranet`, `pybel`, `sbml`, `kappa`, `kappa_im`, `kappa_cm`,
`indranet`, `pybel`, `sbml`, `kappa`, `kappa_im`, `kappa_cm`, `gromet`,
`bngl`, `sbgn`, `pysb_flat`, `kappa_ui`. Note that `kappa_ui` option does
not generate a separate export file but adds a link to Kappa interactive
UI that uses model's kappa export (generated if `kappa` is in this list).
Expand Down
129 changes: 126 additions & 3 deletions emmaa/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import datetime
import pybel
from botocore.exceptions import ClientError
from sqlalchemy.sql.functions import mode
from indra.databases import ndex_client
from indra.literature import pubmed_client, elsevier_client, biorxiv_client
from indra.assemblers.cx import CxAssembler
Expand Down Expand Up @@ -542,10 +543,14 @@ def assemble_pysb(self, mode='local', bucket=EMMAA_BUCKET_NAME):
if mode == 's3':
for exp_f in self.export_formats:
if exp_f not in {'sbml', 'kappa', 'kappa_im', 'kappa_cm',
'bngl', 'sbgn', 'pysb_flat'}:
'bngl', 'sbgn', 'pysb_flat', 'gromet'}:
continue
fname = f'{exp_f}_{self.date_str}.{exp_f}'
pa.export_model(exp_f, fname)
elif exp_f == 'gromet':
fname = f'gromet_{self.date_str}.json'
pysb_to_gromet(pysb_model, self.name, fname)
else:
fname = f'{exp_f}_{self.date_str}.{exp_f}'
pa.export_model(exp_f, fname)
logger.info(f'Uploading {fname}')
client = get_s3_client(unsigned=False)
client.upload_file(fname, bucket,
Expand Down Expand Up @@ -922,3 +927,121 @@ def load_custom_grounding_map(model, bucket=EMMAA_BUCKET_NAME):
def get_search_term_names(model, bucket=EMMAA_BUCKET_NAME):
config = load_config_from_s3(model, bucket=bucket)
return [st['name'] for st in config['search_terms']]


def pysb_to_gromet(pysb_model, model_name, fname=None):
"""Convert PySB model to GroMEt object and save it to a JSON file.
Parameters
----------
pysb_model : pysb.Model
PySB model object.
model_name : str
A name of EMMAA model.
fname : Optional[str]
If given, the GroMEt will be dumped into JSON file.
Returns
-------
g : automates.script.gromet.gromet.Gromet
A GroMEt object built from PySB model.
"""
from gromet.gromet import Gromet, gromet_to_json, \
Junction, Wire, UidJunction, UidType, UidWire, Relation, \
UidBox, UidGromet, Literal, Val
from pysb import Parameter
from pysb.bng import generate_equations

generate_equations(pysb_model)

junctions = []
wires = []
# Get all species values
species_values = {}
for initial in pysb_model.initials:
ix = pysb_model.get_species_index(initial.pattern)
if initial.value:
species_values[ix] = Literal(
uid=None, type=UidType("T:Integer"),
value=Val(initial.value.value),
name=None, metadata=None)
# Store species names to refer later
species_nodes = [str(sp) for sp in pysb_model.species]
# Add all species junctions (uid and name are the same for now)
for ix, sp in enumerate(species_nodes):
junctions.append(Junction(uid=UidJunction(sp),
type=UidType('State'),
name=sp,
value=species_values.get(ix),
value_type=UidType('T:Integer'),
metadata=None))
# Add all rate junctions (uid and name are the same for now)
junctions += [Junction(uid=UidJunction(par.name),
type=UidType('Rate'),
name=par.name,
value=Literal(uid=None,
type=UidType("T:Float"),
value=Val(par.value),
name=None,
metadata=None),
value_type=UidType('T:Float'),
metadata=None)
for par in pysb_model.parameters]
# Add wires for each reaction
for rxn in pysb_model.reactions:
rate_params = [rate_term for rate_term in rxn['rate'].args
if isinstance(rate_term, Parameter)]
assert len(rate_params) == 1
rate_node = rate_params[0].name
# Add wires from reactant to rate
for reactant_ix in rxn['reactants']:
reactant = species_nodes[reactant_ix]
wires.append(Wire(uid=UidWire(f'{reactant}_{rate_node}'),
type=None,
value_type=None,
name=None,
value=None,
metadata=None,
src=UidJunction(reactant),
tgt=UidJunction(rate_node)))
# Add wires from rate to product
for prod_ix in rxn['products']:
prod = species_nodes[prod_ix]
wires.append(Wire(uid=UidWire(f'{rate_node}_{prod}'),
type=None,
value_type=None,
name=None,
value=None,
metadata=None,
src=UidJunction(rate_node),
tgt=UidJunction(prod)))
# Create relation
pnc = Relation(uid=UidBox(model_name),
type=UidType("PetriNetClassic"),
name=model_name,
ports=None,
# contents
junctions=[j.uid for j in junctions],
wires=[w.uid for w in wires],
boxes=None,
metadata=None)
boxes = [pnc]
# Create Gromet object
g = Gromet(
uid=UidGromet(f'{model_name}_pnc'),
name=model_name,
type=UidType("PetriNetClassic"),
root=pnc.uid,
types=None,
literals=None,
junctions=junctions,
ports=None,
wires=wires,
boxes=boxes,
variables=None,
metadata=None
)
# Optionally save Gromet to JSON file
if fname:
gromet_to_json(g, fname)
return g
22 changes: 21 additions & 1 deletion emmaa/tests/test_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
from indra.statements import Activation, ActivityCondition, Phosphorylation, \
Agent, Evidence
from emmaa.model import EmmaaModel
from emmaa.model import EmmaaModel, pysb_to_gromet
from emmaa.priors import SearchTerm
from emmaa.statements import EmmaaStatement

Expand Down Expand Up @@ -135,3 +135,23 @@ def test_papers():
# Add more paper_ids from reading
emmaa_model.add_paper_ids({'4567', '5678'}, id_type='TRID')
assert len(emmaa_model.paper_ids) == 5


def test_pysb_to_gromet():
from gromet.gromet import Gromet
emmaa_model = create_model()
pysb_model = emmaa_model.assemble_pysb()
gromet = pysb_to_gromet(pysb_model, 'test_model', 'gromet_test.json')
assert isinstance(gromet, Gromet)
# Test PySB properties are correctly represented in GroMEt
# Model species and parameters match junctions
assert len(pysb_model.species) == 5
assert len(pysb_model.parameters) == 5
assert len(gromet.junctions) == 10
assert len([j for j in gromet.junctions if j.type == 'State']) == 5
assert len([j for j in gromet.junctions if j.type == 'Rate']) == 5
# Number of wires match total number of reactants and products in reactions
assert len(pysb_model.reactions) == 2
assert sum([len(r['reactants']) + len(r['products'])
for r in pysb_model.reactions]) == 8
assert len(gromet.wires) == 8

0 comments on commit 7679ba5

Please sign in to comment.