Version: 0.3.0 Author: Olivier Vitrac, PhD, HDR Organization: INRAE + Generative Simulation Last Updated: January 2026
NOTE:
Surveyis a companion module ofSFPPyto offer a graphical user interface (web) equivalent to SFPP3, with several extensions (multiple steps and substances, queuing system, reporting, allSFPPyfunctionalities). It has been originally designed to run locally, but it can be deployed remotely (note that users and shared projects are not managed in the current version). The installation ofSFPPyrequires additional steps, in particular, for running the frontend interface.
- Overview
- Features at a Glance
- Installation & Launch
- User Interface Guide
- Tab Reference
- Session Files
- REST API Reference
- Export & Reports
- Offline Operation
- Workflow Examples
- Validation Against SFPPy Core
- Known Limitations
- Troubleshooting
SFPPy Studio is a web-based graphical user interface for the SFPPy (Safe Food Packaging in Python) framework. It provides an intuitive interface for food contact migration simulation and compliance checking, with support for offline operation and comprehensive safety assessment via ToxTree integration.
| Capability | Description |
|---|---|
| Multi-substance simulation | Simulate multiple migrants simultaneously with individual SML tracking |
| Multilayer packaging | Support for functional barriers, ABA structures, up to 5+ layers |
| Multi-step scenarios | Hot-fill → storage, set-off → contact, and complex temperature profiles |
| Restart functionality | Chain simulations from previous results |
| Parameter fitting | Fit D and k from experimental or synthetic migration data |
| Compliance checking | Automated SML comparison with margin calculations |
| Safety assessment | ToxTree Cramer class, genotoxicity alerts, DNA binding potential |
| Offline operation | Work without internet using cached substance data and images |
| Export & Reports | PDF reports, PNG/SVG plots with contact time markers, CSV, XLSX, JSON |
studio/
├── app/
│ ├── main.py # FastAPI application entry point
│ ├── routes/
│ │ ├── assembly.py # Layer & material management
│ │ ├── substances.py # PubChem integration, ToxTree, C0 management
│ │ ├── food.py # Food categories, simulants, geometry
│ │ ├── simulation.py # Patankar solver interface
│ │ ├── jobs.py # Background job management
│ │ ├── config.py # User preferences, solver settings
│ │ ├── exports.py # Multi-format export (CSV, XLSX, PDF, PNG, SVG)
│ │ ├── sessions.py # Session file management
│ │ └── fitting.py # Parameter fitting (D, k) from data
│ ├── templates/
│ │ └── index.html # Single-page application UI
│ └── static/
│ ├── js/
│ │ ├── app.js # Frontend JavaScript logic
│ │ ├── service-worker.js # Offline caching
│ │ └── offline-manager.js # Offline state management
│ ├── vendor/ # Vendored CDN dependencies
│ │ ├── chart.min.js # Chart.js for visualizations
│ │ ├── tailwind-offline.css # Offline CSS fallback
│ │ └── manifest.json # Vendor dependency manifest
│ └── img/ # Static images
├── data/
│ ├── polymers.yaml # Polymer database (Tg, Tm, Piringer params)
│ └── examples/ # Example .sfppy.json session files
├── config/ # User configuration storage
├── jobs/ # Simulation job storage
├── exports/ # Generated export files
├── tests/ # Test suite
├── launcher.py # CLI launcher script
└── version.py # Version information
| Feature | Status | Description |
|---|---|---|
| Multi-substance simulation | ✅ | Simulate multiple migrants with individual tracking |
| Multilayer assembly (1-5+ layers) | ✅ | Define complex packaging structures |
| Multi-step contact scenarios | ✅ | Hot-fill, storage, set-off sequences |
| Restart from previous results | ✅ | Chain simulations for complex scenarios |
| Real Patankar solver | ✅ | Finite-volume method for mass transfer |
| Mock results fallback | ✅ | Testing when SFPPy unavailable |
| CF₀ support | ✅ | Initial concentration in food |
| Background job execution | ✅ | Async simulation with progress tracking |
| Feature | Status | Description |
|---|---|---|
| ToxTree Cramer classification | ✅ | Class I/II/III toxicological concern |
| Genotoxicity alerts | ✅ | Structural alerts for genotoxic potential |
| DNA binding potential | ✅ | Prediction of DNA-reactive structures |
| TTC compliance | ✅ | Threshold of Toxicological Concern checking |
| Regulatory flags | ✅ | EU 10/2011, US FDA, CN GB authorization |
| Feature | Status | Description |
|---|---|---|
| 9-tab interface | ✅ | Substances, Assembly, Food, Simulate, Results, Jobs, Config, Fitting, Help |
| Server health indicator | ✅ | Real-time API status (green/yellow/red) |
| Task queue counter | ✅ | Shows pending/running jobs |
| Server restart button | ✅ | Quick server restart from UI |
| Dark/Light theme | ✅ | User preference toggle |
| Interactive charts | ✅ | Chart.js with zoom, pan, tooltips |
| Print-ready report modal | ✅ | White background for printing |
| Session load/save | ✅ | JSON session file management |
| Example sessions | ✅ | Built-in example configurations |
| Offline indicator | ✅ | Visual status when offline |
| Feature | Status | Description |
|---|---|---|
| CSV export | ✅ | Time series data |
| JSON export | ✅ | Complete simulation data |
| XLSX export | ✅ | Multi-sheet Excel workbook |
| PDF report | ✅ | Multi-page report with assumptions, plots, profiles |
| PNG export | ✅ | Raster plot with contact time markers |
| SVG export | ✅ | Vector plot with contact time markers |
| Report modal | ✅ | Browser-printable summary |
| Feature | Status | Description |
|---|---|---|
| CF(t) kinetics chart | ✅ | Migration concentration over time |
| C(x) profile chart | ✅ | Concentration distribution in layers |
| Multi-substance colors | ✅ | Distinct colors per substance |
| Contact time markers | ✅ | Vertical/horizontal lines with CF values |
| SML threshold lines | ✅ | Dashed lines showing limits |
| Compliance indicators | ✅ | Green/red status badges |
| Feature | Status | Description |
|---|---|---|
| Auto-compute |
✅ | Piringer model from polymer/T/MW |
| Auto-compute |
✅ | Partition coefficient estimation |
| Auto-compute |
✅ | Food partition from logP/simulant |
| Manual override |
✅ | Enter measured diffusivity |
| Manual override |
✅ | Enter measured partition coefficient |
|
|
✅ | Shows k/k₀ partition coefficient |
|
|
✅ | Hover shows k, k₀, K_{F/P} values |
- Python 3.10+ (required by SFPPy core)
- SFPPy core library (patankar module)
No Python installation required — just Docker.
# From SFPPy root directory
docker-compose -f docker/docker-compose.yml up sfppy-studioAccess at: http://localhost:8002
📌 Port can be changed in
docker/docker-compose.ymlor via:docker run -p 9002:8002 sfppy-studio
# Clone SFPPy
git clone https://github.com/ovitrac/SFPPy.git
cd SFPPy
# Install with Studio dependencies
pip install -e ".[studio]"
# Launch
python studio/launcher.py# Install core + studio requirements
pip install -r requirements/core.txt
pip install -r requirements/studio.txt# Create environment
conda create -n sfppy python=3.10 numpy scipy matplotlib pandas -y
conda activate sfppy
# Clone and install
git clone https://github.com/ovitrac/SFPPy.git
cd SFPPy
pip install -e ".[studio]"Core SFPPy (see requirements/core.txt):
| Package | Purpose |
|---|---|
numpy |
Numerical computation |
scipy |
Scientific computing (ODE solvers) |
matplotlib |
Visualization and PDF export |
pandas |
Data manipulation |
openpyxl |
Excel file support |
pillow |
Image processing |
Studio Web Application (see requirements/studio.txt):
| Package | Purpose |
|---|---|
fastapi |
Web API framework |
uvicorn |
ASGI server |
pydantic |
Data validation |
jinja2 |
HTML templating |
pyyaml |
YAML configuration parsing |
requests |
PubChem API access |
# From the SFPPy root directory
python studio/launcher.py
# With custom port
python studio/launcher.py --port 9002
# With auto-reload for development
python studio/launcher.py --reloadOptions:
| Option | Default | Description |
|---|---|---|
--port |
8002 | Server port (reconfigurable) |
--host |
127.0.0.1 | Host binding |
--reload |
off | Enable auto-reload for development |
Default URL: http://127.0.0.1:8002
The UI is organized into nine main tabs plus a top banner with status indicators:
| Element | Description |
|---|---|
| Health indicator | Green (healthy), Yellow (checking), Red (offline) |
| Queue counter | Number of pending/running simulation jobs |
| Restart button | Click to restart the server |
| Theme toggle | Switch between light/dark modes |
| Offline indicator | Shows when operating in offline mode |
| Tab | Icon | Purpose |
|---|---|---|
| Substances | 🧪 | Search, select, and configure chemical migrants |
| Assembly | 🧱 | Define multilayer packaging structure |
| Food | 🍽️ | Configure food type, geometry, and conditions |
| Simulate | Run simulation and manage sessions | |
| Results | 📊 | View charts, compliance status, export data |
| Jobs | 📁 | Manage background simulation jobs |
| Config | ⚙️ | User preferences and solver settings |
| Fitting | 📈 | Fit D and k from experimental data |
| Help | ❓ | Documentation and contextual help |
![]() |
![]() |
|---|
Purpose: Search, select, and configure chemical migrants with safety assessment.
| Feature | Description |
|---|---|
| PubChem Search | Search by name, CAS, or CID with autocomplete |
| Substance Cards | Display structure image, MW, logP, formula |
| Safety Assessment | ToxTree Cramer class, genotoxicity, DNA binding alerts |
| Regulatory Flags | Shows EU 10/2011, US FDA, CN GB authorization |
| C0 Matrix | Initial concentration per substance per layer |
| CF₀ Input | Initial concentration in food |
| D, k, k₀ Overrides | Override computed values with measured data |
| K_{F/P} Display | Hover shows partition coefficient breakdown |
| Structure Images | Local cache with PubChem fallback (offline-ready) |
Safety indicators displayed:
- Cramer Class: I (low), II (medium), III (high) toxicological concern
- Genotoxicity: Structural alerts for genotoxic potential
- DNA Binding: Prediction of DNA-reactive structures
- TTC Value: Threshold of Toxicological Concern (µg/person/day)
Purpose: Define the multilayer packaging structure from food-contact to outer layer.
| Feature | Description |
|---|---|
| Layer Count | 1-5+ layers supported |
| Material Selection | All polymers from patankar.layer database |
| Thickness Input | Value + unit selector (nm, µm, mm) |
| Tg Indicator | Glass transition temperature display |
| Layer Visualization | Color-coded by Tg (rubbery vs. glassy) |
| Substance Assignments | D, k per layer with auto/manual toggle |
| Presets | Monolayer, Bilayer, Trilayer quick-start examples |
| Drag/Reorder | Visual layer ordering from food contact to outer |
Layer order convention:
- Layer 1 = Food contact layer (nearest to food)
- Layer N = Outer layer (furthest from food)
Purpose: Configure food type, simulant, geometry, and contact conditions.
| Feature | Description |
|---|---|
| Food Categories | Fatty, Aqueous, Acidic, Alcoholic, Dry |
| EU Simulants | A (ethanol 10%), B (acetic acid 3%), C (ethanol 20%), D1 (ethanol 50%), D2 (vegetable oil), E (MPPO) |
| Geometry Shapes | Cylinder, Bottle, Rectangle, Pouch, Sphere |
| Dimensions | Automatic V/S ratio calculation |
| Multi-step Contacts | Define temperature/time profiles |
| Condition Presets | EU Standard (10d/40°C), Accelerated, Hot-fill, etc. |
Geometry parameters:
- Volume (V): Total food volume in contact
- Surface (S): Contact surface area
- V/S ratio: Critical parameter for migration calculation
Purpose: Configure and launch simulation runs.
| Feature | Description |
|---|---|
| Session Management | Load/save .sfppy.json configurations |
| Example Sessions | Built-in example configurations to load |
| Restart Control | Enable chaining from previous simulation results |
| Solver Settings | Time steps, mesh refinement, tolerance |
| Run Button | Start async simulation with progress tracking |
| Validation Check | Pre-run validation of configuration |
Purpose: Visualize simulation results and assess compliance.
| Feature | Description |
|---|---|
| CF(t) Kinetics | Migration concentration over time chart |
| C(x) Profiles | Concentration distribution across layers |
| Compliance Status | Green/red badges per substance vs. SML |
| Key Value Cards | Per-substance CF, SML, margin summary |
| Contact Markers | Vertical/horizontal lines at t_contact |
| Export Buttons | CSV, XLSX, JSON, PDF, PNG, SVG |
| Report Modal | Print-ready detailed report |
Compliance calculation:
- Margin = (SML - CF) / SML × 100%
- Green: CF < SML (compliant)
- Red: CF ≥ SML (non-compliant)
Purpose: Manage background simulation jobs.
| Feature | Description |
|---|---|
| Job List | All simulation jobs with status |
| Status Indicators | Pending, Running, Completed, Failed |
| Progress Bar | Real-time progress for running jobs |
| Delete Jobs | Clean up old/unwanted jobs |
| Job Details | Full configuration and results access |
| Auto-refresh | Automatic status updates |
Purpose: User preferences and solver configuration.
| Feature | Description |
|---|---|
| Theme Selection | Light/Dark mode preference |
| Default Polymer | Pre-selected material for new layers |
| Solver Precision | Time step and mesh settings |
| Cache Management | Clear local caches |
| Version Info | Studio and SFPPy version display |
| Traceability | Machine info for audit trails |
Purpose: Fit diffusion (D) and partition (k) coefficients from data.
| Feature | Description |
|---|---|
| Synthetic Data | Generate CF(t) with known D, k plus noise |
| Experimental Data | Enter time-concentration pairs manually |
| CSV Upload | Load data from file |
| Parameter Fitting | L-BFGS-B optimization algorithm |
| Initial Guesses | Configure starting values |
| Fit Quality | R², RMSE metrics display |
| Comparison Plot | Data points vs. fitted curve |
Fitting workflow:
- Load or generate reference data
- Set initial guesses for D and k
- Run optimization
- Review fit quality and residuals
- Apply fitted values to simulation
Purpose: Documentation and contextual assistance.
| Feature | Description |
|---|---|
| Quick Start Guide | Step-by-step getting started |
| Tab Documentation | Context-sensitive help per tab |
| Keyboard Shortcuts | Available shortcuts list |
| API Documentation | Link to Swagger UI |
| Example Walkthroughs | Guided example sessions |
| Troubleshooting | Common issues and solutions |
SFPPy Studio uses .sfppy.json files for saving/loading complete configurations:
{
"version": "1.0",
"metadata": {
"name": "Example 1: LDPE Film Migration",
"description": "Migration from 100 um LDPE film",
"author": "INRAE/[email protected]"
},
"geometry": {...},
"substances": [...],
"layers": [...],
"food": {...},
"contact_steps": [...],
"simulation_config": {...},
"results": {...},
"restart_state": {...}
}| Example | Description | Layers | Steps |
|---|---|---|---|
| Example 1 | LDPE Film Migration | 1 | 1 |
| Example 1 Extensions | Two-Step Migration | 1 | 2 |
| Example 3 | Trilayer ABA Migration | 3 | 3 |
Base URL: http://127.0.0.1:8002/api
Interactive documentation: http://127.0.0.1:8002/docs (Swagger UI)
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Main application HTML |
| GET | /api/info |
API version and module info |
| GET | /api/health |
Health check (status, response time) |
| GET | /api/debug/pubchem-cache |
Debug PubChem cache status |
| Method | Endpoint | Description |
|---|---|---|
| GET | /polymers |
List all polymers |
| GET | /polymers/{code} |
Polymer details |
| GET | /materials |
List all materials |
| GET | /materials/{code} |
Material details |
| GET | /materials/{code}/tg |
Glass transition temperature |
| POST | /validate |
Validate assembly |
| POST | /estimate |
Estimate D, k |
| Method | Endpoint | Description |
|---|---|---|
| GET | /search?q=... |
PubChem search |
| GET | /common |
Common food contact substances |
| GET | /pubchem/{cid} |
Substance by CID |
| GET | /detail/{query} |
Full details + ToxTree assessment |
| GET | /regulatory/{query} |
EU/US/CN authorization |
| GET | /sml/{cas} |
SML by CAS number |
| GET | /thumbnail/{cid} |
Structure image (PubChem) |
| GET | /structure/{cid}.png |
Structure image (local cache) |
| GET | /structure/available |
List cached structure CIDs |
| Method | Endpoint | Description |
|---|---|---|
| GET | /categories |
Food categories |
| GET | /simulants |
All simulants |
| GET | /simulants/{category} |
Simulants for category |
| GET | /shapes |
Geometry shapes |
| GET | /conditions/presets |
Condition presets |
| POST | /geometry/calculate |
Calculate V, S, V/S |
| Method | Endpoint | Description |
|---|---|---|
| POST | /run |
Start simulation (async) |
| GET | /status/{job_id} |
Job status |
| GET | /results/{job_id} |
Full results |
| DELETE | /cancel/{job_id} |
Cancel job |
| GET | /presets |
Simulation presets |
| Method | Endpoint | Description |
|---|---|---|
| GET | /list |
List all jobs |
| GET | /detail/{job_id} |
Job details |
| DELETE | /delete/{job_id} |
Delete job |
| DELETE | /clear |
Delete old jobs |
| GET | /stats |
Job statistics |
| Method | Endpoint | Description |
|---|---|---|
| GET | /formats |
Available formats |
| GET | /{job_id}/csv |
Export CSV |
| GET | /{job_id}/json |
Export JSON |
| GET | /{job_id}/xlsx |
Export Excel |
| GET | /{job_id}/pdf |
Export PDF report |
| GET | /{job_id}/png |
Export PNG plot |
| GET | /{job_id}/svg |
Export SVG plot |
| Method | Endpoint | Description |
|---|---|---|
| POST | /create |
Create session |
| GET | /list |
List sessions |
| GET | /{session_id} |
Session details |
| DELETE | /{session_id} |
Delete session |
| POST | /{session_id}/substances |
Add substance |
| POST | /{session_id}/assignments |
Set C0 assignment |
| POST | /{session_id}/layers |
Add layer |
| POST | /{session_id}/steps |
Add contact step |
| GET | /files/examples |
List examples |
| GET | /files/load/{name} |
Load example |
| GET | /compute/diffusivity |
Compute D |
| Method | Endpoint | Description |
|---|---|---|
| POST | /synthetic/generate |
Generate synthetic data |
| POST | /experimental/load |
Load experimental data |
| POST | /fit |
Run fitting optimization |
| GET | /job/{job_id} |
Fitting job results |
| GET | /jobs |
List fitting jobs |
| GET | /presets |
Fitting presets |
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Full configuration |
| PUT | / |
Update configuration |
| GET | /user |
User profile |
| GET | /solver |
Solver settings |
| GET | /traceability |
Version info |
The PDF export generates a multi-page report:
| Page | Content |
|---|---|
| 1 | Summary: Job info, results table, assembly config, geometry, food simulant |
| 2 | Detailed Assumptions: C0 per layer, D, k, k₀, K_{F/P} per substance |
| 3 | Migration Kinetics: CF(t) plot with contact time markers |
| 4+ | Concentration Profiles: C(x) plots per substance |
All exports (PDF, PNG, SVG) include:
- Vertical line from x-axis to CF curve at t_contact
- Horizontal line from curve to y-axis at CF(t_contact)
- Dot at the intersection point
- Labels showing CF value near y-axis and t_c near x-axis
The in-browser report modal includes:
- Substances table with C0, D, k, safety assessment
- Layers table with polymers and thicknesses
- Food & Geometry section with V, S, V/S ratio
- Print-ready white background
SFPPy Studio v0.3.0 introduces full offline capability for environments without internet access.
| Feature | Description |
|---|---|
| Service Worker | Caches static assets and API responses |
| Local Structure Images | ~950 cached structure images from PubChem |
| Offline CSS | Pre-compiled Tailwind CSS fallback |
| Vendored Chart.js | Local Chart.js library |
| Offline Indicator | Visual status in UI header |
| Strategy | Used For |
|---|---|
| CacheFirst | Static assets, substance data, polymer lists |
| NetworkFirst | Jobs, sessions (dynamic but cached) |
| NetworkOnly | Simulation runs, fitting (must execute on server) |
Structure images are served from:
- Local cache:
patankar/cache.PubChem/thumbs/{cid}.png - Fallback: PubChem CDN (if online)
To check available cached images:
curl http://127.0.0.1:8002/api/substances/structure/availableClear caches via the Config tab or programmatically:
// From browser console
navigator.serviceWorker.controller.postMessage({type: 'CLEAR_CACHE'});- Substances Tab: Add "Irganox 1076" and "BHT"
- Assembly Tab: Select "Monolayer LDPE" preset
- Substances Tab: Set C0 = 1000 mg/kg for both in Layer 1
- Food Tab: Select "Fatty foods" → "EU Standard Test"
- Simulate Tab: Click "Run Simulation"
- Results Tab: View both substances in CF(t) chart with individual colors
- Assembly Tab: Add 2 layers
- Layer 1: gPET, 20 µm (barrier)
- Layer 2: LDPE, 100 µm
- Substances Tab: Set C0 = 0 for L1, C0 = 1000 for L2
- Run simulation and observe lag time
- Food Tab: Use "Hot Fill" preset
- Step 1: 30 min at 85°C
- Step 2: 6 months at 25°C
- Run simulation with multi-step scenario
- Substances Tab: Search and add substance
- Review ToxTree assessment:
- Cramer Class (I/II/III)
- Genotoxicity alerts
- DNA binding potential
- Check TTC compliance
- Proceed with simulation if safe
SFPPy Studio has been validated against the SFPPy core examples to ensure numerical accuracy. All simulations use CFtarget (concentration at the specified contact time) for consistency.
| Example | Test Case | Core CF (mg/kg) | Studio CF (mg/kg) | Error |
|---|---|---|---|---|
| Example 1 | Monolayer LDPE, 10d @ 7°C | 5.2269 | 5.2269 | <0.01% |
| Example 1 Ext | + 4h @ 25°C (chained) | 5.5643 | 5.5643 | <0.01% |
| Example 2 | PP 300µm, no FB, 450d @ 20°C | 0.1827 | 0.1836 | 0.46% |
| Example 2 | With 30µm PET barrier | 0.1080 | 0.1082 | 0.21% |
| Example 3 | Trilayer ABA, 3-step | 0.9730 | 0.9543 | 1.92% |
Legend:
- Example 1: Irganox 1076 in LDPE film migrating to fatty food
- Example 1 Ext: Two-step simulation with temperature change (chained using
>>operator) - Example 2: Toluene surrogate in PP bottle with/without PET functional barrier
- Example 3: Limonene in wPET/PP/gPET trilayer with set-off → hot-fill → storage sequence
-
Simulation Chaining: Multi-step scenarios use the
>>operator pattern from SFPPy core- Step 1:
multilayer >> food(initial simulation) - Step 2+:
previous_result >> food(chains with CF0 propagation)
- Step 1:
-
Set-off Boundary Conditions: Stacked/rolled configurations supported via
setoffclasses -
Temperature-Dependent D: Diffusivity is recalculated at each step's temperature via the
food >> layeroperator -
CFtarget vs CF[-1]: Studio uses
CFtarget(concentration at contact time) for all compliance calculations, matching the scientific kernel's intended behavior
cd studio
python tests/test_validation.py| Area | Limitation |
|---|---|
| D computation | Temperature from first step only |
| Materials | Some paper/board materials incomplete |
| Simulants | Fixed list, no custom simulants |
| Fitting | Single-layer only (the core tools of SFPPy are not limited) |
| UI | No layer drag-and-drop reordering |
| Offline | ToxTree requires initial online query to cache |
- Temperature-dependent D per time step
- Batch simulation mode
- Uncertainty analysis (Monte Carlo)
- Database of measured D, k values
- Integration with EU FCM database
- Full offline ToxTree with local SMARTS rules
Server won't start: "Port already in use"
lsof -i :8002 # Find process
python studio/launcher.py --port 8003 # Use different portSubstance search returns nothing
- Check internet connection (PubChem API)
- Try CID directly: "7519" instead of name
- Use offline cached substances if available
Structure images not loading
- Check local cache:
ls patankar/cache.PubChem/thumbs/ - Verify API:
curl http://127.0.0.1:8002/api/substances/structure/available
Export fails
- Check matplotlib for PNG/SVG
- Check openpyxl for XLSX
Offline mode not working
- Ensure service worker is registered (check browser DevTools)
- Clear browser cache and reload
python studio/launcher.py --reloadAPI docs: http://127.0.0.1:8002/docs
Debug endpoint: http://127.0.0.1:8002/api/debug/pubchem-cache
Author: Olivier Vitrac, PhD, HDR Email: [email protected] Organization: INRAE + Generative Simulation
SFPPy Studio v0.3.0 - January 2026










