Skip to content

Commit db509d3

Browse files
committed
Merge branch 'v0.1.0'
2 parents 26eed5e + f8be77c commit db509d3

10 files changed

+899
-1
lines changed

README.md

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,150 @@
11
# swarm_it
2-
Utility to help setup PSO runs for PySB models.
2+
3+
![Python version badge](https://img.shields.io/badge/python-3.6-blue.svg)
4+
[![license](https://img.shields.io/github/license/LoLab-VU/swarm_it.svg)](LICENSE)
5+
![version](https://img.shields.io/badge/version-0.1.0-orange.svg)
6+
[![release](https://img.shields.io/github/release-pre/LoLab-VU/swarm_it.svg)](https://github.com/LoLab-VU/swarm_it/releases/tag/v0.1.0)
7+
8+
**swarm_it** is a python utility designed to abstract away some of the effort in setting up Particle Swarm Optimization (PSO)-based calibrations of biological models in the [PySB](http://pysb.org/) format using [simplePSO](https://github.com/LoLab-VU/ParticleSwarmOptimization).
9+
10+
------
11+
12+
# Install
13+
14+
| **! Warning** |
15+
| :--- |
16+
| swarm_it is still under heavy development and may rapidly change. |
17+
18+
**swarm_it** installs as the `swarm_it` package. It is compatible (i.e., tested) with Python 3.6.
19+
20+
Note that `swarm_it` has the following core dependencies:
21+
* [NumPy](http://www.numpy.org/)
22+
* [SciPy](https://www.scipy.org/)
23+
* [simplePSO](https://github.com/LoLab-VU/ParticleSwarmOptimization) version 1.0
24+
* [PySB](http://pysb.org/)
25+
26+
### pip install
27+
You can install the latest release of the `swarm_it` package using `pip` sourced from the GitHub repo:
28+
```
29+
pip install -e git+https://github.com/LoLab-VU/[email protected]#egg=swarm_it
30+
```
31+
However, this will not automatically install the core dependencies. You will have to do that separately:
32+
```
33+
pip install numpy scipy simplepso
34+
```
35+
See the [http://pysb.org/download](http://pysb.org/download) page for instructions on installing PySB.
36+
37+
------
38+
39+
# License
40+
41+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
42+
43+
------
44+
45+
# Documentation and Usage
46+
47+
### Quick Overview
48+
swarm_it is a utility that helps generate a simplePSO run script or simplepso.pso.PSO objects for a PySB model.
49+
50+
#### Commmand line use
51+
swarm_it can be used as a command line utility to generate a template Particle Swarm Optimization run script for a PySB model. swarm_it reads the model file, imports and pulls out all the kinetic parameters, and then writes out a simplepso run script for that model. Users can then edit edit the generated template script to load any data and modify the cost function.
52+
53+
Run swarm_it from the command line with following format:
54+
```
55+
python -m swarm_it model.py output_path
56+
```
57+
where output_path is the directory/folder location where you want the generated script to be saved as "simplepso_model_name.py".
58+
59+
The command line version of swarm_it also has support for setting the calibrated model parameters via an instance of [SwarmParam](https://github.com/LoLab-VU/swarm_it/tree/master#swarmparam) defined along with the model.
60+
61+
62+
#### Progammatic use via the SwarmIt class
63+
The swarm_it utility can be used progammatically via the SwarmIt
64+
class. It's importable from swarm_it:
65+
```python
66+
from swarm_it import SwarmIt
67+
```
68+
The SwarmIt class can build an instance of a simplepso.pso.PSO object.
69+
Here's a faux minimal example:
70+
```python
71+
from my_pysb_model import model as my_model
72+
from swarm_it import SwarmIt
73+
import numpy as np
74+
75+
timespan = np.linspace(0., 10., 10)
76+
data = np.load('my_data.npy')
77+
data_sd = np.load('my_data_sd.npy')
78+
observable_data = dict()
79+
time_idxs = list(range(len(timespan)))
80+
observable_data['my_observable'] = (data, data_sd, time_idxs)
81+
# Initialize the SwarmIt instance with the model details.
82+
swarmit = SwarmIt(my_model, observable_data, timespan)
83+
# Now build the PSO object. -- All inputs are
84+
# optional keyword arguments.
85+
pso = swarmit(pso_kwargs=dict({'save_sampled':False, 'verbose':True}),
86+
cost_type='norm_logpdf')
87+
# Then you can run it.
88+
num_particles = 20
89+
num_iterations = 50
90+
pso.run(num_particles, num_iterations)
91+
print("best_theta: ",pso.best)
92+
```
93+
94+
SwarmIt constructs the PSO object to sample all of a model's kinetic rate parameters. It assumes that the priors are uniform with size 4 orders of magnitude and centered on the values defined in the model.
95+
96+
In addition, SwarmIt crrently has three pre-defined loglikelihood functions with different estimators, specified with the keyword parameter cost_type:
97+
```python
98+
# Now build the PSO object.
99+
pso = swarmit(cost_type='mse')
100+
```
101+
The options are
102+
* 'norm_logpdf'=> (default) Compute the cost a the negative sum of normal distribution logpdf's over each data point
103+
* 'mse'=>Compute the cost using the mean squared error estimator
104+
* 'sse'=>Compute the cost using the sum of squared errors estimator.
105+
106+
Each of these functions computes the cost estimate using the timecourse output of a model simulation for each observable defined in the `observable_data` dictionary.
107+
If you want to use a different or more complicated likelihood function with SwarmIt then you'll need to subclass it and either override one of the existing cost functions or define a new one.
108+
109+
#### SwarmParam
110+
The swarm_it module has a built-in helper class, SwarmParam, which can be used in conjunction of with SwarmIt class. SwarmParam can be used at the level of PySB model definition to log which parameters to include in
111+
a Particle Swarm Optimization run, or it can be used after model definition at as long as it is defined before defining a SwarmIt object. It can be imported from swarm_it:
112+
```python
113+
from swarm_it import SwarmParam
114+
```
115+
It is passed at instantiation to the SwarmIt class, which uses it
116+
to build the set of parameters to use, their staring PSO position and bounds, as well as the parameter mask for the cost function.
117+
118+
Note that if you flag a parameter for sampling without setting sampling bounds, SwarmParam will by default assign the parameter bounds centered on the parameter's value (as defined in the model) with a width of 4 orders of magnitude.
119+
120+
### Examples
121+
Additional example scripts that show how to setup and launch PSO runs using **swarm_it** can be found under [examples](./examples).
122+
123+
------
124+
125+
# Contact
126+
127+
To report problems or bugs please open a
128+
[GitHub Issue](https://github.com/LoLab-VU/swarm_it/issues). Additionally, any
129+
comments, suggestions, or feature requests for **swarm_it** can also be submitted as a
130+
[GitHub Issue](https://github.com/LoLab-VU/swarm_it/issues).
131+
132+
------
133+
134+
# Citing
135+
136+
If you use the **swarm_it** software in your research, please cite the GitHub repo.
137+
138+
Also, please cite the following references as appropriate for software used with/via **swarm_it**:
139+
140+
#### Packages from the SciPy ecosystem
141+
142+
This includes NumPy and SciPy for which references can be obtained from:
143+
https://www.scipy.org/citing.html
144+
145+
#### simplePSO
146+
The simplePSO reference can be exported from its Zenodo DOI entry:
147+
[10.5281/zenodo.2612912](https://doi.org/10.5281/zenodo.2612912)
148+
149+
#### PySB
150+
1. Lopez, C. F., Muhlich, J. L., Bachman, J. A. & Sorger, P. K. Programming biological models in Python using PySB. Mol Syst Biol 9, (2013). doi:[10.1038/msb.2013.1](dx.doi.org/10.1038/msb.2013.1)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'''
2+
Dimerization model:
3+
A + A <> AA
4+
'''
5+
from pysb import Model, Parameter, Monomer, Rule, Observable, Initial
6+
7+
8+
Model()
9+
#######
10+
V = 100.
11+
#######
12+
Parameter('kf', 0.001)
13+
Parameter('kr', 1.)
14+
15+
16+
Monomer('A', ['d'])
17+
18+
# Rules
19+
Rule('ReversibleBinding', A(d=None) + A(d=None) | A(d=1) % A(d=1), kf, kr)
20+
21+
#Observables
22+
Observable("A_free", A(d=None))
23+
Observable("A_dimer", A(d=1) % A(d=1))
24+
25+
# Inital Conditions
26+
Parameter("A_0", 20.*V)
27+
Initial(A(d=None), A_0)
Binary file not shown.
Binary file not shown.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'''
2+
Dimerization model:
3+
A + A <> AA
4+
'''
5+
from pysb import Model, Parameter, Monomer, Rule, Observable, Initial
6+
import numpy as np
7+
from swarm_it import SwarmParam
8+
9+
swarm_param = SwarmParam()
10+
11+
Model()
12+
#######
13+
V = 100.
14+
#######
15+
swarm_param(Parameter('kf', 0.001))
16+
swarm_param(Parameter('kr', 1.), loc=np.log10(1.)-1., width=2.)
17+
18+
19+
Monomer('A', ['d'])
20+
21+
# Rules
22+
Rule('ReversibleBinding', A(d=None) + A(d=None) | A(d=1) % A(d=1), kf, kr)
23+
24+
#Observables
25+
Observable("A_free", A(d=None))
26+
Observable("A_dimer", A(d=1) % A(d=1))
27+
28+
# Inital Conditions
29+
Parameter("A_0", 20.*V)
30+
Initial(A(d=None), A_0)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'''
2+
Generated by swarm_it
3+
simplePSO run script for dimerization_model.py
4+
'''
5+
from pysb.simulator import ScipyOdeSimulator
6+
import numpy as np
7+
from scipy.stats import norm
8+
from simplepso.pso import PSO
9+
from dimerization_model import model
10+
11+
# Initialize PySB solver object for running simulations.
12+
# USER-Adjust: simulation timespan should match experimental data.
13+
tspan = np.linspace(0,10, num=100)
14+
solver = ScipyOdeSimulator(model, tspan=tspan)
15+
parameters_idxs = [0, 1]
16+
calibrate_mask = [True, True, False]
17+
param_values = np.array([p.value for p in model.parameters])
18+
19+
# USER-Set: must add commands to import/load any experimental
20+
# data for use in the likelihood function!
21+
experiments_avg = np.load()
22+
experiments_sd = np.load()
23+
like_data = norm(loc=experiments_avg, scale=experiments_sd)
24+
# USER-Set: must appropriately update cost function!
25+
def cost(position):
26+
Y=np.copy(position)
27+
param_values[calibrate_mask] = 10 ** Y
28+
sim = solver.run(param_values=param_values).all
29+
logp_data = np.sum(like_data.logpdf(sim['observable']))
30+
if np.isnan(logp_data):
31+
logp_data = np.inf
32+
return -logp_data,
33+
34+
# Setup the particle swarm optimization run
35+
36+
# Set the number of particles in the swarm.
37+
num_particles = 25
38+
# Set the number of iterations for PSO run.
39+
num_iterations = 50
40+
# Construct the optimizer
41+
pso = PSO(save_sampled=False,
42+
verbose=True,
43+
num_procs=1)
44+
pso.set_cost_function(cost)
45+
starting_position = param_values[calibrate_mask]
46+
pso.set_start_position(starting_position)
47+
# allows particles to move +/- 2 orders of magnitude
48+
pso.set_bounds(2)
49+
# sets maximum speed that a particle can travel
50+
pso.set_speed(-.25, .25)
51+
# run it
52+
pso.run(num_particles,
53+
num_iterations,
54+
stop_threshold=1e-5)
55+
print("Best parameters: ",pso.best)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
PSO run script for dimerization_model.py using swarm_it
3+
classes.
4+
"""
5+
from dimerization_model_swarmit import model, swarm_param
6+
import numpy as np
7+
8+
from swarm_it import SwarmIt
9+
10+
if __name__ == '__main__':
11+
# Initialize PySB solver object for running simulations.
12+
# Simulation timespan should match experimental data.
13+
tspan = np.linspace(0,1, num=51)
14+
15+
# USER must add commands to import/load any experimental
16+
# data for use in the likelihood function!
17+
experiments_avg = np.load('dimerization_model_dimer_data.npy')
18+
experiments_sd = np.load('dimerization_model_dimer_sd.npy')
19+
20+
# Setup the PSO run
21+
observable_data = dict()
22+
time_idxs = list(range(len(tspan)))
23+
observable_data['A_dimer'] = tuple((experiments_avg, experiments_sd, time_idxs))
24+
# Initialize the GAlibrateIt instance with the model details.
25+
swarmit = SwarmIt(model, observable_data, tspan, swarm_param=swarm_param)
26+
# Now build the GAO object. -- All inputs are
27+
# optional keyword arguments.
28+
pso = swarmit(pso_kwargs=dict({'save_sampled':False, 'verbose':True}),
29+
cost_type='norm_logpdf')
30+
31+
# run it
32+
num_particles = 20
33+
num_iterations = 50
34+
pso.run(num_particles, num_iterations)
35+
print("best_theta: ",pso.best)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'''
2+
Generated by swarm_it
3+
simplePSO run script for dimerization_model_swarmit.py
4+
'''
5+
from pysb.simulator import ScipyOdeSimulator
6+
import numpy as np
7+
from scipy.stats import norm
8+
from simplepso.pso import PSO
9+
from dimerization_model_swarmit import model,swarm_param
10+
11+
# Initialize PySB solver object for running simulations.
12+
# USER-Adjust: simulation timespan should match experimental data.
13+
tspan = np.linspace(0,10, num=100)
14+
solver = ScipyOdeSimulator(model, tspan=tspan)
15+
parameters_idxs = [0, 1]
16+
calibrate_mask = [True, True, False]
17+
param_values = np.array([p.value for p in model.parameters])
18+
19+
# USER-Set: must add commands to import/load any experimental
20+
# data for use in the likelihood function!
21+
experiments_avg = np.load()
22+
experiments_sd = np.load()
23+
like_data = norm(loc=experiments_avg, scale=experiments_sd)
24+
# USER-Set: must appropriately update cost function!
25+
def cost(position):
26+
Y=np.copy(position)
27+
param_values[calibrate_mask] = 10 ** Y
28+
sim = solver.run(param_values=param_values).all
29+
logp_data = np.sum(like_data.logpdf(sim['observable']))
30+
if np.isnan(logp_data):
31+
logp_data = np.inf
32+
return -logp_data,
33+
34+
# Setup the particle swarm optimization run
35+
36+
# Set the number of particles in the swarm.
37+
num_particles = 25
38+
# Set the number of iterations for PSO run.
39+
num_iterations = 50
40+
# Construct the optimizer
41+
pso = PSO(save_sampled=False,
42+
verbose=True,
43+
num_procs=1)
44+
pso.set_cost_function(cost)
45+
starting_position = swarm_param.centers()
46+
pso.set_start_position(starting_position)
47+
pso.set_bounds(lower=swarm_param.lower(), upper=swarm_param.upper())
48+
# sets maximum speed that a particle can travel
49+
pso.set_speed(-.25, .25)
50+
# run it
51+
pso.run(num_particles,
52+
num_iterations,
53+
stop_threshold=1e-5)
54+
print("Best parameters: ",pso.best)

setup.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from distutils.core import setup
2+
3+
setup(name='swarm_it',
4+
version='0.1.0',
5+
description='Utility to help setup PSO runs for PySB models.',
6+
author='Blake A. Wilson',
7+
author_email='[email protected]',
8+
url='https://github.com/LoLab-VU/swarm_it',
9+
packages=['swarm_it'],
10+
license='MIT',
11+
keywords=['particle swarm optimization', 'model calibration', 'parameter estimation', 'pysb']
12+
)

0 commit comments

Comments
 (0)