Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
64 changes: 45 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,35 +42,61 @@ jobs:
- name: Run assimulo-free tests
run: python -m pytest tests/ -m "not assimulo"

pixi-lock:
name: Locked pixi install (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest

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

- name: Set up locked pixi environments
uses: prefix-dev/setup-pixi@v0.10.0
with:
pixi-version: v0.67.1
manifest-path: pyproject.toml
environments: >-
default
assimulo
locked: true
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'master' }}

- name: Verify documented locked installation
run: pixi install --all --locked

- name: Verify core and solver imports
run: |
pixi run python -c "import PharmaPy"
pixi run -e assimulo python -c "import PharmaPy, assimulo"

integration-assimulo:
name: Assimulo integration tests
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: true
needs: pixi-lock

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

- name: Install system solver libraries
run: |
sudo apt-get update
sudo apt-get install -y gfortran liblapack-dev libblas-dev

- name: Set up conda environment
uses: conda-incubator/setup-miniconda@v4
- name: Set up locked Assimulo environment
uses: prefix-dev/setup-pixi@v0.10.0
with:
miniforge-version: latest
use-mamba: true
environment-file: environment.yml
activate-environment: pharmapy-assimulo
auto-activate: false
conda-remove-defaults: true

- name: Install PharmaPy without pip solver resolution
shell: bash -el {0}
run: python -m pip install -e . --no-deps
pixi-version: v0.67.1
manifest-path: pyproject.toml
environments: assimulo
locked: true
cache: true
cache-write: false

- name: Run Assimulo-marked tests
shell: bash -el {0}
run: python -m pytest tests/ -v -m assimulo
run: pixi run -e assimulo test-assimulo
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ celerybeat-schedule
# dotenv
.env

# virtualenv
.venv/
# virtualenv (.venv may be a directory or a symlink into a pixi env)
.venv
.venv.*
venv/
ENV/

# pixi
.pixi/

# Spyder project settings
.spyderproject

Expand Down
17 changes: 15 additions & 2 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
# Dependency Policy

For runnable pip, pixi, and conda installation instructions, see
[`INSTALLATION.md`](INSTALLATION.md).

The default install keeps only the core runtime dependencies. Assimulo is an
optional solver dependency because it is difficult to build on common pip-only
environments, is not published on PyPI above version 3.0, and is only needed for
the solver-backed unit-operation models. Use the conda-forge environment in
`environment.yml`, or a local source build of Assimulo, for solver-backed runs.
the solver-backed unit-operation models. For solver-backed runs, use the pixi
environments defined in `pyproject.toml` (`pixi run -e assimulo ...`), the
conda-forge environment in `environment.yml`, or a local source build of
Assimulo.

pixi is the recommended developer/CI environment manager: its `[tool.pixi]`
Comment thread
bernalde marked this conversation as resolved.
configuration in `pyproject.toml` provides a `default` (core, Assimulo-free)
and an `assimulo` (full backend) environment backed by a committed `pixi.lock`,
which is this repository's locked, reproducible way to obtain the conda-forge
solver stack. `[project]` remains the source of truth for pip users under the
`pharmapy-sim` distribution name; the Python import remains `PharmaPy`. The pixi
dependency bounds mirror the core project metadata and must stay synchronized.

Current bounds:

Expand Down
251 changes: 251 additions & 0 deletions INSTALLATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# Installing PharmaPy

PharmaPy has a pip-installable core and an optional Assimulo solver backend.
Choose the installation path that matches the work you need to do:

- Use **pip** for the core library and solver-free development.
- Use **pixi** for a reproducible development environment or any work that
requires Assimulo.

pixi is a development and solver-environment tool. It is not a PharmaPy runtime
dependency and does not replace the package metadata used by pip.

The installation commands intentionally produce different environments:

| Command | Assimulo included? | Intended use |
| --- | --- | --- |
| `python -m pip install .` | No | Core library for users |
| `pixi install --locked` | No | Reproducible core development |
| `pixi install -e assimulo --locked` | Yes | Solver-backed development and use |
| `pixi install --all --locked` | Yes, in the separate `assimulo` environment | Maintainer verification of both environments |

## Package and import names

The planned PyPI distribution name is **`pharmapy-sim`**. The Python import name
remains **`PharmaPy`**:

```python
import PharmaPy
```

There is not yet a PharmaPy process-simulation release on PyPI. Until one is
published, install this project from a source checkout as described below. Do
not run `pip install pharmapy`: that name belongs to an unrelated project.
The `pharmapy-sim` name remains unreserved until the first release is uploaded;
maintainers must recheck its availability immediately before publishing and
must not advertise the index-install command until that upload succeeds.

## Core installation with pip

The core installation supports Python 3.9 or newer and does not install
Assimulo.

Clone the repository and enter it:

```bash
git clone https://github.com/PharmaPy-org/PharmaPy.git
cd PharmaPy
```

Create and activate a virtual environment:

```bash
python -m venv .venv
```

On Linux or macOS:

```bash
source .venv/bin/activate
```

On Windows PowerShell:

```powershell
.venv\Scripts\Activate.ps1
```

Install PharmaPy:

```bash
python -m pip install --upgrade pip
python -m pip install .
```

Verify the installation:

```bash
python -c "import PharmaPy; print(PharmaPy.__file__)"
```

For editable development and the core test dependencies, use:

```bash
python -m pip install -e ".[test]"
python -m pytest tests/ -m "not assimulo"
```

After the first `pharmapy-sim` release is published, the core installation
command will be:

```bash
python -m pip install pharmapy-sim
```

The `assimulo` optional extra contains only the Cython helper used by source
build workflows; it cannot install the current supported Assimulo release from
PyPI.

## Why pixi is used

pip remains the primary installation mechanism for the PharmaPy package. pixi
is used for the development and solver environment because Assimulo wraps
compiled SUNDIALS, Cython, C, and Fortran components. The
[Assimulo release on PyPI](https://pypi.org/project/Assimulo/) does not provide
a compatible wheel for PharmaPy's supported Python versions, whereas
[conda-forge provides compiled Assimulo packages](https://anaconda.org/conda-forge/assimulo).

pixi can resolve those conda-forge binaries, install the local PharmaPy package
editably, and record the complete result in `pixi.lock`. Keeping pixi
configuration under `[tool.pixi]` means that it does not become a dependency of
the PharmaPy wheel and does not change how the package is built or published to
PyPI.

Plain `environment.yml` remains a simpler fallback, but it does not pin the
complete transitive environment. The lockfile is the reason to retain pixi; if
the project stops testing and maintaining that lockfile, pixi would add
maintenance cost without providing its intended reproducibility benefit.

## Reproducible installation with pixi

The committed `pixi.lock` supports `linux-64` and `win-64`. Install pixi using
its
[official installation instructions](https://pixi.prefix.dev/latest/installation/).
The native Windows installer used to verify this guide can be run from
PowerShell:

```powershell
powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex"
```

Open a new terminal after installation so that `pixi` is available on `PATH`.
Then clone and enter the repository:

```bash
git clone https://github.com/PharmaPy-org/PharmaPy.git
cd PharmaPy
```

The available environments are:

- `default`: core dependencies without Assimulo
- `assimulo`: the full solver stack with Assimulo 3.4.3 and SUNDIALS

For work that requires Assimulo, install its locked environment explicitly:

```bash
pixi install -e assimulo --locked
```

This command installs both PharmaPy and Assimulo in the named environment.
Verify that both imports work:

```bash
pixi run -e assimulo python -c "import PharmaPy, assimulo"
```

For core-only development, install the default environment:

```bash
pixi install --locked
```

Maintainers can install both environments together:

```bash
pixi install --all --locked
```

Run the matching test lanes:

```bash
pixi run test
pixi run -e assimulo test-assimulo
```

Run Python or a script in either environment:

```bash
pixi run python -c "import PharmaPy"
pixi run -e assimulo python -c "import PharmaPy, assimulo"
pixi run -e assimulo python path/to/script.py
```

You can also start an activated shell with `pixi shell` or
`pixi shell -e assimulo`.

macOS is not currently present in the committed lockfile. Maintainers extending
platform support must add the platform under `[tool.pixi.workspace].platforms`,
regenerate `pixi.lock`, and verify both test lanes on that platform.

## What is tested

The following installation paths were run successfully on `linux-64` when this
guide was introduced:

- A fresh Python 3.11 virtual environment ran `python -m pip install .`,
`python -m pip check`, and `import PharmaPy`. Wheel and source-distribution
builds also passed.
- `pixi install --all --locked` installed both locked environments.
- The core pixi test lane passed.
- The Assimulo pixi test lane passed and imported both `PharmaPy` and Assimulo
3.4.3.

The native `win-64` lock was then generated and verified with pixi 0.67.1 and
Python 3.11:

- `pixi install --all --locked` installed the core and Assimulo environments.
- The core lane passed 56 tests, with 4 skipped and 6 deselected.
- The Assimulo lane imported Assimulo 3.4.3 and passed all 14 selected
integration tests.

Continuous integration exercises both installation promises:

- The core job installs PharmaPy editably with pip and runs the solver-free
tests.
- The gating locked-environment job runs on Linux and Windows, installs both
pixi environments from the committed lockfile, reruns the documented
`pixi install --all --locked` command, and verifies the core and Assimulo
imports.
- A separate advisory job runs the solver-backed tests with
`continue-on-error: true`, preserving the project's tolerance for instability
in the compiled Assimulo/SUNDIALS integration without weakening the lockfile
check.

Maintainers changing dependencies should also run the same checks locally:

```bash
pixi lock --check
pixi install --all --locked
pixi run test
pixi run -e assimulo test-assimulo
```

Keeping the pip-based core CI lane alongside a gating locked-pixi job proves
both installation promises: PharmaPy remains pip-installable, and the compiled
solver environment remains reproducible. The advisory solver-test job reports
integration health separately.

## Manual conda fallback for Assimulo

`environment.yml` remains available as an unlocked conda-forge fallback:

```bash
conda env create -f environment.yml
conda activate pharmapy-assimulo
python -m pip install -e . --no-deps
python -m pytest tests/ -m assimulo
```

Prefer pixi when possible because its committed lockfile records the complete
resolved environment.
19 changes: 0 additions & 19 deletions InstallOnMac.sh

This file was deleted.

Loading