Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e6d16f7
#236 Update README
kwabenantim Mar 18, 2026
2b4ea0b
#236 Add pyproject.toml
kwabenantim Mar 18, 2026
6aa68a7
#236 Update CI
kwabenantim Mar 18, 2026
15f926f
#236 Set Python 3.10 on CI
kwabenantim Mar 18, 2026
f691aea
#236 Fix sundials install on CI
kwabenantim Mar 18, 2026
14771dc
#236 Fix style errors
kwabenantim Mar 18, 2026
5c543bd
#236 add apt update to CI
kwabenantim Mar 18, 2026
f51688f
#236 Update Cython build config
kwabenantim Mar 18, 2026
dae66c1
#236 Fix print statements
kwabenantim Mar 18, 2026
b55133f
#236 Update sundials wrapper
kwabenantim Mar 18, 2026
9f7e8a9
#236 Fix numpy api deprecation warning
kwabenantim Mar 18, 2026
c4cc73a
#236 replace pkg_resources with importlib
kwabenantim Mar 18, 2026
d897cd4
#236 Fix style errors
kwabenantim Mar 18, 2026
745679d
#236 Fix test_algebraic_models
kwabenantim Mar 18, 2026
1e26ce1
#236 Fix pyparsing deprecation warnings
kwabenantim Mar 18, 2026
b8c5e21
#236 Fix pyparsing deprecations
kwabenantim Mar 18, 2026
5dd39c5
#236 Update protocol setup
kwabenantim Mar 18, 2026
e9fd42a
#236 Fix pyparsing deprecations
kwabenantim Mar 18, 2026
4b2c4c6
#236 Fix style
kwabenantim Mar 19, 2026
985b418
#236 test_clamping fix pass one
kwabenantim Mar 19, 2026
9dd32e5
#236 Revert wrappers and test with sundials 3
kwabenantim Mar 19, 2026
343a570
#236 Add sundials wrappers for v3 to v7
kwabenantim Mar 19, 2026
70e1aba
#236 Fix test_algebraic_models
kwabenantim Mar 19, 2026
bf95101
#236 Fix sundials version detection
kwabenantim Mar 20, 2026
f9b021c
#236 Update sundials version handling
kwabenantim Mar 20, 2026
e7bc53e
#236 Bump up dependency versions
kwabenantim Mar 20, 2026
c1b35ae
#236 Enable long tests
kwabenantim Mar 20, 2026
6a0cddf
#236 Run multiple tests in parallel
kwabenantim Mar 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,36 @@ name: Unit test and coverage
on: [pull_request]
jobs:
coverage:
runs-on: ubuntu-16.04
runs-on: ubuntu-24.04

steps:
- name: Check out repository
uses: actions/checkout@v2
uses: actions/checkout@v6
with:
submodules: recursive

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v6
with:
python-version: 3.6
python-version: "3.10"

- name: Install Sundials
run: |
sudo apt-get install libsundials-serial-dev
sudo apt-get update
sudo apt-get install libsundials-dev

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements/setup.txt
python3 -m pip install --upgrade pip

- name: Build and install
run: |
python -m pip install -e .[test]
python3 -m pip install -e .[dev]

- name: Unit & coverage tests
run: |
python -m pytest --cov --cov-config=.coveragerc
FC_LONG_TESTS=1 python3 -m pytest -n auto --cov --cov-config=.coveragerc

- name: Submit report to codecov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v5
if: success()

19 changes: 9 additions & 10 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@ name: Style
on: [pull_request]
jobs:
style:
runs-on: ubuntu-16.04
runs-on: ubuntu-24.04

steps:
- name: Check out repository
uses: actions/checkout@v2
uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v6
with:
python-version: 3.6
python-version: "3.10"

- name: Install tools
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install flake8
python3 -m pip install --upgrade pip
python3 -m pip install flake8

- name: Check code style
run: |
python --version
python -m flake8 --version
python -m flake8

python3 --version
python3 -m flake8 --version
python3 -m flake8
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ develop-eggs
lib
lib64
venv*/
.venv
pyvenv*/

# Installer logs
Expand Down
69 changes: 30 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,45 @@

This is a Python implementation of the Functional Curation (FC) language, intended for use with the Cardiac Electrophysiology Web Lab.

