From 9d79c08a82f2e9d959fc9603e9d546464bd5e947 Mon Sep 17 00:00:00 2001 From: LeonardSchmiester Date: Thu, 19 Sep 2024 11:32:44 +0200 Subject: [PATCH 01/12] Unit tests and code coverage (#47) * Added unit tests * Added GitHub actions workflow for tests and coverage report --- .github/workflows/deploy.yml | 1 - .github/workflows/tests.yml | 45 +++++++++++++++++++ setup.cfg | 8 +++- tests/test_get_optimization_bounds.py | 60 +++++++++++++++++++++++++ tests/test_mixture_id.py | 54 ++++++++++++++++++++++ tests/test_neg_log_likelihood.py | 48 ++++++++++++++++++++ tests/test_pop_expo.py | 65 +++++++++++++++++++++++++++ tests/test_rate_expo.py | 24 ++++++++++ 8 files changed, 302 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/tests.yml create mode 100644 tests/test_get_optimization_bounds.py create mode 100644 tests/test_mixture_id.py create mode 100644 tests/test_neg_log_likelihood.py create mode 100644 tests/test_pop_expo.py create mode 100644 tests/test_rate_expo.py diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 54e9f3b..1462f77 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,3 @@ - name: Deploy on: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..3c6a9bb --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,45 @@ +name: tests + +on: + push: + branches: + - main + pull_request: + branches: + - main + - develop + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + python-version: ['3.8', '3.9', '3.10'] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install .[dev] + + - name: Run tests with coverage + run: | + pytest --cov=pyphenopop --cov-report xml:coverage.xml + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + fail_ci_if_error: true diff --git a/setup.cfg b/setup.cfg index 6402003..561abbd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,11 +31,15 @@ install_requires = pandas >= 1.5.1 tqdm >= 4.64.1 - python_requires = >=3.8.0 - packages = find: +[options.extras_require] +dev = + pytest + pytest-cov + + [options.packages.find] include = pyphenopop* diff --git a/tests/test_get_optimization_bounds.py b/tests/test_get_optimization_bounds.py new file mode 100644 index 0000000..060af8b --- /dev/null +++ b/tests/test_get_optimization_bounds.py @@ -0,0 +1,60 @@ +import unittest +from pyphenopop.mixpopid import get_optimization_bounds + + +class TestGetOptimizationBounds(unittest.TestCase): + + def test_single_subpopulation(self): + num_subpop = 1 + bounds_model = { + 'alpha': (0.1, 1.0), + 'b': (0.1, 1.0), + 'E': (0.1, 1.0), + 'n': (0.1, 1.0) + } + bounds_sigma_low = (1e-05, 5000.0) + bounds_sigma_high = (1e-05, 10000.0) + + bnds, lb, ub = get_optimization_bounds(num_subpop, bounds_model, bounds_sigma_low, bounds_sigma_high) + + expected_bnds = ( + (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), + (1e-05, 10000.0), (1e-05, 5000.0) + ) + expected_lb = [0.1, 0.1, 0.1, 0.1, 1e-05, 1e-05] + expected_ub = [1.0, 1.0, 1.0, 1.0, 10000.0, 5000.0] + + self.assertEqual(bnds, expected_bnds) + self.assertEqual(lb, expected_lb) + self.assertEqual(ub, expected_ub) + + def test_multiple_subpopulations(self): + num_subpop = 3 + bounds_model = { + 'alpha': (0.1, 1.0), + 'b': (0.1, 1.0), + 'E': (0.1, 1.0), + 'n': (0.1, 1.0) + } + bounds_sigma_low = (1e-05, 5000.0) + bounds_sigma_high = (1e-05, 10000.0) + + bnds, lb, ub = get_optimization_bounds(num_subpop, bounds_model, bounds_sigma_low, bounds_sigma_high) + + expected_bnds = ( + (0.0, 0.5), (0.0, 0.5), + (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), + (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), + (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), (0.1, 1.0), + (1e-05, 10000.0), (1e-05, 5000.0) + ) + expected_lb = [0.0, 0.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 1e-05, 1e-05] + expected_ub = [0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 10000.0, 5000.0] + + self.assertEqual(bnds, expected_bnds) + self.assertEqual(lb, expected_lb) + self.assertEqual(ub, expected_ub) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_mixture_id.py b/tests/test_mixture_id.py new file mode 100644 index 0000000..8bcd46a --- /dev/null +++ b/tests/test_mixture_id.py @@ -0,0 +1,54 @@ +import unittest +import numpy as np +import pandas as pd +from pyphenopop.mixpopid import mixture_id +import os + + +class TestMixtureId(unittest.TestCase): + + def setUp(self): + # Create a temporary CSV file with mock data + self.data_file = 'test_data.csv' + data = np.random.rand(10*2, 3) # 10 timepoints, 3 concentrations + pd.DataFrame(data).to_csv(self.data_file, header=False, index=False) + + self.max_subpop = 3 + self.timepoints = np.linspace(0, 48, 10) # 10 timepoints from 0 to 48 hours + self.concentrations = np.linspace(0.01, 10, 3) # 3 concentrations from 0.01 to 10 + self.num_replicates = 2 + self.model = 'expo' + self.bounds_model = {'alpha': (0.0, 0.1), 'b': (0.0, 1.0), 'E': (1e-06, 15), 'n': (0.01, 10)} + self.bounds_sigma_high = (1e-05, 10000.0) + self.bounds_sigma_low = (1e-05, 5000.0) + self.optimizer_options = {'method': 'L-BFGS-B', 'options': {'disp': False, 'ftol': 1e-12}} + self.num_optim = 5 + self.selection_method = 'BIC' + + def test_mixture_id(self): + results = mixture_id( + self.max_subpop, + self.data_file, + self.timepoints, + self.concentrations, + self.num_replicates, + self.model, + self.bounds_model, + self.bounds_sigma_high, + self.bounds_sigma_low, + self.optimizer_options, + self.num_optim, + self.selection_method + ) + + self.assertIn('summary', results) + self.assertIn('estimated_num_populations', results['summary']) + self.assertIn('final_neg_log_likelihood', results['summary']) + self.assertIn('final_parameters', results['summary']) + + def tearDown(self): + os.remove(self.data_file) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_neg_log_likelihood.py b/tests/test_neg_log_likelihood.py new file mode 100644 index 0000000..f45027f --- /dev/null +++ b/tests/test_neg_log_likelihood.py @@ -0,0 +1,48 @@ +import unittest +import numpy as np +from pyphenopop.mixpopid import neg_log_likelihood + + +class TestNegLogLikelihood(unittest.TestCase): + + def setUp(self): + # Setting up common variables for tests + self.max_subpop = 2 + self.parameters = np.array([0.5, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]) + measurements = np.array([[[10, 20, 30], [15, 25, 35]], [[12, 22, 32], [18, 28, 38]]]) + measurements = measurements.reshape((3, 2, 2)) + self.measurements = measurements + self.concvec = np.array([0.1, 0.2]) + self.timevec = np.array([0, 24, 48]) + self.num_replicates = 2 + self.model = 'expo' + self.num_timepoints_high = np.array(1) + self.num_conc_high_noise = np.array(1) + self.num_noise_high = 1 + self.num_noise_low = 1 + + def test_neg_log_likelihood(self): + # Test the neg_log_likelihood function with valid inputs + result = neg_log_likelihood(self.max_subpop, self.parameters, self.measurements, self.concvec, self.timevec, + self.num_replicates, self.model, self.num_timepoints_high, self.num_conc_high_noise, + self.num_noise_high, self.num_noise_low) + self.assertIsInstance(result, float) + + def test_neg_log_likelihood_invalid_model(self): + # Test the neg_log_likelihood function with an invalid model + with self.assertRaises(NotImplementedError): + neg_log_likelihood(self.max_subpop, self.parameters, self.measurements, self.concvec, self.timevec, + self.num_replicates, 'invalid_model', self.num_timepoints_high, self.num_conc_high_noise, + self.num_noise_high, self.num_noise_low) + + def test_neg_log_likelihood_invalid_parameters(self): + # Test the neg_log_likelihood function with invalid parameters length + invalid_parameters = np.array([0.5, 0.1, 0.2, 0.3, 0.4]) + with self.assertRaises(KeyError): + neg_log_likelihood(self.max_subpop, invalid_parameters, self.measurements, self.concvec, self.timevec, + self.num_replicates, self.model, self.num_timepoints_high, self.num_conc_high_noise, + self.num_noise_high, self.num_noise_low) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_pop_expo.py b/tests/test_pop_expo.py new file mode 100644 index 0000000..14ac00e --- /dev/null +++ b/tests/test_pop_expo.py @@ -0,0 +1,65 @@ +import unittest +import numpy as np +from pyphenopop.mixpopid import pop_expo, rate_expo + + +class TestPopExpo(unittest.TestCase): + + def test_pop_expo_basic(self): + parameters = [0.1, 0.5, 1.0, 2.0] + concentrations = np.array([0.1, 1.0, 10.0]) + timepoints = np.array([0, 24, 48]) + expected_shape = (len(concentrations), len(timepoints)) + + result = pop_expo(parameters, concentrations, timepoints) + + self.assertEqual(result.shape, expected_shape) + self.assertTrue(np.all(result >= 0), "All population counts should be non-negative") + + def test_pop_expo_zero_timepoints(self): + parameters = [0.1, 0.5, 1.0, 2.0] + concentrations = np.array([0.1, 1.0, 10.0]) + timepoints = np.array([0]) + expected_shape = (len(concentrations), len(timepoints)) + + result = pop_expo(parameters, concentrations, timepoints) + + self.assertEqual(result.shape, expected_shape) + self.assertTrue(np.all(result == 1), "Population counts at time zero should be 1") + + def test_pop_expo_high_concentration(self): + parameters = [0.1, 0.5, 1.0, 2.0] + concentrations = np.array([1000.0]) + timepoints = np.array([0, 24, 48]) + expected_shape = (len(concentrations), len(timepoints)) + + result = pop_expo(parameters, concentrations, timepoints) + + self.assertEqual(result.shape, expected_shape) + self.assertTrue(np.all(result >= 0), "All population counts should be non-negative") + + def test_pop_expo_edge_case(self): + parameters = [0.0, 0.0, 0.0, 0.0] + concentrations = np.array([0.0]) + timepoints = np.array([0]) + expected_shape = (len(concentrations), len(timepoints)) + + result = pop_expo(parameters, concentrations, timepoints) + + self.assertEqual(result.shape, expected_shape) + self.assertTrue(np.all(result == 1), "Population counts at time zero should be 1") + + def test_pop_expo_large_timepoints(self): + parameters = [0.1, 0.5, 1.0, 2.0] + concentrations = np.array([0.1, 1.0, 10.0]) + timepoints = np.array([0, 1000, 2000]) + expected_shape = (len(concentrations), len(timepoints)) + + result = pop_expo(parameters, concentrations, timepoints) + + self.assertEqual(result.shape, expected_shape) + self.assertTrue(np.all(result >= 0), "All population counts should be non-negative") + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_rate_expo.py b/tests/test_rate_expo.py new file mode 100644 index 0000000..faf65ba --- /dev/null +++ b/tests/test_rate_expo.py @@ -0,0 +1,24 @@ +import unittest +import numpy as np +from pyphenopop.mixpopid import rate_expo + + +class TestRateExpo(unittest.TestCase): + + def test_rate_expo_basic_functionality(self): + parameters = [0.1, 0.5, 2.0, 1.0] + concentrations = np.array([0.1, 1.0, 10.0]) + expected_output = np.array([0.1 + np.log(0.5 + (1 - 0.5) / (1 + (0.1 / 2.0) ** 1.0)), + 0.1 + np.log(0.5 + (1 - 0.5) / (1 + (1.0 / 2.0) ** 1.0)), + 0.1 + np.log(0.5 + (1 - 0.5) / (1 + (10.0 / 2.0) ** 1.0))]) + np.testing.assert_array_almost_equal(rate_expo(parameters, concentrations), expected_output) + + def test_rate_expo_zero_concentration(self): + parameters = [0.1, 0.5, 2.0, 1.0] + concentrations = np.array([0.0]) + expected_output = np.array([0.1 + np.log(0.5 + (1 - 0.5) / (1 + (0.0 / 2.0) ** 1.0))]) + np.testing.assert_array_almost_equal(rate_expo(parameters, concentrations), expected_output) + + +if __name__ == '__main__': + unittest.main() From 08bd79a2f071437156ceca3b39c92819ee7d621f Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 19 Sep 2024 12:25:42 +0200 Subject: [PATCH 02/12] Add test info --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index a5357d0..558a41c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,3 +5,7 @@ [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" + +[tool.pytest.ini_options] +testpaths = "tests" +addopts = "--cov=pyphenopop --cov-report=xml" From 76f063152ff9c03de416e28740bb2a8e8c3dfa3e Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 19 Sep 2024 13:04:44 +0200 Subject: [PATCH 03/12] Fix coverage --- .github/workflows/tests.yml | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3c6a9bb..fe2f0c9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,11 +29,11 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install .[dev] + pip install -e .[dev] - name: Run tests with coverage run: | - pytest --cov=pyphenopop --cov-report xml:coverage.xml + pytest --cov=./ --cov-report xml:coverage.xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 diff --git a/pyproject.toml b/pyproject.toml index 558a41c..c8c5997 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,4 +8,4 @@ build-backend = "setuptools.build_meta" [tool.pytest.ini_options] testpaths = "tests" -addopts = "--cov=pyphenopop --cov-report=xml" +addopts = "--cov=./ --cov-report=xml" From b69592ec0abdf5c1291f8f10162450a68be2ce10 Mon Sep 17 00:00:00 2001 From: LeonardSchmiester Date: Thu, 19 Sep 2024 13:10:37 +0200 Subject: [PATCH 04/12] Added codecov badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e352f3..b668b6f 100755 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Mixed Cell Population Identification Package ======================= [![PyPI version](https://badge.fury.io/py/pyphenopop.svg)](https://badge.fury.io/py/pyphenopop) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7323577.svg)](https://doi.org/10.5281/zenodo.7323577) - +[![codecov](https://codecov.io/gh/ocbe-uio/pyPhenoPop/graph/badge.svg?token=fihRjmYkMy)](https://codecov.io/gh/ocbe-uio/pyPhenoPop) This package contains methods designed to determine the existance of From 1a3a26ebb27df8b4c00c6131af880d06ccf3ac47 Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 19 Sep 2024 13:59:11 +0200 Subject: [PATCH 05/12] Fix formatting --- tests/test_plotting.py | 140 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 tests/test_plotting.py diff --git a/tests/test_plotting.py b/tests/test_plotting.py new file mode 100644 index 0000000..e77e67d --- /dev/null +++ b/tests/test_plotting.py @@ -0,0 +1,140 @@ +import unittest +from unittest.mock import patch +from pyphenopop.plotting import plot_neg_llh, plot_bic, plot_aic, plot_gr50, plot_gr50_subplot + +import matplotlib.pyplot as plt + + +class TestPlotting(unittest.TestCase): + + def setUp(self): + self.results_dict = { + 'summary': { + 'estimated_num_populations': 3, + 'final_parameters': [0.3, 0.5, 0.2] + }, + '3_subpopulations': { + 'gr50': [0.1, 1.0, 10.0] + } + } + self.results_list = [self.results_dict, self.results_dict] + self.concentrations = [0.01, 0.1, 1.0, 10.0, 100.0] + self.subpopulation_indices = [3, 3] + + @patch('pyphenopop.plotting.plt.show') + def test_plot_neg_llh(self, mock_show): + # Mock data + results = { + '1_subpopulations': {'fval': [10, 12, 11, 13, 14]}, + '2_subpopulations': {'fval': [8, 9, 7, 10, 6]}, + '3_subpopulations': {'fval': [6, 5, 7, 8, 4]}, + '4_subpopulations': {'fval': [4, 3, 5, 2, 1]}, + 'summary': {'estimated_num_populations': 4, + 'final_neg_llh': 1, + 'best_optimization_idx': 4} + } + + # Call the function + fig = plot_neg_llh(results) + + # Check if the figure is created + self.assertIsInstance(fig, plt.Figure) + + # Check if the plot has the correct number of points + ax = fig.gca() + self.assertEqual(len(ax.lines[0].get_xdata()), len(results) - 1) + self.assertEqual(len(ax.lines[0].get_ydata()), len(results) - 1) + + # Check if the y-data matches the expected negative log-likelihood values + expected_nllhs = [10, 6, 4, 1] + self.assertListEqual(list(ax.lines[0].get_ydata()), expected_nllhs) + + # Check labels + self.assertEqual(ax.get_ylabel(), 'Negative log-likelihood') + self.assertEqual(ax.get_xlabel(), 'Number of inferred populations') + + @patch('pyphenopop.plotting.plt.show') + def test_plot_bic(self, mock_show): + # Mock data + results = { + '1_subpopulations': {'BIC': 100}, + '2_subpopulations': {'BIC': 80}, + '3_subpopulations': {'BIC': 60}, + '4_subpopulations': {'BIC': 40}, + 'summary': {'estimated_num_populations': 4, + 'final_neg_llh': 1, + 'best_optimization_idx': 4} + } + + # Call the function + fig = plot_bic(results) + + # Check if the figure is created + self.assertIsInstance(fig, plt.Figure) + + # Check if the plot has the correct number of points + ax = fig.gca() + self.assertEqual(len(ax.lines[0].get_xdata()), len(results) - 1) + self.assertEqual(len(ax.lines[0].get_ydata()), len(results) - 1) + + # Check if the y-data matches the expected BIC values + expected_bic = [100, 80, 60, 40] + self.assertListEqual(list(ax.lines[0].get_ydata()), expected_bic) + + # Check labels + self.assertEqual(ax.get_ylabel(), 'BIC') + self.assertEqual(ax.get_xlabel(), 'Number of inferred populations') + + @patch('pyphenopop.plotting.plt.show') + def test_plot_aic(self, mock_show): + # Mock data + results = { + '1_subpopulations': {'AIC': 90}, + '2_subpopulations': {'AIC': 70}, + '3_subpopulations': {'AIC': 50}, + '4_subpopulations': {'AIC': 30}, + 'summary': {'estimated_num_populations': 4, + 'final_neg_llh': 1, + 'best_optimization_idx': 4} + } + + # Call the function + fig = plot_aic(results) + + # Check if the figure is created + self.assertIsInstance(fig, plt.Figure) + + # Check if the plot has the correct number of points + ax = fig.gca() + self.assertEqual(len(ax.lines[0].get_xdata()), len(results) - 1) + self.assertEqual(len(ax.lines[0].get_ydata()), len(results) - 1) + + # Check if the y-data matches the expected AIC values + expected_aic = [90, 70, 50, 30] + self.assertListEqual(list(ax.lines[0].get_ydata()), expected_aic) + + # Check labels + self.assertEqual(ax.get_ylabel(), 'AIC') + self.assertEqual(ax.get_xlabel(), 'Number of inferred populations') + + def test_plot_gr50_with_dict(self): + fig = plot_gr50(self.results_dict, self.concentrations, 'best') + self.assertIsInstance(fig, plt.Figure) + + def test_plot_gr50_with_invalid_results(self): + with self.assertRaises(TypeError): + plot_gr50("invalid_results", self.concentrations, 'best') + + def test_plot_gr50_with_mismatched_lengths(self): + with self.assertRaises(Exception): + plot_gr50(self.results_list, self.concentrations, [3]) + + def test_plot_gr50_subplot(self): + fig, (ax1, ax2) = plt.subplots(1, 2, gridspec_kw={'width_ratios': [1, 3]}) + plot_gr50_subplot(ax1, ax2, self.results_dict, self.concentrations, 'best') + self.assertTrue(len(ax1.patches) > 0) # Check if pie chart is plotted + self.assertTrue(len(ax2.lines) > 0) # Check if GR50 lines are plotted + + +if __name__ == '__main__': + unittest.main() From 70a4c94c533dac9c94a8d49e75a91eb29ecbf5e0 Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 19 Sep 2024 14:54:10 +0200 Subject: [PATCH 06/12] Fix numpy version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 561abbd..8272c8a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ classifiers= install_requires = matplotlib == 3.5.3 scipy >= 1.9.3 - numpy >= 1.23.4 + numpy >= 1.23.4, < 2.0 pandas >= 1.5.1 tqdm >= 4.64.1 From 36c8eefa4018e02bd5a8b35df62a8cf1682da232 Mon Sep 17 00:00:00 2001 From: LeonardSchmiester Date: Thu, 17 Oct 2024 09:57:54 +0200 Subject: [PATCH 07/12] Dockerfile (#52) * Added dockerfile * Added readme for docker file --- docker/Dockerfile | 15 +++++++++++++++ docker/README.md | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 docker/Dockerfile create mode 100644 docker/README.md diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..b59a8e7 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,15 @@ +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Berlin + +RUN apt-get update \ + && apt-get install -y \ + git \ + python-is-python3 \ + python3 \ + python3-dev \ + python3-pip + +RUN pip3 install -U --upgrade pip wheel \ + && pip3 install pyphenopop diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..0483cf9 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,7 @@ +# AMICI & pyPESTO with Docker + +## Create image + +```bash +cd /docker && docker build -t $USER/pyphenopop:latest . +``` From 7686d497beef11331a06e0ae602c1b6cf1c11913 Mon Sep 17 00:00:00 2001 From: LeonardSchmiester Date: Thu, 17 Oct 2024 10:06:16 +0200 Subject: [PATCH 08/12] Update develop (#54) * Fix coverage report * Fix coverage report * Added codecov badge * Tests for plotting scripts (#51) * Unit tests for plotting scripts * Fix numpy version From 036b2ac8eaabfa86a13dc5d6288100abf5d7a44e Mon Sep 17 00:00:00 2001 From: LeonardSchmiester Date: Thu, 17 Oct 2024 10:07:04 +0200 Subject: [PATCH 09/12] update develop (#55) * Fix coverage report * Fix coverage report * Added codecov badge * Tests for plotting scripts (#51) * Unit tests for plotting scripts * Fix numpy version From 3b04597e87bdd3a79a72e78c478179f9ec32a8f6 Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 17 Oct 2024 10:07:42 +0200 Subject: [PATCH 10/12] Fix pip install --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b59a8e7..f826147 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,5 +11,5 @@ RUN apt-get update \ python3-dev \ python3-pip -RUN pip3 install -U --upgrade pip wheel \ - && pip3 install pyphenopop +RUN pip3 install --no-cache-dir -U --upgrade pip wheel \ + && pip3 install --no-cache-dir pyphenopop From 73ab54d1171a8f6930d4e8723dfabc1d34948234 Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 17 Oct 2024 10:12:24 +0200 Subject: [PATCH 11/12] clean up --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f826147..b77f4d4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -9,7 +9,8 @@ RUN apt-get update \ python-is-python3 \ python3 \ python3-dev \ - python3-pip + python3-pip \ + && apt-get clean RUN pip3 install --no-cache-dir -U --upgrade pip wheel \ && pip3 install --no-cache-dir pyphenopop From fc3835d5d45df44a9762503a833639e7152f2874 Mon Sep 17 00:00:00 2001 From: leonargs Date: Thu, 17 Oct 2024 10:15:24 +0200 Subject: [PATCH 12/12] remove files to clean up --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b77f4d4..1e07f97 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,7 +10,8 @@ RUN apt-get update \ python3 \ python3-dev \ python3-pip \ - && apt-get clean + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* RUN pip3 install --no-cache-dir -U --upgrade pip wheel \ && pip3 install --no-cache-dir pyphenopop