From 8b5e4532794a89add65d2bac2c8a6893303daf51 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 12:39:33 -0400 Subject: [PATCH 01/13] Changes so we can test the code with pytest The changes are: - adding a "do_it" function so we can call the program from another Python script with a particular set of command line options - return the array of final rate constants so we compare them to the right answer --- Source/main.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Source/main.py b/Source/main.py index fb2a796..23a0938 100644 --- a/Source/main.py +++ b/Source/main.py @@ -3,12 +3,27 @@ from Source.visualize import plot_write_ode import numpy as np import os +import sys import torch import datetime import torch.multiprocessing as mp def main(): + ''' + Main and Do_it construct. + + Introducing this two level approach allows the code to be run in two + different ways: + - From the command line when the main function will pass the system + command line arguments. + - From inside another Python script when the do_it function can have an + artificial set of command line arguments passed to it. + The latter approach is a way to run test cases with, e.g. pytest. + ''' + do_it(sys.argv[1:]) + +def do_it(arguments): parser = argparse.ArgumentParser() parser.add_argument('-c', "--conserve", type=int, default=0, help="Number of conservation constraints") @@ -48,7 +63,7 @@ def main(): help="Working directory") parser.add_argument("--zeroth", action='store_true', help="Add 0th order terms") - args = parser.parse_args() + args = parser.parse_args(arguments) world_size = args.jobs os.chdir(os.path.expandvars(os.path.expanduser(args.work_dir))) @@ -116,6 +131,7 @@ def main(): print(trainer.ode.basis_weights.data.numpy()) torch.save(trainer.ode, args.name+'.pt') plot_write_ode(trainer.ode, concentrations, timestamps, args.name, trainer.device) + return trainer.ode.basis_weights.data.numpy() if __name__ == '__main__': From b3826b34702de5254ff0250b118315b3dcb2d055 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 12:49:58 -0400 Subject: [PATCH 02/13] Minor changes to how filenames are constructed. The old way to create filenames caused issues if the test case is stored in a sub-directory of the directory where the test case is run. This caused annoying issues with pytest. The new way to create filenames replaces the "/" character with "_" creating valid filenames in the current working directory instead. --- Source/visualize.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/visualize.py b/Source/visualize.py index f3e6467..f39f5f8 100644 --- a/Source/visualize.py +++ b/Source/visualize.py @@ -13,7 +13,7 @@ def plot_write_ode(ode, real_concentrations, real_timestamps, name, device): tensor_concentrations.to(device) tensor_timestamps.to(device) - with open(f"Rate_equations_of_{name}.txt", "w") as f: + with open(f"Rate_equations_of_{name.replace('/','_')}.txt", "w") as f: f.write(str(ode)) for i in range(len(real_timestamps)): @@ -36,10 +36,10 @@ def plot_write_ode(ode, real_concentrations, real_timestamps, name, device): plt.ylabel("Concentration") plt.ylim(bottom=-0.1) plt.legend() - title = f'Plot_of_{name}_set_{i}' + title = f"Plot_of_{name.replace('/','_')}_set_{i}" plt.title(title) plt.savefig(f"{title}.jpg", dpi=300) pred_df = pd.DataFrame(data=np.hstack([timestamps[:, np.newaxis], pred_conc]), columns=["## Time"] + [f'Set {j + 1} ' for j in range(pred_conc.shape[1])]) - pred_df.to_csv(f"Predicted_Concentrations_of_{name}_set_{i}.csv", sep='\t', index=False, float_format='%8.6f') + pred_df.to_csv(f"Predicted_Concentrations_of_{name.replace('/','_')}_set_{i}.csv", sep='\t', index=False, float_format='%8.6f') From 39115d3cc145f2dc7d987e6f93cc0df39d796781 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 12:53:37 -0400 Subject: [PATCH 03/13] Add continuous integration testing. --- .github/workflows/run_ci.yml | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/run_ci.yml diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml new file mode 100644 index 0000000..7c80740 --- /dev/null +++ b/.github/workflows/run_ci.yml @@ -0,0 +1,58 @@ +name: PolyODENet_CI + +on: + pull_request: + branches: + - master + push: + branches: + - '**' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' + - name: upgrade-pip + run: | + python -m pip install --upgrade pip + python -m pip install wheel + - name: get-numpy + run: | + pip install numpy + - name: get-pytorch + run: | + pip install torch=1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html + - name: get-torchdiffeq + run: | + git clone https://github.com/rtqichen/torchdiffeq + cd torchdiffeq + python setup.py install + - name: get-pytest + run: | + pip install -U pytest + pip install -U pytest-cov + pytest --version + - name: install-PolyODENet + run: | + python setup.py install + - name: run-tests + run: | + cd Tests + pytest --cov=.. --cov-report=xml + - name: publish-coverage + uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: ./coverage/reports/ + env_vars: OS,PYTHON + fail_ci_if_error: true + files: ./converage1.xml + flags: unittests + name: PolyODENet + path_to_write_report: ./coverage/codecov_report.txt + verbose: true From 40bea23159c2301cde5340050e2bea4a08968f38 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 12:54:02 -0400 Subject: [PATCH 04/13] Add a test case based on our current example. --- Tests/test_basic/README.md | 49 ++++++++++++++++++++++++++++++++++ Tests/test_basic/ex1.guess | 3 +++ Tests/test_basic/ex1.ind | 3 +++ Tests/test_basic/ex1.scale | 3 +++ Tests/test_basic/ex1.txt | 40 +++++++++++++++++++++++++++ Tests/test_basic/test_basic.py | 13 +++++++++ 6 files changed, 111 insertions(+) create mode 100644 Tests/test_basic/README.md create mode 100644 Tests/test_basic/ex1.guess create mode 100644 Tests/test_basic/ex1.ind create mode 100644 Tests/test_basic/ex1.scale create mode 100644 Tests/test_basic/ex1.txt create mode 100644 Tests/test_basic/test_basic.py diff --git a/Tests/test_basic/README.md b/Tests/test_basic/README.md new file mode 100644 index 0000000..5666aeb --- /dev/null +++ b/Tests/test_basic/README.md @@ -0,0 +1,49 @@ +## Test constructed from Example 1 +### Consecutive reactions with 1 unknown intermediate + +This example has consecutive reactions with species C being the intermediate. + +A <--> C --> B + +The dimensionless reaction constants are: +* k_1+ = 2 (first reaction forward) +* k_1- = 1 (first reaction reverse) +* k_2 = 3 (second reaction) + +The corresponding ODEs are: + +d[A]/dt = -2[A] + 1[C] + +d[B]/dt = 3[C] + +d[C]/dt = 2[A] - 4[C] + +The original data are generated using scipy.integrate.odeint. +The initial condition is A0=2, B0=0, C0=0. + +In the 'ex1.txt' file, concentration data for C are replaced with -1, +meaning missing profile. Only the initial condition C0=0 is kept. + +The 'ex1.guess' file gives almost-optimized ODE coefficients so the +test can be fast. + +The 'ex1.ind' and 'ex1.scale' files control the polynomial model. + +Use the following command for a test run. + +```train_poly -f ex1.txt -m 1000 -N ex1 -igs``` + +Your 'Rate_equations_of_ex1.txt' should look like + +``` +PolynomialODE(): + +d[A]/dt = -1.84[A] + 0.682[C] + +d[B]/dt = 2.73[C] + +d[C]/dt = 1.84[A] - 3.32[C] +``` + +The test case is executed by the ```test_basic.py``` script. This script has +to be invoked by `pytest` from one directory up. diff --git a/Tests/test_basic/ex1.guess b/Tests/test_basic/ex1.guess new file mode 100644 index 0000000..93524b9 --- /dev/null +++ b/Tests/test_basic/ex1.guess @@ -0,0 +1,3 @@ +-1.0 0.0 1.0 + 0.0 0.0 0.0 + 2.0 2.0 -4.0 diff --git a/Tests/test_basic/ex1.ind b/Tests/test_basic/ex1.ind new file mode 100644 index 0000000..c1a16dd --- /dev/null +++ b/Tests/test_basic/ex1.ind @@ -0,0 +1,3 @@ +0 0 0 1 0 0 +1 0 1 1 1 1 +2 0 2 1 2 2 diff --git a/Tests/test_basic/ex1.scale b/Tests/test_basic/ex1.scale new file mode 100644 index 0000000..c2b8964 --- /dev/null +++ b/Tests/test_basic/ex1.scale @@ -0,0 +1,3 @@ +1. 0. -1. +0. 0. 0. +1. 1. 1. diff --git a/Tests/test_basic/ex1.txt b/Tests/test_basic/ex1.txt new file mode 100644 index 0000000..259e4fd --- /dev/null +++ b/Tests/test_basic/ex1.txt @@ -0,0 +1,40 @@ +0.00000000e+00 2.00000000e+00 0.00000000e+00 0.00000000e+00 +5.00000000e-02 1.81405372e+00 1.35894200e-02 -1 +1.00000000e-01 1.65282218e+00 4.93666785e-02 -1 +1.50000000e-01 1.51198657e+00 1.01118013e-01 -1 +2.00000000e-01 1.38808346e+00 1.64033431e-01 -1 +2.50000000e-01 1.27832791e+00 2.34405081e-01 -1 +3.00000000e-01 1.18047370e+00 3.09389644e-01 -1 +3.50000000e-01 1.09270275e+00 3.86821013e-01 -1 +4.00000000e-01 1.01353765e+00 4.65062829e-01 -1 +4.50000000e-01 9.41772570e-01 5.42892366e-01 -1 +5.00000000e-01 8.76418400e-01 6.19409136e-01 -1 +5.50000000e-01 8.16659425e-01 6.93963034e-01 -1 +6.00000000e-01 7.61818928e-01 7.66097856e-01 -1 +6.50000000e-01 7.11331926e-01 8.35506946e-01 -1 +7.00000000e-01 6.64723524e-01 9.01998415e-01 -1 +7.50000000e-01 6.21591704e-01 9.65467851e-01 -1 +8.00000000e-01 5.81593652e-01 1.02587704e+00 -1 +8.50000000e-01 5.44434844e-01 1.08323726e+00 -1 +9.00000000e-01 5.09860345e-01 1.13759634e+00 -1 +9.50000000e-01 4.77647843e-01 1.18902857e+00 -1 +1.00000000e+00 4.47602076e-01 1.23762684e+00 -1 +1.05000000e+00 4.19550345e-01 1.28349666e+00 -1 +1.10000000e+00 3.93338904e-01 1.32675151e+00 -1 +1.15000000e+00 3.68830036e-01 1.36750929e+00 -1 +1.20000000e+00 3.45899681e-01 1.40588967e+00 -1 +1.25000000e+00 3.24435504e-01 1.44201209e+00 -1 +1.30000000e+00 3.04335307e-01 1.47599422e+00 -1 +1.35000000e+00 2.85505726e-01 1.50795097e+00 -1 +1.40000000e+00 2.67861151e-01 1.53799367e+00 -1 +1.45000000e+00 2.51322822e-01 1.56622956e+00 -1 +1.50000000e+00 2.35818075e-01 1.59276147e+00 -1 +1.55000000e+00 2.21279701e-01 1.61768766e+00 -1 +1.60000000e+00 2.07645403e-01 1.64110167e+00 -1 +1.65000000e+00 1.94857328e-01 1.66309239e+00 -1 +1.70000000e+00 1.82861665e-01 1.68374408e+00 -1 +1.75000000e+00 1.71608296e-01 1.70313651e+00 -1 +1.80000000e+00 1.61050482e-01 1.72134506e+00 -1 +1.85000000e+00 1.51144597e-01 1.73844089e+00 -1 +1.90000000e+00 1.41849884e-01 1.75449113e+00 -1 +1.95000000e+00 1.33128239e-01 1.76955904e+00 -1 diff --git a/Tests/test_basic/test_basic.py b/Tests/test_basic/test_basic.py new file mode 100644 index 0000000..4cb4720 --- /dev/null +++ b/Tests/test_basic/test_basic.py @@ -0,0 +1,13 @@ +from Source.main import do_it +import numpy + +def train_basic(): + args = ['-f', 'test_basic/ex1.txt', '-m', '1000', '-N', 'test_basic/ex1', '-igs'] + return do_it(args) + +def test_basic(): + answer = numpy.array([[-1.8376, 0., 1.8376], [ 0., 0., 0. ], [ 0.6819, 2.7304, -3.3204]]) + result = train_basic() + diff = result - answer + vector = diff.reshape((9)) + assert numpy.linalg.norm(vector,numpy.inf) < 1.0e-3 From 2a54ae6e49f0420378cb989fb021a25ea1bc4eba Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 12:55:06 -0400 Subject: [PATCH 05/13] This file is needed so that setup.py will install PolyODENet properly. --- Source/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Source/__init__.py diff --git a/Source/__init__.py b/Source/__init__.py new file mode 100644 index 0000000..e69de29 From 1b2a034810fed10882260ea977d0a72012ef363c Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 19:21:26 -0400 Subject: [PATCH 06/13] Github complained about actions/checkout@v2 (?) --- .github/workflows/run_ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index 7c80740..2516a70 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -13,8 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - name: checkout + uses: actions/checkout@v3 + - name: get-python + uses: actions/setup-python@v2 with: python-version: '3.9' - name: upgrade-pip From 98a87bb6af61e2f1ac4e883742a9f264493ac37d Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 21:28:23 -0400 Subject: [PATCH 07/13] Still trying to fix the "syntax error". --- .github/workflows/run_ci.yml | 93 ++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index 2516a70..112f100 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -11,50 +11,49 @@ on: jobs: build: runs-on: ubuntu-latest - - steps: - - name: checkout - uses: actions/checkout@v3 - - name: get-python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - name: upgrade-pip - run: | - python -m pip install --upgrade pip - python -m pip install wheel - - name: get-numpy - run: | - pip install numpy - - name: get-pytorch - run: | - pip install torch=1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html - - name: get-torchdiffeq - run: | - git clone https://github.com/rtqichen/torchdiffeq - cd torchdiffeq - python setup.py install - - name: get-pytest - run: | - pip install -U pytest - pip install -U pytest-cov - pytest --version - - name: install-PolyODENet - run: | - python setup.py install - - name: run-tests - run: | - cd Tests - pytest --cov=.. --cov-report=xml - - name: publish-coverage - uses: codecov/codecov-action@v2 - with: - token: ${{ secrets.CODECOV_TOKEN }} - directory: ./coverage/reports/ - env_vars: OS,PYTHON - fail_ci_if_error: true - files: ./converage1.xml - flags: unittests - name: PolyODENet - path_to_write_report: ./coverage/codecov_report.txt - verbose: true + steps: + - name: checkout + uses: actions/checkout@v3 + - name: get-python + uses: actions/setup-python@v2 + with: + python-version: '3.9' + - name: upgrade-pip + run: | + python -m pip install --upgrade pip + python -m pip install wheel + - name: get-numpy + run: | + pip install numpy + - name: get-pytorch + run: | + pip install torch=1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html + - name: get-torchdiffeq + run: | + git clone https://github.com/rtqichen/torchdiffeq + cd torchdiffeq + python setup.py install + - name: get-pytest + run: | + pip install -U pytest + pip install -U pytest-cov + pytest --version + - name: install-PolyODENet + run: | + python setup.py install + - name: run-tests + run: | + cd Tests + pytest --cov=.. --cov-report=xml + - name: publish-coverage + uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: ./coverage/reports/ + env_vars: OS,PYTHON + fail_ci_if_error: true + files: ./converage1.xml + flags: unittests + name: PolyODENet + path_to_write_report: ./coverage/codecov_report.txt + verbose: true From 837ea0d60f0844938697ad9ac80deacd90628875 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 21:32:58 -0400 Subject: [PATCH 08/13] Fix: torch=1.7.0+cpu should have been torch==1.7.0+cpu. --- .github/workflows/run_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index 112f100..413b44e 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -27,7 +27,7 @@ jobs: pip install numpy - name: get-pytorch run: | - pip install torch=1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html + pip install torch==1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html - name: get-torchdiffeq run: | git clone https://github.com/rtqichen/torchdiffeq From 23d28617de14f768c64f13830ddb53596c9aec86 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 21:36:18 -0400 Subject: [PATCH 09/13] Version 1.7.0 of pytorch is no longer available. Trying 1.11.0 instead. --- .github/workflows/run_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index 413b44e..debc71d 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -27,7 +27,7 @@ jobs: pip install numpy - name: get-pytorch run: | - pip install torch==1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html + pip install torch==1.11.0+cpu -f https://download.pytorch.org/whl/torch_stable.html - name: get-torchdiffeq run: | git clone https://github.com/rtqichen/torchdiffeq From 0c3bc9fea84cc5a86f1ce2b5c3ec42de73cbe3d1 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 21:50:35 -0400 Subject: [PATCH 10/13] Codecov uploader documentation seems inconsistent with implementation. --- .github/workflows/run_ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index debc71d..ad0d16e 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -45,6 +45,8 @@ jobs: run: | cd Tests pytest --cov=.. --cov-report=xml + cd .. + ls -l - name: publish-coverage uses: codecov/codecov-action@v2 with: @@ -55,5 +57,4 @@ jobs: files: ./converage1.xml flags: unittests name: PolyODENet - path_to_write_report: ./coverage/codecov_report.txt verbose: true From a0fa894b6feba1f4489704f4ef7a80622ed13c0c Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 21:57:48 -0400 Subject: [PATCH 11/13] Coverage reports are not written where I said they should be. --- .github/workflows/run_ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index ad0d16e..4bb18a1 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -45,16 +45,19 @@ jobs: run: | cd Tests pytest --cov=.. --cov-report=xml + pwd + ls -l cd .. + pwd ls -l - name: publish-coverage uses: codecov/codecov-action@v2 with: token: ${{ secrets.CODECOV_TOKEN }} - directory: ./coverage/reports/ + directory: ./Tests env_vars: OS,PYTHON fail_ci_if_error: true - files: ./converage1.xml + files: ./Tests/converage.xml flags: unittests name: PolyODENet verbose: true From aa79ae5242dec31129ad13e1524514c2e9a8dd68 Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Thu, 31 Mar 2022 22:05:12 -0400 Subject: [PATCH 12/13] Fixed a typo in filename. --- .github/workflows/run_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index 4bb18a1..3337cdf 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -44,7 +44,7 @@ jobs: - name: run-tests run: | cd Tests - pytest --cov=.. --cov-report=xml + pytest --cov=. --cov-report=xml pwd ls -l cd .. @@ -57,7 +57,7 @@ jobs: directory: ./Tests env_vars: OS,PYTHON fail_ci_if_error: true - files: ./Tests/converage.xml + files: ./Tests/coverage.xml flags: unittests name: PolyODENet verbose: true From 2912426501a9f4e8108b959b9b5f895b226c35ac Mon Sep 17 00:00:00 2001 From: hjjvandam Date: Wed, 6 Apr 2022 09:22:40 -0400 Subject: [PATCH 13/13] Comment code coverage report upload out. We can add this back in when we have a place and a token to complete the upload successfully. For now we can do without the upload and instead make sure that the CI is successfull. --- .github/workflows/run_ci.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/run_ci.yml b/.github/workflows/run_ci.yml index 3337cdf..599f051 100644 --- a/.github/workflows/run_ci.yml +++ b/.github/workflows/run_ci.yml @@ -50,14 +50,14 @@ jobs: cd .. pwd ls -l - - name: publish-coverage - uses: codecov/codecov-action@v2 - with: - token: ${{ secrets.CODECOV_TOKEN }} - directory: ./Tests - env_vars: OS,PYTHON - fail_ci_if_error: true - files: ./Tests/coverage.xml - flags: unittests - name: PolyODENet - verbose: true + # - name: publish-coverage + # uses: codecov/codecov-action@v2 + # with: + # token: ${{ secrets.CODECOV_TOKEN }} + # directory: ./Tests + # env_vars: OS,PYTHON + # fail_ci_if_error: true + # files: ./Tests/coverage.xml + # flags: unittests + # name: PolyODENet + # verbose: true