Skip to content

fix(drug_discovery): operator input widths default to the featurizer's - #48

Merged
mahdi-shafiei merged 2 commits into
mainfrom
fix/featurizer-width-defaults
Nov 8, 2026
Merged

mahdi-shafiei merged 2 commits into
mainfrom
fix/featurizer-width-defaults

Conversation

@mahdi-shafiei

Copy link
Copy Markdown
Collaborator

Summary

 primitives.py
-  NUM_BOND_FEATURES = 4
+  DEFAULT_BOND_FEATURES = 4          (exported beside DEFAULT_ATOM_FEATURES)
 MolecularPropertyConfig, ADMETConfig, MACCSKeysConfig, CircularFingerprintConfig,
 MolecularFingerprintConfig, MessagePassingLayer, StackedMessagePassing
-  in_features = 4, num_edge_features = 4
+  in_features = DEFAULT_ATOM_FEATURES, num_edge_features = DEFAULT_BOND_FEATURES
 AttentiveFPConfig
-  in_features = 39, edge_dim = 10
+  in_features = DEFAULT_ATOM_FEATURES, edge_dim = DEFAULT_BOND_FEATURES

Closes DB-078. Every drug-discovery operator's default input width is now the graph builder's width, written as its symbol, the way chemprop derives DEFAULT_ATOM_FDIM from its featurizer (chemprop/conf.py, constructor default in nn/message_passing/base.py). Before, the defaults were 4 and 4, so a default config raised a shape error on any smiles_to_graph molecule, and several docstrings documented 34 for the same field.

Two commits:

  1. A rename, NUM_BOND_FEATURES to DEFAULT_BOND_FEATURES, with no behavior change.
  2. The defaults, their tests, and the callers, fixtures and docs that relied on 4.

This is the foundation for the AttentiveFP featurization PR: once the defaults follow the featurizer, that change touches no config.

Evidence

Before: tests/operators/drug_discovery/test_default_widths.py, 13 of 14 failed. Every default config was 4 (or 39) against the featurizer's 34, and every default operator raised dot_general requires contracting dimensions to have the same shape, got (34,) and (4,) on aspirin.

After: 14 of 14 pass. Each config default equals the symbol, and each operator and both message-passing modules, built with defaults, run on aspirin to finite outputs.

A first draft asserted a num_edge_features attribute that StackedMessagePassing doesn't store. It was rewritten to specify behavior: the module runs on a real molecule, which fails on the old defaults and passes on the new ones.

Fixtures: molecular_graph and batch_molecular_graphs hand-encoded "ethanol" with a 4-feature one-hot (C, N, O, other) matching the old default, not the graph builder. They now come from smiles_to_graph("CCO") and batch_smiles_to_graphs(["CCO", "CC"]). The JIT, gradient and vmap tests in test_drug_discovery.py (jax.jit, nnx.grad, jax.grad, jax.vmap) therefore run on real graphs at the default widths: 56 of 56 pass.

Gate: soft ops, drug discovery, the DTI and MolNet benchmark tests, and integration: 637 passed. pre-commit run --all-files passes all 24 hooks, and mkdocs build --strict passes.

Merge Danger

Door: two-way.

Blast Radius: default widths.

  • Default construction: code that built an operator with default widths gets a model sized for the graph builder's 34 and 4 features, where it used to get 4 and 4. That code could only have run on hand-built 4-feature inputs before. AttentiveFP's default goes from 39/10 to the builder's width.
  • Speed: no traced code changes. Models built with explicit widths compute exactly as before.
  • Siblings: kinase-challenge passes its own NODE_FEATURES and EDGE_FEATURES to StackedMessagePassing (multitask.py:98-99), and receptifex uses only similarity; neither is affected.
  • Docs: the user guide's tables now name the symbols, and its examples and scripts/_advanced_plots.py stop hand-passing widths.

…ATURES

The graph builder's bond-feature width was NUM_BOND_FEATURES beside the
atom width DEFAULT_ATOM_FEATURES. It is renamed to match, ahead of the
operators taking their default edge width from it. No behaviour changes.
The drug-discovery operators' input widths defaulted to 4 atom and 4
bond features, while smiles_to_graph produces DEFAULT_ATOM_FEATURES and
DEFAULT_BOND_FEATURES. Several docstrings documented 34 for the same
field, so a default MolecularPropertyConfig, ADMETConfig,
MACCSKeysConfig, CircularFingerprintConfig, MolecularFingerprintConfig
or message-passing layer raised a shape error on a real molecule, and
AttentiveFPConfig defaulted to the AttentiveFP paper's 39 and 10. Each
default is now the featurizer's symbol, the way chemprop derives its
model width from its featurizer, so the two cannot disagree.
DEFAULT_BOND_FEATURES is exported beside DEFAULT_ATOM_FEATURES.

The shared test fixtures hand-encoded ethanol with a 4-feature one-hot
that matched the old default rather than the graph builder; they now
come from smiles_to_graph and batch_smiles_to_graphs, so the jit, grad
and vmap tests run on real graphs at the default widths. The user
guide's tables and examples, and the AttentiveFP plot script, use the
defaults instead of hand-passed widths.
@mahdi-shafiei
mahdi-shafiei marked this pull request as ready for review November 8, 2026 16:32
@mahdi-shafiei
mahdi-shafiei merged commit c13e3a9 into main Nov 8, 2026
14 checks passed
@mahdi-shafiei
mahdi-shafiei deleted the fix/featurizer-width-defaults branch November 8, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant