schrodinger.application.matsci.martini3_ff module

Martini 3 force-field parameterization and coarse-grained mapping.

Combines nonbond parameter loading + shifted-potential fits with the Martini 3 mapping logic and lipid mapper. Bead-type taxonomy lives in the dependency-free martini3_types module.

Reference: Souza, P.C.T. et al. Martini 3: a general purpose force field for coarse-grained molecular dynamics. Nature Methods 18, 382-388 (2021).

Copyright Schrodinger, LLC. All rights reserved.

schrodinger.application.matsci.martini3_ff.resolve_martini_ff_type(ff_type_str)

Resolve a force field type string to a canonical Martini version constant.

Handles legacy ‘martini’ alias, returning MARTINI for backward compatibility. Returns the input unchanged if it is not a Martini type.

Parameters:

ff_type_str (str) – raw force_field_type value from JSON

Return type:

str

Returns:

canonical Martini version constant, or original string

schrodinger.application.matsci.martini3_ff.loadMartini3NonbondParams()

Load and cache the Martini 3 pairwise nonbond parameters.

Reads the three shard files martini3_nonbond_params_1.json, martini3_nonbond_params_2.json, and martini3_nonbond_params_3.json and merges their pairs mappings into a single in-memory cache.

The cache maps ‘TYPE1,TYPE2’ (alphabetically sorted pair key) to a (sigma_angstrom, epsilon_kcal) tuple.

Return type:

dict

Returns:

mapping of pair key to (sigma, epsilon) tuple

schrodinger.application.matsci.martini3_ff.get_martini3_sigmas()

Return the allowed Martini 3 sigma values.

Return type:

list(float)

Returns:

Sigma values in ascending order, in Angstrom

schrodinger.application.matsci.martini3_ff.get_martini3_compatible_type(bead_type)

Return the Martini 3 type corresponding to a Martini 2 bead type.

Parameters:

bead_type (str) – Martini bead type

Return type:

str

Returns:

Martini 3-compatible bead type, or the original type when it is not in the Martini 2 compatibility table

schrodinger.application.matsci.martini3_ff.getMartini3Epsilon(type1, type2)

Return the Martini 3 epsilon for a bead-type pair.

Parameters:
  • type1 – first Martini 3 bead type or supported legacy type

  • type2 – second Martini 3 bead type or supported legacy type

Return type:

float

Returns:

epsilon in kcal/mol

Raises:

KeyError – if the pair is not in the parameter database

schrodinger.application.matsci.martini3_ff.getMartini3Sigma(type1, type2)

Return the Martini 3 sigma for a bead-type pair.

Parameters:
  • type1 – first Martini 3 bead type or supported legacy type

  • type2 – second Martini 3 bead type or supported legacy type

Return type:

float

Returns:

sigma in Angstrom

Raises:

KeyError – if the pair is not in the parameter database

schrodinger.application.matsci.martini3_ff.getMartini3NonbondPair(type1, type2)

Return both sigma and epsilon for a Martini 3 bead-type pair.

Parameters:
  • type1 – first Martini 3 bead type or supported legacy type

  • type2 – second Martini 3 bead type or supported legacy type

Return type:

tuple(float, float)

Returns:

(sigma_angstrom, epsilon_kcal)

Raises:

KeyError – if the pair is not in the parameter database

schrodinger.application.matsci.martini3_ff.clearMartini3NonbondCache()

Clear the Martini 3 nonbond parameter cache.

Useful for testing or after modifying the underlying JSON file.

schrodinger.application.matsci.martini3_ff.computeShiftedLJFitCoefficients(sigma, m_exp=12, n_exp=6, r_shift=9.0, r_cutoff=12.0)

Compute polynomial_cij fit coefficients for a shifted Lennard-Jones potential at the given sigma, using least-squares regression.

The fit is to the unitless potential (V/epsilon) so that the returned coefficients can be multiplied by epsilon at runtime (same convention as SHIFTED_LJ_FIT).

Results are cached by (sigma, m_exp, n_exp, r_shift, r_cutoff).

Parameters:
  • sigma – sigma parameter in Angstrom

  • m_exp – repulsive exponent (default 12)

  • n_exp – attractive exponent (default 6)

  • r_shift – shift onset radius in Angstrom

  • r_cutoff – cutoff radius in Angstrom

Return type:

list(tuple(int, int, float))

Returns:

list of (one_based_index, exponent, coefficient) tuples compatible with the SHIFTED_LJ_FIT format

schrodinger.application.matsci.martini3_ff.clearShiftedLJFitCache()

Clear the on-the-fly shifted LJ fit coefficient cache.

schrodinger.application.matsci.martini3_ff.computeShiftedCoulombFitCoefficients(r_shift=0.0, r_cutoff=12.0)

Compute polynomial_cij fit coefficients for the shifted Coulomb potential, using least-squares regression.

The fit is to the unitless potential so that the returned coefficients can be multiplied by q_i * q_j / dielectric at runtime (same convention as SHIFTED_COULOMB_FIT).

Results are cached by (r_shift, r_cutoff).

Parameters:
  • r_shift – shift onset radius in Angstrom

  • r_cutoff – cutoff radius in Angstrom

Return type:

list(tuple(int, int, float))

Returns:

list of (one_based_index, exponent, coefficient) tuples compatible with the SHIFTED_COULOMB_FIT format

schrodinger.application.matsci.martini3_ff.clearShiftedCoulombFitCache()

Clear the on-the-fly shifted Coulomb fit coefficient cache.

class schrodinger.application.matsci.martini3_ff.Martini3BeadTypeAssigner

Bases: object

Assigns Martini 3 bead types to molecular fragments based on their chemical composition and environment.

Martini 3 bead type assignment follows a hierarchy:

  1. Size from heavy atom count: 4+ atoms -> Regular (no prefix), 3 atoms -> Small (S), 2 atoms -> Tiny (T), aromatic rings always -> Tiny (T)

  2. Chemical type from functional groups: pure hydrocarbon -> C, ether/ester -> N, alcohol/amide -> P, charged -> Q, halogenated -> X

  3. Level from specific chemical environment (1-6 polarity scale)

  4. Suffix from H-bond capability: donor -> d, acceptor -> a, both -> h

classmethod assignBeadType(fragment_st, num_heavy_atoms, is_aromatic_ring, is_ring, martini_version=None, aromatic_ring_size=None, is_adjacent_to_aromatic=False, has_ring_ether_oxygen=False, ring_ether_o_total=0, ring_size=0, has_ring_thioether_sulfur=False, is_mixed_aromatic_alkyl=False, has_ring_nh=False, has_ring_n_no_h=False, has_adj_ring_ether=False)

Assign a Martini 3 bead type string to a molecular fragment.

Parameters:
  • fragment_st (Structure) – extracted fragment structure

  • num_heavy_atoms (int) – number of heavy atoms in the fragment

  • is_aromatic_ring (bool) – whether the fragment is an aromatic ring

  • is_ring (bool) – whether the fragment is any ring

  • martini_version (str) – Martini version for version-specific chemistry rules

  • aromatic_ring_size (int) – size of the parent aromatic ring (5 or 6), used to distinguish imidazole-type (TN5a) from pyridine-type (TN6a) imine nitrogen beads

  • is_adjacent_to_aromatic (bool) – True when at least one bead node is directly bonded to an aromatic ring atom outside the bead. Used to assign level 4 (N4a) to aryl carbonyl beads (e.g. acetophenone ketone) vs level 6 (N6a) for aliphatic carbonyls (e.g. heptanal).

  • has_ring_ether_oxygen (bool) – True when an O atom in the bead is itself a ring member (THP/THF), not just an exocyclic alcohol

  • ring_ether_o_total (int) – total ether O atoms in the parent ring across all beads

  • ring_size (int) – total number of atoms in the parent ring

  • has_ring_thioether_sulfur (bool) – True when an S atom in the bead is itself a ring member (THT)

  • is_mixed_aromatic_alkyl (bool) – True when the bead contains both ring carbons and non-ring carbons with no heteroatom (e.g. toluene)

  • has_ring_nh (bool) – True when any ring N in the bead carries an H atom in the original molecule (pyrrole-type NH). Cannot be inferred from the heavy-atom-only extracted fragment.

Return type:

str

Returns:

Martini 3 bead type string (e.g. ‘SC4’, ‘TC5e’, ‘P1h’)

schrodinger.application.matsci.martini3_ff.absorb_bridgehead_beads(fragment, mapping, fused_ring_bridgehead_nodes)

Redistribute bridgehead atoms into adjacent non-bridgehead beads.

For fused aromatic rings, the standard Martini 3 mapping places bridgehead atoms (shared between two rings) into their own 2-atom bead. This function moves each bridgehead atom into the smallest adjacent bead so that the molecule maps to the reference 4-bead topology.

Bridgehead nodes are added to fused_ring_bridgehead_nodes so that assign_martini3_bead_name can exclude them from the heavy-atom count.

Parameters:
  • fragment (SymmRingFragmentData) – fragment describing the fused ring

  • mapping (Mapping) – current best mapping

  • fused_ring_bridgehead_nodes (set) – set to collect bridgehead node indices

Return type:

Mapping

Returns:

updated mapping with bridgehead atoms absorbed into adjacent beads

schrodinger.application.matsci.martini3_ff.try_heteroatom_singleton(fragment, best_mapping, best_score, validator)

For Martini 3 non-aromatic rings, try candidates where each heteroatom ring atom is placed in a 2-atom bead with exactly one adjacent ring carbon, and the remaining carbons form one or more 3-atom beads.

Recovers the reference SC3 + TN6d split for pyrrolidine and analogous 5-membered aliphatic rings.

Parameters:
Return type:

tuple(Mapping, float)

Returns:

updated best mapping and score

schrodinger.application.matsci.martini3_ff.try_exocyclic_split(fragment, best_mapping, best_score, validator)

For Martini 3 non-aromatic rings with exocyclic heavy-atom substituents, try placing each decorated ring carbon with its substituent(s) and one adjacent ring carbon into a 3-atom bead.

Recovers SN6{O, C1, C2} + SC3{C3, C4, C5} for cyclopentanol.

Parameters:
Return type:

tuple(Mapping, float)

Returns:

updated best mapping and score

schrodinger.application.matsci.martini3_ff.try_ring_halving(fragment, best_mapping, best_score, validator)

For Martini 3 even-sized non-aromatic rings with at least one ring heteroatom, try splitting the ring into two equal halves.

Recovers SC3+SN4a (3+3) for THP instead of 3x2 perfect-matching.

Parameters:
Return type:

tuple(Mapping, float)

Returns:

updated best mapping and score

schrodinger.application.matsci.martini3_ff.ring_atom_cost(mapping, ring_node_set, cg_scale)

Compute a cost based on ring-atom counts per bead only.

Non-ring nodes are excluded from the count so that decoration atoms do not inflate the size penalty. A bead with exactly 1 ring atom paired with decoration atoms is treated as effective size min(cg_scale, ring + decoration_count).

Parameters:
  • mapping (Mapping) – the CG mapping

  • ring_node_set (set) – set of ring atom node indices

  • cg_scale (int) – target bead size (e.g. TINY_SCALE=2)

Return type:

float

Returns:

ring-atom size cost

schrodinger.application.matsci.martini3_ff.try_ring_perfect_matchings(fragment, best_mapping, best_score, validator, martini_version=None)

Try perfect matchings of a simple ring cycle as candidate CG mappings.

For an even-length ring there are exactly two perfect matchings. Decoration nodes are attached to the bead containing their parent ring atom. Cost is computed using ring-atom counts only so decorations do not distort the comparison.

Parameters:
  • fragment (SymmRingFragmentData) – fragment data

  • best_mapping (Mapping) – current best mapping

  • best_score (float) – current best cost

  • validator (MappingValidator) – mapping validator

  • martini_version (str) – Martini version string

Return type:

tuple(Mapping, float)

Returns:

updated best mapping and score

schrodinger.application.matsci.martini3_ff.apply_ring_strategies(fragment, best_mapping, best_score, validator, fused_ring_bridgehead_nodes, martini_version, is_aromatic)

Facade that runs all Martini 3 ring mapping strategies in sequence.

For aromatic fragments: tries perfect matchings then absorbs bridgehead beads. For non-aromatic fragments: tries heteroatom singleton, exocyclic split, and ring halving strategies.

Parameters:
  • fragment (SymmRingFragmentData) – fragment data

  • best_mapping (Mapping) – current best mapping

  • best_score (float) – current best cost

  • validator (MappingValidator) – mapping validator

  • fused_ring_bridgehead_nodes (set) – set collecting bridgehead nodes

  • martini_version (str) – Martini version string

  • is_aromatic (bool) – True if this is an aromatic ring fragment