Documentation on FC can be found [here](https://chaste.cs.ox.ac.uk/trac/wiki/FunctionalCuration), while the syntax of FC protocols is described [here](https://chaste.cs.ox.ac.uk/trac/wiki/FunctionalCuration/ProtocolSyntax).
Documentation on FC can be found [here](https://chaste.github.io/docs/paper-tutorials/functionalcuration/), while the syntax of FC protocols is described [here](https://github.com/Chaste/trac_archive/wiki/Functional-Curation-_-Protocol-Syntax).

An ongoing attempt to document the Web Lab and all its interconnected technologies can be viewed in the [weblab docs repository](https://github.com/ModellingWebLab/weblab_docs).

## No Windows support

**FC is tested/developed on Linux and OS/X. There are no plans to run it work on Windows**.

It _might_ run on Windows, if you have installed CVODE with the shared libraries, and an MSVC compiler that matches your Python installation (see [here](https://wiki.python.org/moin/WindowsCompilers)).

## Transition!

This package is currently in transition, migrating the functional curation code from being a Chaste extension project to a standalone Python package.
In particular, we're replacing the CellML and code-generation tool PyCml with [cellmlmanip](https://github.com/ModellingWebLab/cellmlmanip) to read and manipulate CellML code and a new module within `weblab-fc` to generate Model code.

The code from before this transition started can be seen at the tag [`pycml-version`](https://github.com/ModellingWebLab/weblab-fc/tree/pycml-version), but crucial parts of PyCml weblab code are also temporarily stored in the [pycml](./pycml) directory.
Most of the code from [pycml_protocol.py](./pycml/pycml_protocol.py) will have to be replaced by (1) changes to `fc` so that it extracts and stores _all_ the protocol information, and (2) a new code generation module in `fc` that can use information provides by weblab protocols to generate simulation code.
(At the moment both `fc` and `pycml` read the protocol, but in the new code `fc` should gather all the information and then pass it to the code generation component of `fc`.)
> [!NOTE]
> ### No Windows support
>
> FC is tested/developed on Linux and OS/X. There are no plans to make it run on Windows.
> We recommend the [Windows Subsystem for Linux](https://github.com/microsoft/WSL).

> [!WARNING]
> ### Transition!
>
> This package is currently in transition, migrating the functional curation code from
> being a Chaste extension project to a standalone Python package.
> In particular, we're replacing the CellML and code-generation tool PyCml with
> [cellmlmanip](https://github.com/ModellingWebLab/cellmlmanip) to read and manipulate
> CellML code and a new module within `weblab-fc` to generate Model code.
>
> The code from before this transition started can be seen at the tag
> [`pycml-version`](https://github.com/ModellingWebLab/weblab-fc/tree/pycml-version),
> but crucial parts of PyCml weblab code are also temporarily stored in the
> [pycml](./pycml) directory.
> Most of the code from [pycml_protocol.py](./pycml/pycml_protocol.py) will have to be
> replaced by (1) changes to `fc` so that it extracts and stores _all_ the protocol
> information, and (2) a new code generation module in `fc` that can use information
> provides by weblab protocols to generate simulation code.
> (At the moment both `fc` and `pycml` read the protocol, but in the new code `fc`
> should gather all the information and then pass it to the code generation component of `fc`.)

## Installation

In order to build the package you need Cython and numpy. These can be installed with:
```sh
pip install -r requirements/setup.txt
```

The ontologies used are in a separate module, to install this run

```sh
git submodule init
git submodule update
git submodule update --init
```

You also need to have CVODE (from Sundials) installed. If you do this with your system package
You also need to have CVODE (from Sundials v3+) installed. If you do this with your system package
manager no further setup is (probably) needed. Alternatively you can install it using `conda`:
```sh
conda install sundials -c conda-forge
Expand All @@ -52,25 +57,11 @@ export LDFLAGS="-L$HOME/anaconda3/envs/weblab/lib"
```

Because the `weblab_fc` module has Cython components, it needs to be compiled before you can use it.
Compilation is performed using Python's [`distutils`](https://docs.python.org/3/library/distutils.html) and [`setuptools`](https://setuptools.readthedocs.io/en/latest/), and happens automatically when you install the package using `setup.py`.
Compilation is performed using Python's [`setuptools`](https://setuptools.readthedocs.io/en/latest/), and happens automatically when you install the package.
For developers, this can be done using:

```sh
pip install -e .[dev,test]
python3 -m pip install -e ."[dev]"
```

Note that you'll need to repeat this step after any changes to Cython files (e.g. `.pyx` or `.pxd` files), because these don't automatically get recompiled.

## Full installation steps on Jonathan's Macbook (slightly out of date)

```sh
export CONDA_ENV=weblab-fc-py36
conda create -n $CONDA_ENV python=3.6
conda activate $CONDA_ENV
conda install -c conda-forge sundials=4 pytables scipy numpy numexpr
pip install -r requirements/setup.txt
./requirements/weblab_cg.sh
export CFLAGS="-I/anaconda3/envs/$CONDA_ENV/include"
export LDFLAGS="-L/anaconda3/envs/$CONDA_ENV/lib"
pip install -e .[dev,test]
```
5 changes: 3 additions & 2 deletions fc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
finally:
# Always manually delete frame
# https://docs.python.org/2/library/inspect.html#the-interpreter-stack
del(frame)
del(os, inspect)
del frame
del os
del inspect


from .protocol import Protocol # noqa:F401,E402
12 changes: 6 additions & 6 deletions fc/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Environment(object):
Variables not found within the environment are looked up in its "default delegatee".

For more information, see
https://chaste.cs.ox.ac.uk/trac/wiki/FunctionalCuration/ProtocolSyntax#Identifiersandnameresolution
https://github.com/Chaste/trac_archive/wiki/Functional-Curation-_-Protocol-Syntax#Identifiersandnameresolution
"""
next_ident = [0]

Expand Down Expand Up @@ -57,14 +57,14 @@ def define_names(self, names, values):
def evaluate_expr(self, expr_str, env):
from fc.parsing.CompactSyntaxParser import CompactSyntaxParser as csp

parse_action = csp.expr.parseString(expr_str, parseAll=True)
parse_action = csp.expr.parse_string(expr_str, parse_all=True)
expr = parse_action[0].expr()
return expr.evaluate(env)

def evaluate_statement(self, stmt_str, env):
from fc.parsing.CompactSyntaxParser import CompactSyntaxParser as csp

parse_action = csp.stmt_list.parseString(stmt_str, parseAll=True)
parse_action = csp.stmt_list.parse_string(stmt_str, parse_all=True)
stmt_list = parse_action[0].expr()
return env.execute_statements(stmt_list)

Expand All @@ -78,14 +78,14 @@ def look_up(self, name):
# try:
# return self.bindings[name]
# except KeyError:
# print 'Key error looking up', name, 'in', self
# print('Key error looking up', name, 'in', self)
# import sys
# tb = sys.exc_info()[2]
# while tb:
# local_vars = tb.tb_frame.f_locals
# obj = local_vars.get('self', None)
# if obj and isinstance(obj, DelegatingDict):
# print 'Looked for', local_vars['key'], 'in', obj._env
# print('Looked for', local_vars['key'], 'in', obj._env)
# tb = tb.tb_next
# self.debug_delegatees('root')
# raise
Expand All @@ -101,7 +101,7 @@ def set_delegatee_env(self, delegatee, prefix=""):
"The name prefix '" + prefix +
"' has already been used in this context. Check your simulations, imports, etc.")
self.delegatees[prefix] = delegatee
# print 'Delegating to', delegatee, 'for', prefix, 'in', self
# print('Delegating to', delegatee, 'for', prefix, 'in', self)
self.bindings.set_delegatee(delegatee.bindings, prefix)
self.unwrapped_bindings.set_delegatee(delegatee.unwrapped_bindings, prefix)

Expand Down
16 changes: 8 additions & 8 deletions fc/language/expressions/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ def get_defining_environments(self, env):
return self._defining_envs
except AttributeError:
self._root_defining_env = env # For paranoia checking that the cache is valid
d = self._defining_envs = {}
l = self._used_var_local_names = [] # noqa: E741
defining_envs = self._defining_envs = {}
used_local_names = self._used_var_local_names = [] # noqa: E741
for name in self.used_variable_list:
local_name = name[name.rfind(':') + 1:]
l.append(local_name)
d[local_name] = env.find_defining_environment(name)
return d
used_local_names.append(local_name)
defining_envs[local_name] = env.find_defining_environment(name)
return defining_envs

@property
def compiled_function(self):
Expand All @@ -154,9 +154,9 @@ def used_variable_list(self):
try:
return self._used_var_list
except AttributeError:
l = self._used_var_list = list(self.used_variables) # noqa: E741
l.sort()
return l
used_var_list = self._used_var_list = list(self.used_variables) # noqa: E741
used_var_list.sort()
return used_var_list

@property
def used_variables(self):
Expand Down
Loading
Loading