Skip to main content

PolyNet

Python License PyTorch PyG RDKit Tests PyPI DOI Black Poetry Status

PolyNet logo

PolyNet is a Python library for polymer property prediction using graph neural networks (GNNs) and traditional machine learning (TML). It provides a complete, configurable pipeline — from raw SMILES strings to trained models, evaluation metrics, result plots, and atom-level explainability — designed for polymer informatics research.

The library is split into two layers:

  • Core package (polynet) — pipeline stages, model training/inference, featurisers, config schemas, and path/IO helpers. No Streamlit dependency; importable from any Python script or notebook.
  • Optional GUI (polynet.app) — a Streamlit web application that wraps the same core stages. Install only when you want an interactive interface.

Both entry points call the same underlying functions and produce identical results.


Overview

Predicting polymer properties from chemical structure is challenging because polymers are repeating units of one or more monomers combined in varying ratios. PolyNet handles this by representing each polymer as a graph where atoms are nodes, bonds are edges, and per-monomer molar ratios (normalised to sum to 1 across the participating monomers) are encoded as node attributes. This graph is fed into GNN architectures that learn structure–property relationships directly from the molecular graph.

PolyNet also supports traditional ML workflows using molecular descriptor vectors (RDKit descriptors, PolyBERT fingerprints, and others), enabling direct comparison between GNN and TML approaches on the same dataset and splits.


Features

  • Six GNN architectures — GCN, GAT, CGCNN, MPNN, GraphSAGE, TransformerGNN — each with regression and classification variants
  • Traditional ML — Random Forest, XGBoost, SVM, Logistic Regression, Linear Regression, with optional automatic hyperparameter search (RandomizedSearchCV scored by shuffled, user-set k-fold cross-validation)
  • Molecular fingerprints — Morgan and RDKit count fingerprints with configurable size and Morgan radius (defaults: 2048 bins, radius 3), alongside RDKit descriptors, PolyBERT and PolyMetriX
  • Multi-monomer polymers — handles copolymers with any number of monomers and molar ratios; ratios are normalised per polymer to sum to 1 across the participating monomers (any scale works — fractions, percentages, or arbitrary ratios such as 1:1:2), and ratio-0 monomers are excluded from the graph entirely so homopolymers written as (monomer, 100/0) are invariant to the empty SMILES column
  • Per-monomer pooling — PerMonomerPooling weighting mode pools each monomer's nodes separately and combines them as Σ wᵢ·pool(monomerᵢ), removing the atom-count bias that arises when weighting before pooling on mixed-size copolymers (wD-MPNN-style weighted-mean pooling is also supported)
  • PSMILES attachment-point handling — opt-in IsAttachmentPoint atom feature strips * (wildcard) atoms from the graph and flags the atoms that were attached to them, replacing dangling pseudo-element nodes with an explicit boolean marker
  • PolyMetriX descriptors — polymer-aware chemical descriptors (molecular weight, ring counts, TPSA, etc.) computed on the full repeat unit, side chain, or backbone, with configurable aggregation; three modes — side_chain, backbone, and polymer — can be used in any combination
  • Automatic HPO — Ray Tune for GNNs with configurable split strategy (cross-validation, holdout, repeated holdout; ASHA early stopping for holdout-based strategies); configurable number of sampled configurations (default 50 for GNNs and traditional ML) and custom search grids — in YAML or the GUI — that override individual parameters of the default grids; results cached per search settings and saved with the experiment
  • Configurable GNN training — optimiser (Adam, SGD, RMSprop, Adadelta, Adagrad), learning-rate scheduler (ReduceLROnPlateau, step, multi-step, exponential) and regression loss (RMSE, MSE, MAE), applied identically to final training and HPO
  • Data splitting with astartes — train/val/test splits drawn with an astartes sampler: random (default), Kennard–Stone, SPXY, k-means or target-property, optionally stratified by class; fingerprint samplers use a ratio-weighted polymer fingerprint (Morgan, RDKit or polyBERT) whose type and settings are chosen for splitting only, and the sampling settings are saved with the experiment
  • Repeated random splits and ensembles — configurable number of train/val/test splits (n_bootstrap_iterations); predictions on new data are combined across the splits into ensembles per GNN architecture, across all GNNs, and per TML model × representation, reported as mean ± standard deviation (regression) or majority vote with vote fraction (classification), with metrics for each ensemble
  • Structure validation — SMILES/PSMILES are validated and canonicalised the same way in the GUI, the CLI and when predicting new data; invalid or missing structures and duplicated sample IDs are reported with examples
  • Target variable scaling — six scaling strategies for regression targets (StandardScaler, MinMaxScaler, RobustScaler, Log₁₀, Log(1+y), or none); scaler is fit on the training set only and automatically inverse-transformed before metrics and plots so all results are reported in the original target units
  • Polymer descriptor fusion — user-supplied experimental or computed polymer-level features (e.g. molecular weight, chain length) can be concatenated to vectorial descriptor representations and, for GNN models, fused into the graph embedding after pooling so the FFN receives both learned and given features; for GNNs they are scaled with the pipeline's feature scaler, fitted on the training split
  • GNN fragment-level explainability — chemistry-masking attribution (substructure masking; Wu et al., Nat. Commun. 14, 2585 (2023), doi:10.1038/s41467-023-38192-3): each fragment's importance is measured as the change in prediction when that fragment is masked from the graph pooling step; fragments come from BRICS or Murcko-scaffold fragmentation and attributions are aggregated per fragment; supports global distribution plots (ridge, bar, strip) and per-molecule attribution heatmaps
  • TML SHAP explainability — SHAP-based attribution for all traditional ML models using auto-selected explainers (TreeExplainer for RF/XGBoost, LinearExplainer for linear models, KernelExplainer for SVM); global summaries and per-instance plots are rendered with the native shap package (beeswarm / bar / violin and waterfall / force / bar); SHAP values are cached to CSV and reused across runs
  • Configurable explanation display — view local explanations averaged across the model ensemble or as one plot per model × molecule, with selectable attribution normalisation (local / per-model / global / none)
  • Statistical model comparison — pairwise McNemar (classification) and Wilcoxon signed-rank tests on absolute errors (regression) on the Analyse Results page; metric-level comparison across repeated splits with Wilcoxon or the Nadeau–Bengio corrected resampled t-test; multiple-comparison correction (Holm-Bonferroni, Bonferroni, Benjamini-Hochberg)
  • Publication-quality plots — parity plots, ROC curves, confusion matrices, learning curves, and attribution heatmaps
  • Single-command pipeline — YAML config file drives the entire workflow; no code changes between experiments
  • GUI-independent core — all pipeline stages are importable from polynet without Streamlit

Installation

PolyNet requires Python 3.11. Install it from PyPI to use it, or from source with Poetry to develop it.

Create a Python 3.11 environment with conda:

conda create -n polynet python=3.11
conda activate polynet

or with venv:

python3.11 -m venv .venv
source .venv/bin/activate      # macOS / Linux
.venv\Scripts\activate         # Windows

Then install PolyNet:

pip install polynet

On macOS, XGBoost also needs the OpenMP library from Homebrew: brew install libomp.

This installs the polynet command: polynet opens the GUI and polynet run --config experiment.yaml runs the pipeline (see Quick Start below).

Option 2 — From source with Poetry (development)

Step 1 — Clone the repository

git clone https://github.com/Biomaterials-for-Medical-Devices-AI/PolyNet.git
cd PolyNet

Step 2 — Create a Python 3.11 environment

As in Option 1 (conda or venv).

Step 3 — Install Poetry

With the environment active, install Poetry via pip:

pip install poetry

Then tell Poetry to use the active environment rather than creating its own:

poetry config virtualenvs.create false --local

Step 4 — Install the project

poetry install

Poetry reads pyproject.toml and poetry.lock and installs the exact dependency versions the project is developed and tested with, plus the development tools. pip install polynet instead takes the newest versions pyproject.toml allows. When developing the GUI, see Running the GUI while developing.

PSMILES support

PolyNet canonicalises PSMILES (polymer SMILES with * attachment points) with canonicalize-psmiles from the Kuenneth group. It is distributed by Georgia Tech Research Corporation under its own licence, which allows non-commercial use only, and is not on PyPI, so it is installed separately from PolyNet's MIT-licensed code:

  • poetry install (Option 2) installs it; pip install polynet does not.
  • In the GUI, loading PSMILES data offers an Install canonicalize-psmiles button after you accept its licence.
  • From a terminal: polynet install-psmiles.

Datasets written as plain SMILES do not need it.

Verifying the installation

polynet check

This runs the whole pipeline on a small synthetic dataset (about a minute) and prints a PASS / FAIL table.

Common Poetry commands

Command Description
poetry install Install all dependencies from poetry.lock
poetry add <package> Add a new dependency
poetry update Update all dependencies within the version constraints
poetry run python <script> Run a script without manually activating the environment

Dependencies (managed by Poetry): PyTorch, PyTorch Geometric, RDKit, scikit-learn, XGBoost, imbalanced-learn, Ray Tune, Captum, Streamlit, Pydantic, matplotlib, seaborn, scipy, statsmodels, and more — see pyproject.toml for the full list.


Quick Start

CLI

1. Edit the config file to point at your data and choose your models. The template configs/experiment.yaml runs out of the box on the built-in Tg benchmark (benchmark_dataset: "curated_tg", downloaded on first use); to use your own data, replace it with data_path. If you installed from PyPI, download the template from GitHub:

# configs/experiment.yaml
experiment:
  name: "tg_prediction"
  output_dir: "results/tg_prediction"
  random_seed: 42

data:
  data_path: "data/polymers.csv"
  id_col: "polymer_id"
  target_variable_col: "Tg"
  target_variable_name: "Glass Transition Temperature"
  problem_type: "regression"
  smiles_cols:
    - "monomer1_smiles"
    - "monomer2_smiles"

2. Run the pipeline:

polynet run --config configs/experiment.yaml

All outputs are written to the directory specified by experiment.output_dir in the config. polynet run --help lists the flags (e.g. --epochs, --no-gnn, --predict-data).

Streamlit GUI

polynet

This works from any directory once the package is installed (polynet gui is the same). Any streamlit run option is forwarded, so polynet --server.port 8502 changes the port. When developing PolyNet, run polynet --server.fileWatcherType auto so the app reloads on save (see Development). From the repository root, the explicit command also works:

streamlit run polynet/app/Welcome_to_PolyNet.py

Python API

The core stages can be called directly from any script or notebook:

from polynet.pipeline import (
    build_graph_dataset,
    compute_descriptors,
    compute_data_splits,
    train_gnn,
    run_gnn_inference,
    train_tml,
    run_tml_inference,
    compute_metrics,
    predict_external,
)
from polynet.config.io import save_options, load_options
from polynet.config.paths import polynet_experiments_base_dir, model_dir
from polynet.experiment.manager import get_experiments, create_experiment
from polynet.models.persistence import load_models_from_experiment
from polynet.inference.predict import predict_unseen_tml, predict_unseen_gnn

Data Format

PolyNet expects a CSV file with one row per polymer sample:

Column Required Description
polymer_id Recommended Unique identifier (used as sample index)
monomer1_smiles Yes SMILES string for the first monomer
monomer2_smiles Yes (copolymers) SMILES string for the second monomer
ratio_1 No Molar ratio of monomer 1. Omit to treat monomers as equally weighted
ratio_2 No Molar ratio of monomer 2
target Yes Property to predict (numeric for regression, integer class for classification)

Copolymers with any number of monomers are supported by adding one SMILES column and one molar-ratio column per monomer and listing them in the config. Ratios are normalised per polymer to sum to 1 across the participating monomers, so they need not sum to 1 or 100; a ratio of 0 excludes that monomer. The target column is optional when predicting on unseen data.


Documentation

Full documentation lives in docs/:

  • Configuration reference — every YAML section, including automatic HPO
  • Descriptors — polymer descriptor fusion and the PolyMetriX integration
  • Explainability — GNN masking & TML SHAP attribution, normalisation, averaged vs per-model display, and statistical model comparison
  • Running the pipeline & outputs — CLI flags, predicting on external data, target scaling, and the output directory layout
  • API reference — project structure and the public Python API
  • GUI & architecture — the Streamlit application and the core-vs-GUI design
  • Development — running the test suite and extending PolyNet

Team

Citing PolyNet

If you use PolyNet, please cite the software (GitHub's "Cite this repository" button reads CITATION.cff):

@software{polynet,
  author  = {Aguilar-Bejarano, Eduardo and Alexander, Morgan and Winkler, David and Figueredo, Grazziela},
  title   = {PolyNet: A Python Package for Polymer Informatics},
  version = {1.0.3},
  year    = {2026},
  doi     = {10.5281/zenodo.23302984},
  url     = {https://github.com/Biomaterials-for-Medical-Devices-AI/PolyNet}
}

This DOI always resolves to the latest release. To cite the exact version you used, take its DOI from the Zenodo record (1.0.0: 10.5281/zenodo.23302985).

Changes between versions are listed in CHANGELOG.md.

Metadata

Release files for polynet 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for polynet 1.0.3
File Size Uploaded
polynet-1.0.3.tar.gz 1.3 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for polynet 1.0.3
File Interpreter ABI Platform
polynet-1.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 2.7 MB

Release files / polynet-1.0.3.tar.gz

Download URL polynet-1.0.3.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
0c1ecb6a89c86dec73e0651601fe1f753e243570afccf803fe27724b417293e6
BLAKE2b-256 checksum
How to use checksums
bb8dae92cd5bb07bc6729c920b43d82d901c4e2ecd237159e5de9aeeb675b0c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / polynet-1.0.3-py3-none-any.whl

Download URL polynet-1.0.3-py3-none-any.whl
Size 1.4 MB
Tags Python 3
SHA-256 checksum
How to use checksums
b89bca86577676a1d31a510a2fad39fe9cbce84d490ea3f9a163dd387ff179b7
BLAKE2b-256 checksum
How to use checksums
262710f3514ddc23ee92faf733f3b74ef56c5df6ab03a5f01d82e615422a397c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.3 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page