Return type:

tuple(Mapping, float)

Returns:

updated (best_mapping, best_score)

schrodinger.application.matsci.martini3_ff.is_bead_aromatic_m3(nodes, aromatic_bonds)

Determine if any node in the bead participates in an aromatic bond.

Martini 3 version: checks any node (even bonds outside the bead), because M3 beads pair a ring carbon with a substituent (e.g. {C_ring, O} for phenol) and no aromatic bond may exist within the bead itself.

Parameters:
  • nodes (list) – bead node indices

  • aromatic_bonds (list) – list of (node_a, node_b) aromatic bond pairs

Return type:

bool

Returns:

True if any node participates in an aromatic bond

schrodinger.application.matsci.martini3_ff.get_aromatic_ring_size(nodes, mol_rings_mapping, aromatic_bonds)

Determine the size of the smallest aromatic ring containing any of the given nodes.

Parameters:
  • nodes (list) – bead node indices

  • mol_rings_mapping – mapping object with group_node attribute

  • aromatic_bonds (list) – list of (node_a, node_b) aromatic bond pairs

Return type:

int or None

Returns:

ring size (e.g. 5 or 6), or None if not determinable

schrodinger.application.matsci.martini3_ff.assign_martini3_bead_name(nodes, bead_graph, molecule_st, node_to_atom_idx, mapping_solution, mol_rings_mapping, st_graph, aromatic_bonds, martini_version, fused_ring_bridgehead_nodes)

Assign a Martini 3 bead type name based on fragment chemistry.

Parameters:
  • nodes (list) – nodes belonging to this bead

  • bead_graph (networkx.Graph) – subgraph for this bead

  • molecule_st (Structure) – parent molecule structure

  • node_to_atom_idx (dict) – mapping from node index to atom index

  • mapping_solution – current mapping solution with node_group

  • mol_rings_mapping – ring mapping with group_node attribute

  • st_graph (networkx.Graph) – full structure graph

  • aromatic_bonds (list) – list of (node_a, node_b) aromatic bond pairs

  • martini_version (str) – Martini version string

  • fused_ring_bridgehead_nodes (set) – bridgehead node indices to exclude

Return type:

str

Returns:

Martini 3 bead type string (e.g. ‘SC4’, ‘TC5e’)

schrodinger.application.matsci.martini3_ff.compute_m3_bead_metrics(fragment, bead, bead_nodes, cg_scale)

Compute bead_size and bead_scale for a single bead under Martini 3 rules.

Returns raw node count as bead_size (not inflated by ring contribution), and a per-bead target scale based on heteroatom content and ring type.

Parameters:
  • fragment – fragment data object (ResidueData or SymmRingFragmentData)

  • bead – bead identifier

  • bead_nodes (list) – nodes in this bead

  • cg_scale (int) – default CG scale

Return type:

tuple(int, int)

Returns:

(bead_size, bead_scale)

schrodinger.application.matsci.martini3_ff.m3_is_score_improved(new_num_beads, best_num_beads, new_num_shared, best_num_shared)

Martini 3 tie-breaking rule: prefer finer resolution (more beads), then fewer shared atoms as secondary criterion.

Parameters:
  • new_num_beads (int) – number of beads in new mapping

  • best_num_beads (int) – number of beads in best mapping

  • new_num_shared (int) – shared atom count in new mapping

  • best_num_shared (int) – shared atom count in best mapping

Return type:

bool

Returns:

True if new mapping is preferred

schrodinger.application.matsci.martini3_ff.get_martini3_target_scale(is_ring_bead, is_aromatic_ring)

Get the target bead size for Martini 3 bead sizing.

Aromatic ring beads target TINY_SCALE (2), aliphatic ring beads target SMALL_SCALE (3), regular non-ring beads target MARTINI_SCALE (4).

Parameters:
  • is_ring_bead (bool) – whether the bead contains ring nodes

  • is_aromatic_ring (bool) – whether the ring is aromatic

Return type:

int

Returns:

target scale for bead sizing

schrodinger.application.matsci.martini3_ff.get_ring_graph_weights()

Return substituent edge weights for the Martini 3 weighted ring graph.

