-
Notifications
You must be signed in to change notification settings - Fork 34
Generic stochastic model #1417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic stochastic model #1417
Changes from 21 commits
4d4ef3c
556e560
1e99263
74c8b2e
97d737d
1850b2b
b080f09
52835a3
5098400
cfc6c2b
6d3b874
acc6b9d
24d1aa8
0a1ffdd
14ed81a
4122bcb
f158670
c4edd3f
362567d
4b12e0e
5403208
7f69fda
a0d4f24
99a56b3
7c4d14f
d14667d
27453ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| *********************** | ||
| Stochastic Toy Problems | ||
| *********************** | ||
|
|
||
| The `stochastic` module provides toy :class:`models<pints.toy.stochastic.MarkovJumpModel>`, | ||
| :class:`distributions<pints.LogPrior>` and | ||
| :class:`error measures<pints.ErrorMeasure>` that can be used for tests and in | ||
| examples. | ||
|
|
||
|
|
||
| .. toctree:: | ||
|
|
||
| markov_jump_model | ||
| stochastic_degradation_model | ||
| stochastic_michaelis_menten_model | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| ***************** | ||
| Markov Jump Model | ||
| ***************** | ||
|
|
||
| .. currentmodule:: pints.toy.stochastic | ||
|
|
||
| .. autoclass:: MarkovJumpModel |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| ********************************* | ||
| Stochastic Michaelis Menten model | ||
| ********************************* | ||
|
|
||
| .. currentmodule:: pints.toy.stochastic | ||
|
|
||
| .. autoclass:: MichaelisMentenModel |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -117,6 +117,7 @@ relevant code. | |
| - [SIR Epidemiology model](./toy/model-sir.ipynb) | ||
| - [Stochastic Degradation model](./toy/model-stochastic-degradation.ipynb) | ||
| - [Stochastic Logistic model](./toy/model-stochastic-logistic-growth.ipynb) | ||
| - [Michaelis Menten model](./toy/model-stochastic-michaelis-menten.ipynb) | ||
|
||
|
|
||
| ### Distributions | ||
| - [Annulus](./toy/distribution-annulus.ipynb) | ||
|
|
||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Tests if the markov jump model works. | ||
| # | ||
| # This file is part of PINTS (https://github.com/pints-team/pints/) which is | ||
| # released under the BSD 3-clause license. See accompanying LICENSE.md for | ||
| # copyright notice and full license details. | ||
| # | ||
| import unittest | ||
| import numpy as np | ||
| from pints.toy.stochastic import DegradationModel | ||
|
|
||
|
|
||
| class TestMarkovJumpModel(unittest.TestCase): | ||
| """ | ||
| Tests if the markov jump model works using | ||
| the degradation model. | ||
| """ | ||
| def test_start_with_zero(self): | ||
| # Test the special case where the initial molecule count is zero | ||
| model = DegradationModel(0) | ||
| times = [0, 1, 2, 100, 1000] | ||
| parameters = [0.1] | ||
| values = model.simulate(parameters, times) | ||
| self.assertEqual(len(values), len(times)) | ||
| self.assertTrue(np.all(values == np.zeros(5))) | ||
|
|
||
| def test_start_with_twenty(self): | ||
| # Run small simulation | ||
| model = DegradationModel(20) | ||
| times = [0, 1, 2, 100, 1000] | ||
| parameters = [0.1] | ||
| values = model.simulate(parameters, times) | ||
| self.assertEqual(len(values), len(times)) | ||
| self.assertEqual(values[0], 20) | ||
| self.assertEqual(values[-1], 0) | ||
| self.assertTrue(np.all(values[1:] <= values[:-1])) | ||
|
|
||
| def test_simulate(self): | ||
| times = np.linspace(0, 100, 101) | ||
| model = DegradationModel(20) | ||
| time, mol_count = model.simulate_raw([0.1], 100) | ||
| values = model.interpolate_mol_counts(time, mol_count, times) | ||
| self.assertTrue(len(time), len(mol_count)) | ||
| # Test output of Gillespie algorithm | ||
| expected = np.array([[x] for x in range(20, -1, -1)]) | ||
| self.assertTrue(np.all(mol_count == expected)) | ||
|
|
||
| # Check simulate function returns expected values | ||
| self.assertTrue(np.all(values[np.where(times < time[1])] == 20)) | ||
|
|
||
| # Check interpolation function works as expected | ||
| temp_time = np.array([np.random.uniform(time[0], time[1])]) | ||
| self.assertEqual( | ||
| model.interpolate_mol_counts(time, mol_count, temp_time)[0], | ||
| 20) | ||
| temp_time = np.array([np.random.uniform(time[1], time[2])]) | ||
| self.assertEqual( | ||
| model.interpolate_mol_counts(time, mol_count, temp_time)[0], | ||
| 19) | ||
|
|
||
| def test_errors(self): | ||
| model = DegradationModel(20) | ||
| # parameters, times cannot be negative | ||
| times = np.linspace(0, 100, 101) | ||
| parameters = [-0.1] | ||
| self.assertRaises(ValueError, model.simulate, parameters, times) | ||
|
|
||
| times_2 = np.linspace(-10, 10, 21) | ||
| parameters_2 = [0.1] | ||
| self.assertRaises(ValueError, model.simulate, parameters_2, times_2) | ||
|
|
||
| # this model should have 1 parameter | ||
| parameters_3 = [0.1, 1] | ||
| self.assertRaises(ValueError, model.simulate, parameters_3, times) | ||
|
|
||
| # Initial value can't be negative | ||
| self.assertRaises(ValueError, DegradationModel, -1) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,116 +1,88 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Tests if the stochastic degradation (toy) model works. | ||
| # Tests if the degradation (toy) model works. | ||
| # | ||
| # This file is part of PINTS (https://github.com/pints-team/pints/) which is | ||
| # released under the BSD 3-clause license. See accompanying LICENSE.md for | ||
| # copyright notice and full license details. | ||
| # | ||
| import unittest | ||
| import numpy as np | ||
| import pints | ||
| import pints.toy | ||
| from pints.toy import StochasticDegradationModel | ||
| from pints.toy.stochastic import DegradationModel | ||
|
|
||
|
|
||
| class TestStochasticDegradationModel(unittest.TestCase): | ||
| class TestDegradationModel(unittest.TestCase): | ||
| """ | ||
| Tests if the stochastic degradation (toy) model works. | ||
| Tests if the degradation (toy) model works. | ||
| """ | ||
| def test_start_with_zero(self): | ||
| # Test the special case where the initial molecule count is zero | ||
| model = StochasticDegradationModel(0) | ||
| times = [0, 1, 2, 100, 1000] | ||
| parameters = [0.1] | ||
| values = model.simulate(parameters, times) | ||
| self.assertEqual(len(values), len(times)) | ||
| self.assertTrue(np.all(values == np.zeros(5))) | ||
|
|
||
| def test_start_with_twenty(self): | ||
| # Run small simulation | ||
| model = pints.toy.StochasticDegradationModel(20) | ||
| times = [0, 1, 2, 100, 1000] | ||
| parameters = [0.1] | ||
| values = model.simulate(parameters, times) | ||
| self.assertEqual(len(values), len(times)) | ||
| self.assertEqual(values[0], 20) | ||
| self.assertEqual(values[-1], 0) | ||
| self.assertTrue(np.all(values[1:] <= values[:-1])) | ||
| def test_n_parameters(self): | ||
| x_0 = 20 | ||
| model = DegradationModel(x_0) | ||
| self.assertEqual(model.n_parameters(), 1) | ||
|
|
||
| def test_simulation_length(self): | ||
| x_0 = 20 | ||
| model = DegradationModel(x_0) | ||
| times = np.linspace(0, 1, 100) | ||
| k = [0.1] | ||
| values = model.simulate(k, times) | ||
| self.assertEqual(len(values), 100) | ||
|
|
||
| def test_propensities(self): | ||
| x_0 = 20 | ||
| k = [0.1] | ||
| model = DegradationModel(x_0) | ||
| self.assertTrue( | ||
| np.allclose( | ||
| model._propensities([x_0], k), | ||
| np.array([2.0]))) | ||
|
|
||
| def test_suggested(self): | ||
| model = pints.toy.StochasticDegradationModel(20) | ||
| model = DegradationModel(20) | ||
| times = model.suggested_times() | ||
| parameters = model.suggested_parameters() | ||
| self.assertTrue(len(times) == 101) | ||
| self.assertTrue(parameters > 0) | ||
|
|
||
| def test_simulate(self): | ||
| times = np.linspace(0, 100, 101) | ||
| model = StochasticDegradationModel(20) | ||
| time, mol_count = model.simulate_raw([0.1]) | ||
| values = model.interpolate_mol_counts(time, mol_count, times) | ||
| self.assertTrue(len(time), len(mol_count)) | ||
| # Test output of Gillespie algorithm | ||
| self.assertTrue(np.all(mol_count == np.array(range(20, -1, -1)))) | ||
|
|
||
| # Check simulate function returns expected values | ||
| self.assertTrue(np.all(values[np.where(times < time[1])] == 20)) | ||
|
|
||
| # Check interpolation function works as expected | ||
| temp_time = np.array([np.random.uniform(time[0], time[1])]) | ||
| self.assertEqual( | ||
| model.interpolate_mol_counts(time, mol_count, temp_time)[0], | ||
| 20) | ||
| temp_time = np.array([np.random.uniform(time[1], time[2])]) | ||
| self.assertEqual( | ||
| model.interpolate_mol_counts(time, mol_count, temp_time)[0], | ||
| 19) | ||
|
|
||
| def test_mean_variance(self): | ||
| # test mean | ||
| model = pints.toy.StochasticDegradationModel(10) | ||
| model = DegradationModel(10) | ||
| v_mean = model.mean([1], [5, 10]) | ||
| self.assertEqual(v_mean[0], 10 * np.exp(-5)) | ||
| self.assertEqual(v_mean[1], 10 * np.exp(-10)) | ||
|
|
||
| model = pints.toy.StochasticDegradationModel(20) | ||
| model = DegradationModel(20) | ||
| v_mean = model.mean([5], [7.2]) | ||
| self.assertEqual(v_mean[0], 20 * np.exp(-7.2 * 5)) | ||
|
|
||
| # test variance | ||
| model = pints.toy.StochasticDegradationModel(10) | ||
| model = DegradationModel(10) | ||
| v_var = model.variance([1], [5, 10]) | ||
| self.assertEqual(v_var[0], 10 * (np.exp(5) - 1.0) / np.exp(10)) | ||
| self.assertAlmostEqual(v_var[1], 10 * (np.exp(10) - 1.0) / np.exp(20)) | ||
|
|
||
| model = pints.toy.StochasticDegradationModel(20) | ||
| model = DegradationModel(20) | ||
| v_var = model.variance([2.0], [2.0]) | ||
| self.assertAlmostEqual(v_var[0], 20 * (np.exp(4) - 1.0) / np.exp(8)) | ||
|
|
||
| def test_errors(self): | ||
| model = pints.toy.StochasticDegradationModel(20) | ||
| model = DegradationModel(20) | ||
| # parameters, times cannot be negative | ||
| times = np.linspace(0, 100, 101) | ||
| parameters = [-0.1] | ||
| self.assertRaises(ValueError, model.simulate, parameters, times) | ||
| self.assertRaises(ValueError, model.mean, parameters, times) | ||
| self.assertRaises(ValueError, model.variance, parameters, times) | ||
|
|
||
| times_2 = np.linspace(-10, 10, 21) | ||
| parameters_2 = [0.1] | ||
| self.assertRaises(ValueError, model.simulate, parameters_2, times_2) | ||
| self.assertRaises(ValueError, model.mean, parameters_2, times_2) | ||
| self.assertRaises(ValueError, model.variance, parameters_2, times_2) | ||
|
|
||
| # this model should have 1 parameter | ||
| parameters_3 = [0.1, 1] | ||
| self.assertRaises(ValueError, model.simulate, parameters_3, times) | ||
| self.assertRaises(ValueError, model.mean, parameters_3, times) | ||
| self.assertRaises(ValueError, model.variance, parameters_3, times) | ||
|
|
||
| # Initial value can't be negative | ||
| self.assertRaises(ValueError, pints.toy.StochasticDegradationModel, -1) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Tests if the Michaelis Menten (toy) model works. | ||
| # | ||
| # This file is part of PINTS (https://github.com/pints-team/pints/) which is | ||
| # released under the BSD 3-clause license. See accompanying LICENSE.md for | ||
| # copyright notice and full license details. | ||
| # | ||
| import unittest | ||
| import numpy as np | ||
| from pints.toy.stochastic import MichaelisMentenModel | ||
|
|
||
|
|
||
| class TestMichaelisMentenModel(unittest.TestCase): | ||
| """ | ||
| Tests if the Michaelis Menten (toy) model works. | ||
| """ | ||
| def test_n_parameters(self): | ||
| x_0 = [1e4, 2e3, 2e4, 0] | ||
| model = MichaelisMentenModel(x_0) | ||
| self.assertEqual(model.n_parameters(), 3) | ||
|
|
||
| def test_simulation_length(self): | ||
| x_0 = [1e4, 2e3, 2e4, 0] | ||
| model = MichaelisMentenModel(x_0) | ||
| times = np.linspace(0, 1, 100) | ||
| k = [1e-5, 0.2, 0.2] | ||
| values = model.simulate(k, times) | ||
| self.assertEqual(len(values), 100) | ||
|
|
||
| def test_propensities(self): | ||
| x_0 = [1e4, 2e3, 2e4, 0] | ||
| k = [1e-5, 0.2, 0.2] | ||
| model = MichaelisMentenModel(x_0) | ||
| self.assertTrue( | ||
| np.allclose( | ||
| model._propensities(x_0, k), | ||
| np.array([200.0, 4000.0, 4000.0]))) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess initially it's just models?