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
28 changes: 13 additions & 15 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,31 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_COMMITTER_NAME: ${{ github.actor }}
GIT_COMMITTER_EMAIL: ${{ github.actor }}@users.noreply.github.com

name: Deploy docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Checkout main
uses: actions/checkout@v5
# To be able to push gh-pages branch later, need to have that branch fetched
# Could fetch it later on but this seems simpler and less finicky
with:
fetch-depth: 0
- name: Read CI version config
id: versions
uses: mikefarah/yq@v4.44.1
with:
cmd: yq eval '.python-version' .github/ci-config/ci-versions.yml
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ steps.versions.outputs.result }}
- run: pip install mkdocstrings-python mkdocs-material mike mkdocs-ipynb
- run: pip install .
- run: pip install .[docs]
- run: echo ${{ github.event_name}} ${{ github.ref_name }}
# Deploy docs according to type of event
- name: Deploy docs as latest
- name: Build docs as latest
if: ${{ github.event_name == 'release' }}
run: mike deploy ${{ github.ref_name }} latest
- name: Deploy docs for PR
- name: Build docs for PR
if: ${{ github.event_name == 'pull_request' }}
run: mike deploy pr-${{ github.event.number }}
- name: Deploy docs as dev
- name: Build docs as dev
if: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
run: mike deploy dev
- name: Get docs into GitHub Pages
- name: Deploy docs to GitHub Pages
if: ${{ github.event_name != 'pull_request' }}
run: |
git switch gh-pages
git push origin gh-pages
39 changes: 13 additions & 26 deletions .github/workflows/pr-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name: PR Tests

on:
pull_request:
branches: [ main, dev-pyomo ]
branches: [ main ]
types: [ opened, synchronize, reopened, ready_for_review, converted_to_draft ]

jobs:
Expand All @@ -26,11 +26,9 @@ jobs:
- name: Determine test mode
id: mode
run: |
if [ "${{ github.event.pull_request.draft }}" == "true" ]; then
echo "coverage=false" >> $GITHUB_OUTPUT
if [ "${{ github.event.pull_request.draft }}" ]; then
echo "mode=fast" >> $GITHUB_OUTPUT
else
echo "coverage=true" >> $GITHUB_OUTPUT
echo "mode=full" >> $GITHUB_OUTPUT
fi

Expand All @@ -40,25 +38,25 @@ jobs:
python-version: ${{ steps.versions.outputs.result }}
cache: 'pip'
cache-dependency-path: |
requirements.txt
requirements-dev.txt
pyproject.toml

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt -r requirements-dev.txt
pip install .
pip install .[dev]
pip install -e . --no-build-isolation

- name: Run tests (draft = fast, ready = coverage)
- name: Run tests
# Currently this conditional branching doesn't actually do anything,
# since pyproject.toml adds these coverage arguments to the testing anyway
run: |
if [ "${{ steps.mode.outputs.coverage }}" == "true" ]; then
echo "🔍 Running full tests with coverage (PR is ready for review)"
echo "⚡ Skipping slow tests (marked with @pytest.mark.slow) - these run on merge"
pytest tests/ -n auto -v -m "not slow" --cov=lyopronto --cov-report=xml --cov-report=term-missing
if [ "${{ steps.mode.outputs.mode }}" == "fast" ]; then
echo "⚡ Skipping notebook tests (marked with @pytest.mark.notebook) - these run separately"
pytest tests/ -n auto -v -m "not notebook" --cov=lyopronto --cov-report=term-missing
else
echo "⚡ Running fast tests without coverage (PR is draft)"
echo "⚡ Skipping slow tests (marked with @pytest.mark.slow)"
pytest tests/ -n auto -v -m "not slow"
echo "⚡ Skipping notebook tests (marked with @pytest.mark.slow), not running coverage"
pytest tests/ -n auto -v -m "not notebook"
fi

- name: Upload coverage (if run)
Expand All @@ -70,14 +68,3 @@ jobs:
name: pr-coverage
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

- name: Test Summary
if: always()
run: |
if [ "${{ steps.mode.outputs.coverage }}" == "true" ]; then
echo "✅ Full tests with coverage completed"
echo "📊 PR is ready for review with coverage verified"
else
echo "⚡ Fast tests completed (PR is draft)"
echo "� Mark PR as 'Ready for Review' to run coverage tests"
fi
68 changes: 49 additions & 19 deletions .github/workflows/rundocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,54 @@ on:

jobs:
doctests:
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# GIT_COMMITTER_NAME: ${{ github.actor }}
# GIT_COMMITTER_EMAIL: ${{ github.actor }}@users.noreply.github.com
name: Notebook
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./docs/examples
strategy:
matrix:
notebook:
- knownRp_PD.ipynb
- unknownRp_PD.ipynb

steps:
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v4
- run: pip install ruamel.yaml scipy numpy matplotlib papermill ipykernel
- name: Run notebooks
run: papermill ${{ matrix.notebook }} ${{ matrix.notebook }} -k python
- uses: actions/checkout@v4

- name: Read CI version config
id: versions
uses: mikefarah/yq@v4.44.1
with:
cmd: yq eval '.python-version' .github/ci-config/ci-versions.yml

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ steps.versions.outputs.result }}
cache: 'pip'
cache-dependency-path: |
pyproject.toml

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install .
pip install .[dev]
pip install -e . --no-build-isolation

- name: Run tests (draft = fast, ready = coverage)
run: pytest tests/ -n auto -v -m "notebook" --cov=lyopronto --cov-report=xml --cov-report=term-missing
# jobs:
# doctests:
# # env:
# # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# # GIT_COMMITTER_NAME: ${{ github.actor }}
# # GIT_COMMITTER_EMAIL: ${{ github.actor }}@users.noreply.github.com
# name: Notebook
# runs-on: ubuntu-latest
# defaults:
# run:
# working-directory: ./docs/examples
# strategy:
# matrix:
# notebook:
# - knownRp_PD.ipynb
# - unknownRp_PD.ipynb
# steps:
# - uses: actions/checkout@v5
# - name: Set up Python
# uses: actions/setup-python@v4
# - run: pip install ruamel.yaml scipy numpy matplotlib papermill ipykernel
# - name: Run notebooks
# run: papermill ${{ matrix.notebook }} ${{ matrix.notebook }} -k python
6 changes: 3 additions & 3 deletions .github/workflows/slow-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ jobs:
python-version: ${{ steps.versions.outputs.result }}
cache: 'pip'
cache-dependency-path: |
requirements.txt
requirements-dev.txt
pyproject.toml

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt -r requirements-dev.txt
pip install .
pip install .[dev]
pip install -e . --no-build-isolation

- name: Run slow tests
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ jobs:
python-version: ${{ steps.versions.outputs.result }}
cache: 'pip'
cache-dependency-path: |
requirements.txt
requirements-dev.txt
pyproject.toml

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt -r requirements-dev.txt
pip install .
pip install .[dev]
pip install -e . --no-build-isolation

- name: Run ALL tests with pytest and coverage (including slow tests)
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ MANIFEST
*.csv

docs/build

# for conda environment install, converted from pyproject.toml
environment.yml
# for local settings
.vscode/
################################################################################
# Jupyter Notebook #
################################################################################
Expand Down
68 changes: 1 addition & 67 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# LyoPRONTO

[![Tests](https://github.com/SECQUOIA/LyoPRONTO/workflows/Tests/badge.svg?branch=dev-pyomo)](https://github.com/SECQUOIA/LyoPRONTO/actions/workflows/tests.yml)
[![Python 3.13](https://img.shields.io/badge/python-3.13-blue.svg)](https://www.python.org/downloads/)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Code Coverage](https://img.shields.io/badge/coverage-93%25-brightgreen.svg)](htmlcov/index.html)

LyoPRONTO is an open-source user-friendly tool to simulate and optimize freezing and primary drying in lyophilizers written using Python.

Expand All @@ -20,39 +14,9 @@ Execute:
```
python3 LyoPronto.main -m
```
LyoPRONTO is a vial-scale lyophilization (freeze-drying) process simulator written in Python. It models the freezing and primary drying phases using heat and mass transfer equations.
This will execute the file `main.py` in an appropriate scope. Parameters can be changed in `main.py`. Files listing the inputs and outputs will be generated in the current directory, along with some plots of temperature, pressure, and drying progress vs. time.
A video tutorial by the authors illustrating this process can be found [on LyoHUB's YouTube channel](https://youtu.be/DI-Gz0pBI0w).

## Modern Examples

For new users, we recommend using the examples in the `examples/` directory instead:
```bash
# Primary drying simulation (recommended starting point)
python examples/example_web_interface.py

# Parameter estimation from experimental data
python examples/example_parameter_estimation.py

# Process optimization
python examples/example_optimizer.py

# Freezing simulation
python examples/example_freezing.py

# Design space generation
python examples/example_design_space.py
```

See [`examples/README.md`](examples/README.md) for detailed documentation.

## Legacy Examples

The repository root contains legacy example scripts for backward compatibility:
- `ex_knownRp_PD.py` - Original primary drying example → Use `examples/example_web_interface.py` instead
- `ex_unknownRp_PD.py` - Original parameter estimation example → Use `examples/example_parameter_estimation.py` instead

These legacy scripts are maintained and tested, but new users should use the modern examples in the `examples/` directory.

# Citation
G. Shivkumar, P. S. Kazarin, A. D. Strongrich, & A. A. Alexeenko, "LyoPRONTO: An Open-Source Lyophilization PRocess OptimizatioN TOol", AAPS PharmSciTech (2019) 20: 328.

Expand All @@ -69,33 +33,3 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.

By request, this software may also be distributed under the terms of the GNU Lesser General Public License (LGPL); for permission, contact the authors or maintainer.

# Documentation

### Quick Start
- **Getting Started**: [`docs/GETTING_STARTED.md`](docs/GETTING_STARTED.md) - Developer setup and environment
- **Examples**: [`examples/README.md`](examples/README.md) - Web interface examples (primary drying, optimizer, freezing, design space)
- **Testing**: [`tests/README.md`](tests/README.md) - Test suite (85 tests, 100% passing)

### Technical Documentation
- **Architecture**: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) - System design and module structure
- **Physics**: [`docs/PHYSICS_REFERENCE.md`](docs/PHYSICS_REFERENCE.md) - Equations, models, and thermodynamics
- **Pyomo Integration**: [`docs/PYOMO_ROADMAP.md`](docs/PYOMO_ROADMAP.md) - NLP optimization plans
- **Coexistence Philosophy**: [`docs/COEXISTENCE_PHILOSOPHY.md`](docs/COEXISTENCE_PHILOSOPHY.md) - Scipy + Pyomo parallel implementation

### Development
- **Development Log**: [`docs/DEVELOPMENT_LOG.md`](docs/DEVELOPMENT_LOG.md) - Chronological change history
- **Contributing**: [`CONTRIBUTING.md`](CONTRIBUTING.md) - Contribution guidelines
- **Archive**: [`docs/archive/`](docs/archive/) - Historical session summaries

# Notes on contributing & maintenance

There is a GitHub Action on this repo which will automatically build the documentation (which uses Material for MkDocs with `mike` for versioning). This action triggers on push to main (which creates a `dev` section of the docs), on publishing a release (which creates a numbered version of the docs), and on pull request edits (which makes a `pr-###` version of the docs).
After merging a pull request, it is a good idea to use [mike](https://github.com/jimporter/mike) to clear out the PR version of the docs. Locally, do something like the following
```
git fetch
mike delete pr-### # replace with correct PR number
git switch gh-pages
git push origin gh-pages
```
This could theoretically be automated but I decided against this for now. In the long run, it may be worth not generating PR versions of the docs if this is burdensome.
7 changes: 0 additions & 7 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,4 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.


import sys
import scipy.optimize as sp
import numpy as np
import math
import csv

from .lyopronto import *
Loading
Loading