Martini 3 uses equal weights of 0.5 for short-end and long-end substituents so that ring decorations are treated as full-weight nodes during centrality scoring (distinct from the implicit ring edge weight of 1.0).

Return type:

tuple(float, float)

Returns:

(short_end_weight, long_end_weight)

schrodinger.application.matsci.martini3_ff.is_ring_eligible_m3(ring, scale)

Martini 3 ring eligibility check.

Aromatic rings with 3+ atoms are eligible because T-beads map 2-3 heavy atoms. Non-aromatic rings use the standard criterion (size within (scale, 2*scale]).

Parameters:
  • ring (structure.Ring) – the ring

  • scale (int) – current CG scale

Return type:

bool

Returns:

True if the ring is eligible for coarse-graining

schrodinger.application.matsci.martini3_ff.get_residue_scale(sample_fragments_data, residue, default_scale)

Determine the CG scale for residue-level homogenization under Martini 3.

If all fragments of the residue are aromatic ring fragments, use TINY_SCALE so that 2-atom aromatic beads are preserved during homogenization.

Parameters:
  • sample_fragments_data (list) – all fragment data objects for the molecule

  • residue – residue data object with res_name attribute

  • default_scale (int) – default CG scale

Return type:

int

Returns:

scale to use for this residue

schrodinger.application.matsci.martini3_ff.get_mapping_from_order_m3(fragment, nodes, new_mapping, mapped_nodes)

Martini 3 aromatic ring node grouping strategy.

Pairs adjacent nodes within each connected component into 2-atom T-beads. Graph coloring (used in the Martini 2 path) is not applicable because it enforces non-adjacency between grouped nodes.

Mutates new_mapping and mapped_nodes in place.

Parameters:
  • fragment – fragment data object

  • nodes (list) – unmapped nodes of the current node type

  • new_mapping – current Mapping being built (mutated)

  • mapped_nodes (list) – already-mapped node indices (mutated)

Return type:

None

Returns:

None

schrodinger.application.matsci.martini3_ff.get_fused_aromatic_ring_bead_groups_from_molecule(molecule_data)

Identify groups of CG beads belonging to fused aromatic ring systems.

Delegates to the graph module for cycle detection and checks aromaticity via the molecule’s aromatic bond set. Only ring systems with 3 or more beads are included (eligible for virtual site placement).

Parameters:

molecule_data – MoleculeData instance with mol_rings_mapping, st_graph, aromatic_bonds, bead_types, and mapping_solution attributes

Return type:

list(list(tuple(str, int)))

Returns:

list of ring bead groups; each group is a list of (bead_type_name, bead_idx) tuples

exception schrodinger.application.matsci.martini3_ff.LipidMappingError

Bases: Exception

Raised when lipid mapping fails.

class schrodinger.application.matsci.martini3_ff.Martini3LipidMapper(struct, martini_version)

Bases: object

Maps all-atom lipid structures to Martini 3 coarse-grained beads.

Follows the same driver-consumption contract as AutomatedMartiniProteinMapping: after calling map, the particles_info property returns the standard automated-mapping particle records that the driver iterates to build the CG structure.

Supported lipid molecules are those whose residue name (or CG atom name) appears as a site key prefix in Martini3_cgff.json (e.g. DPPC, POPC, CHOL). The lipid-fragment SMARTS library is loaded from map_lipid_to_martini3.json.

Atom-to-bead assignment uses the CG atom name stored in each atom’s atom_type or pdbname field: the name is expected to match a key in the CGFF sites dict under the pattern <RESNAME>_<BEADNAME>.

MAPPING_FILENAME = 'map_lipid_to_martini3.json'
CGFF_FILENAME = 'Martini3_cgff.json'
PHOSPHATE_COMPONENT = 'phosphate'
__init__(struct, martini_version)

Load the lipid mapping JSON and CGFF JSON, and store the structure.

Parameters:
  • struct (Structure) – all-atom structure to be mapped

  • martini_version (str) – Martini force field version string (e.g. ‘martini3’)

map()

Detect lipid molecules, assign available CG beads, and tag atoms.

Return type:

Structure

Returns:

the input structure with CG mapping properties tagged on each relevant atom

property particles_info

Return the standard automated-mapping particle records accumulated during mapping

Return type:

list(AUTOMAPPED_PARTICLE_INFO)

Returns:

particle records for driver consumption