extract_clusters_step package

Submodules

extract_clusters_step.cluster_sampling module

Sampling of n-molecule clusters from a (periodic) configuration.

The pure functions here have no dependence on the SEAMM framework, only on numpy/scipy and the duck-typed molsystem configuration passed in, so they can be unit-tested directly and reused outside a flowchart.

The approach:

  1. Find the molecules (by bonds) and build a molecular contact graph: molecule A is adjacent to B if any contact atom of A is within cutoff (minimum image) of any contact atom of B.

  2. Sample n-mers as connected subgraphs of that graph by random frontier growth from a random seed molecule. Every member interacts with at least one other, and chains, rings and stars all occur – unlike nearest-neighbour selection, which only ever yields the most compact cluster.

  3. Optionally stratify the accepted clusters to be flat in a spread coordinate (radius of gyration or largest centroid separation of the molecules), with bin edges taken as quantiles of a pilot sample, and optionally balance jointly over contact-graph topology (motif).

  4. Emit each cluster as an unwrapped, centred, non-periodic configuration with the molecules intact, a unique name carrying provenance, and optional per-configuration properties.

extract_clusters_step.cluster_sampling.accepts_topology(adj, order, motifs=None, coordination=None)[source]

Whether the cluster order passes the motif and centre-coordination filters. Returns (accepted, motif, n_edges, degrees).

extract_clusters_step.cluster_sampling.bond_index_pairs(configuration)[source]

The bonds of a configuration as 0-based atom-index pairs, with orders.

For a configuration without symmetry operators (the normal case, and every non-periodic one) the pairs come straight from the bond table, since symmetry.bond_atoms is only populated for periodic configurations. For a symmetric crystal the symmetry-expanded list is used.

Returns:

pairs is a list of (i, j) index tuples; orders the matching list of bond orders, or None if it could not be matched up.

Return type:

(pairs, orders)

extract_clusters_step.cluster_sampling.check_bonds(configuration)[source]

Raise if the configuration has no bonds but clearly consists of molecules.

Molecules are found from the bonds, so a configuration read from a format without connectivity (e.g. extended XYZ without bond perception) would be treated as one atom per molecule and the “clusters” would silently be groups of atoms. Configurations made only of noble-gas atoms or monatomic ions are allowed through.

extract_clusters_step.cluster_sampling.classify_motif(n, n_edges, degrees)[source]

Name the topology of the induced contact graph of an n-mer.

Only n <= 4 get descriptive names; larger clusters are labelled by edge count so they can still be balanced on topology.

Parameters:
  • n (int) – Number of molecules.

  • n_edges (int) – Number of contact edges within the cluster.

  • degrees ([int]) – The degree of each molecule within the cluster.

Return type:

str

extract_clusters_step.cluster_sampling.cluster_motif(adj, order)[source]

The motif label, edge count and degree list of the cluster order.

extract_clusters_step.cluster_sampling.cluster_summary(records, edges=None)[source]

Tabulate how a set of extracted n-mers is distributed over motif and spread bin – the quick check that the set is actually balanced.

Parameters:
  • records ([dict]) – The records from extract_nmers().

  • edges ([float] or None) – The bin edges, printed as a final line if given.

Return type:

str

extract_clusters_step.cluster_sampling.extract_nmers(configuration, n, n_samples, *, cutoff=3.5, contact_elements=None, spread_metric='rg', spread_bins=None, balance_motifs=False, motifs=None, coordination=None, system=None, system_name='clusters', name_prefix='', max_attempts=None, rng=None, store_properties=True, seen=None)[source]

Extract n-molecule clusters from a (periodic) configuration.

The clusters are returned as unwrapped, non-periodic configurations suitable for cluster QM.

Selection is by connected subgraph of a molecular contact graph, not by nearest neighbours: every molecule in a returned n-mer is within cutoff of at least one other, but chains, rings and stars all occur, and seeds are random so a single frame yields many distinct clusters.

Parameters:
  • configuration (molsystem _Configuration) – Source configuration (periodic or not). Molecules are found by bonds.

  • n (int) – Molecules per cluster (>= 2).

  • n_samples (int) – Target number of clusters (fewer if the pool or quotas run out).

  • cutoff (float) – Contact distance (Å) defining the neighbour graph. 3.5 with contact_elements=["O"] is the usual H-bond criterion for water.

  • contact_elements (list[str] or None) – Elements whose atoms define contact; None uses all atoms.

  • spread_metric ("rg" | "dmax") – Compactness coordinate used for stratification: radius of gyration of the molecular centroids, or the largest centroid-centroid distance.

  • spread_bins (int, sequence of float, or None) – Bin edges on the spread coordinate. An int asks for that many equal-quantile bins, with edges taken from an unstratified pilot sample of the same frame – the usual choice, since sensible edges depend on n and on the system. If given, acceptance is quota- limited so bins fill roughly evenly (flat-in-spread, analogous to the dimer builder’s flat-in-energy selection). Samples outside the edges are rejected. None disables stratification.

  • balance_motifs (bool) – Also balance across contact-graph topology (chain/ring/star/…), jointly with the spread bins.

  • motifs (iterable of str or None) – Accept only clusters whose contact-graph motif is one of these (see motif_names()); None accepts every motif. Rejected candidates count against the attempt budget, so rare motifs (rings are a few percent of water trimers) may need a larger budget.

  • coordination (iterable of int or None) – Accept only clusters whose most-connected molecule has one of these numbers of contacts within the cluster (its degree in the induced contact graph) – e.g. [3] for star tetramers, [4] for a complete first shell. None accepts any. Stored on every cluster as the centre coordination property.

  • system (molsystem _System or None) – Destination system. If None, system_name is looked up in the configuration’s database and created if needed.

  • system_name (str) – Destination system name, used when system is None.

  • name_prefix (str) – Prefix (e.g. a frame label) for the configuration names, which are f"{name_prefix}{seed}_{m1-m2-...}" and unique within a frame.

  • max_attempts (int or None) – Sampling attempts before giving up (default 50 * n_samples).

  • rng (int, numpy Generator or None) – Seed / generator for reproducibility.

  • store_properties (bool) – Store size, spread, motif, edge count, and source molecule list as *#ExtractClusters#scan properties on each configuration.

  • seen (set or None) – Molecule sets already emitted (as frozensets); updated in place. Pass the same set across calls on the same frame to avoid duplicates.

Returns:

New configurations; one metadata dict per cluster with keys name, n, molecules, seed, order, rg, dmax, n_edges, degrees, motif, bin; and an info dict with edges (the bin edges used, or None), attempts, per_key quota, n_molecules and n_contacts of the frame’s graph, and warning (a message or None) if fewer than requested were produced.

Return type:

(configurations, records, info)

extract_clusters_step.cluster_sampling.grow_connected(adj, seed, n, rng)[source]

Grow a connected n-molecule subgraph from seed.

Random frontier expansion: at each step a molecule adjacent to the current cluster is chosen uniformly and attached through a random one of its neighbours already inside. Uniform choice from the frontier is a cheap approximation to uniform connected-subgraph sampling; it mildly favours high-degree regions.

Returns:

order is the list of molecule indices in growth order; parent maps each to the molecule it attached through (None for the seed). None if the connected component is smaller than n.

Return type:

(order, parent) or None

extract_clusters_step.cluster_sampling.make_put_property(conf, tag='#ExtractClusters#scan')[source]

Return a closure storing name+tag properties on conf.

Defines the property first if the database lacks it (the properties are normally pre-registered from data/properties.csv).

extract_clusters_step.cluster_sampling.molecule_neighbour_graph(frac_atoms, atom_mol, contact_mask, T, cutoff, periodic, cell_parameters)[source]

Molecule-level adjacency from atom contacts.

A~B if any contact atom of A is within cutoff (Å, minimum image) of any contact atom of B.

Parameters:
  • frac_atoms ((N,3) ndarray) – Fractional coordinates (Cartesian if not periodic).

  • atom_mol ((N,) ndarray of int) – Molecule index of each atom.

  • contact_mask ((N,) ndarray of bool) – Which atoms define contact.

  • T ((3,3) ndarray) – Fractional->Cartesian transform (xyz = uvw @ T); identity if not periodic.

  • cutoff (float) – Contact distance, Å.

  • periodic (bool)

  • cell_parameters ((a, b, c, alpha, beta, gamma) or None)

Returns:

Adjacency lists keyed by molecule index. Molecules with no contacts are absent.

Return type:

dict[int, set[int]]

extract_clusters_step.cluster_sampling.motif_names(n)[source]

The motif labels classify_motif() can produce for n molecules.

Named motifs for n <= 4; for larger n the labels are e<edges> for every possible edge count of a connected graph, from n-1 (a tree) to n(n-1)/2.

extract_clusters_step.cluster_sampling.pilot_spreads(adj, n, frac_centroids, T, periodic, spread_metric, n_mol, rng, n_pilot, motifs=None, coordination=None)[source]

Spread values of an unstratified pilot sample, used to place bin edges.

If motifs or coordination is given only clusters passing those filters are sampled, so the bin edges describe the distribution the extraction will actually draw from (ring trimers, say, are compact and never reach the widest all-motif bin).

extract_clusters_step.cluster_sampling.unwrap_shifts(order, parent, frac_centroids, periodic)[source]

Integer lattice shifts making each molecule contiguous with its parent.

Each molecule is shifted to the image nearest the neighbour it attached through, so the whole cluster is contiguous in space.

extract_clusters_step.extract_clusters module

Non-graphical part of the Extract Clusters step in a SEAMM flowchart

class extract_clusters_step.extract_clusters.ExtractClusters(flowchart=None, title='Extract Clusters', extension=None, logger=<Logger extract_clusters_step.extract_clusters (WARNING)>)[source]

Bases: Node

The non-graphical part of a Extract Clusters step in a flowchart.

Extracts n-molecule clusters (trimers, tetramers, … larger clusters) from the current, typically periodic, condensed-phase configuration as unwrapped, non-periodic configurations in a new system, tagged with provenance. The clusters are connected subgraphs of the molecular contact graph, optionally stratified to be flat in a spread coordinate and balanced over topology. See extract_clusters_step.cluster_sampling for the algorithm.

parser

The parser object.

Type:

configargparse.ArgParser

options

It contains a two item tuple containing the populated namespace and the list of remaining argument strings.

Type:

tuple

parameters

The control parameters for Extract Clusters.

Type:

ExtractClustersParameters

See also

TkExtractClusters, ExtractClustersParameters

analyze(indent='', P=None, results=None, system=None, sources=None, seed=None, motifs=None, coordination=None, **kwargs)[source]

Report the extracted clusters to step.out.

Parameters:
  • indent (str) – An extra indentation for the output

  • P (dict) – The control parameters.

  • results ([(n, configurations, records, info)]) – The output of extract_nmers() for each cluster size.

  • system (molsystem _System) – The destination system.

  • source (molsystem _Configuration) – The source configuration.

description_text(P=None)[source]

Create the text description of what this step will do. The dictionary of control values is passed in as P so that the code can test values, etc.

Parameters:

P (dict) – An optional dictionary of the current values of the control parameters.

Returns:

A description of the current step.

Return type:

str

property git_revision

The git version of this module.

property property_tag

The suffix of the per-cluster properties, ‘#ExtractClusters#scan’.

run()[source]

Run a Extract Clusters step.

Returns:

The next node object in the flowchart.

Return type:

seamm.Node

property version

The semantic version of this module.

extract_clusters_step.extract_clusters_parameters module

Control parameters for the Extract Clusters step in a SEAMM flowchart

class extract_clusters_step.extract_clusters_parameters.ExtractClustersParameters(defaults={}, data=None)[source]

Bases: Parameters

The control parameters for Extract Clusters.

The keys are the parameters for this plug-in; each value is a dictionary describing that parameter (default, kind, units, enumeration, format, description, help).

parameters{str: {str: str}}

A dictionary containing the parameters for the current step.

See also

ExtractClusters, TkExtractClusters, ExtractClustersStep

parameters = {'attempts per cluster': {'default': 50, 'default_units': '', 'description': 'Attempts per cluster:', 'enumeration': (), 'format_string': '', 'help_text': 'The sampling budget: the total number of attempts is this times the number of clusters requested. Attempts that duplicate an earlier cluster, fall outside the bin edges, or land in a full quota cell are rejected and count against the budget.', 'kind': 'integer'}, 'balance motifs': {'default': 'no', 'default_units': '', 'description': 'Balance motifs:', 'enumeration': ('yes', 'no'), 'format_string': '', 'help_text': 'Also balance the set over the topology of the contact graph within the cluster (chain / ring / star / ..., or the number of contacts for clusters of more than four molecules), jointly with the spread bins. Topology and spread are correlated -- rings only exist compact -- so some cells cannot fill and the set will come up short of the requested number; the summary shows which.', 'kind': 'boolean'}, 'bin edges': {'default': '', 'default_units': 'Å', 'description': 'Bin edges:', 'enumeration': (), 'format_string': '', 'help_text': "The bin edges of the spread metric, in Å, as an increasing comma- or space-separated list, e.g. '1.6, 2.0, 2.5, 3.5'. Clusters outside the outer edges are rejected. Note that sensible edges depend strongly on the cluster size and the system; 'quantile bins' is usually the better choice.", 'kind': 'string'}, 'centre coordination': {'default': 'any', 'default_units': '', 'description': 'Centre coordination:', 'enumeration': ('any',), 'format_string': '', 'help_text': "Accept only clusters whose most-connected molecule has this many contacts within the cluster: a value or SEAMM list such as '3' (star tetramers), '4' (a complete first shell) or '3:4'. 'any' accepts all. Applied at acceptance, so the set contains only such clusters instead of being post-filtered; the value is also stored on every cluster as the 'centre coordination' property.", 'kind': 'string'}, 'cluster sizes': {'default': '3', 'default_units': '', 'description': 'Cluster sizes (molecules):', 'enumeration': (), 'format_string': '', 'help_text': "The number of molecules per cluster. A comma- or space-separated list, e.g. '3, 4', extracts a set of each size from the same frame. Each must be at least 2.", 'kind': 'string'}, 'contact cutoff': {'default': 3.5, 'default_units': 'Å', 'description': 'Contact cutoff:', 'enumeration': (), 'format_string': '.2f', 'help_text': 'Two molecules are in contact if any of their contact atoms are within this distance (minimum image). A cluster is a connected set of molecules under this criterion. 3.5 Å between oxygens is the usual hydrogen-bond criterion for water.', 'kind': 'float'}, 'contact elements': {'default': 'all', 'default_units': '', 'description': 'Contact elements:', 'enumeration': ('all',), 'format_string': '', 'help_text': "The elements whose atoms define contact, e.g. 'O' or 'O, N'. 'all' uses every atom. Restricting to the heavy atoms that form the intermolecular contacts (e.g. O for water) makes the cutoff meaningful and the graph cheaper to build.", 'kind': 'string'}, 'make current': {'default': 'yes', 'default_units': '', 'description': 'Make the cluster system current:', 'enumeration': ('yes', 'no'), 'format_string': '', 'help_text': "Whether to make the cluster system (and its first configuration) the current one, so that a following Write Structure step writes the clusters. Choose 'no' when the source must remain current.", 'kind': 'boolean'}, 'motifs': {'default': 'any', 'default_units': '', 'description': 'Restrict to motifs:', 'enumeration': ('any',), 'format_string': '', 'help_text': "Accept only clusters whose contact-graph topology is one of the given motifs, e.g. 'ring', or 'ring, star' for several. 'any' accepts all. Trimers have 'chain' and 'ring'; tetramers 'chain', 'star', 'ring', 'paw', 'diamond' and 'K4'; larger clusters are labelled 'e<n>' by their number of contacts. Rare motifs use up the attempt budget quickly, so raise 'Attempts per cluster' if the set comes up short.", 'kind': 'string'}, 'name prefix': {'default': 'from configuration', 'default_units': '', 'description': 'Configuration name prefix:', 'enumeration': ('from configuration', 'none'), 'format_string': '', 'help_text': "Each cluster is named '<prefix><seed>_<m1-m2-...>' from the source molecules, which is unique within a frame. The prefix keeps the names unique across frames: 'from configuration' uses '<source configuration name>_' (the default, and the right choice when several frames are selected); 'none' uses no prefix; any other text is used literally (a variable such as '$frame_' works).", 'kind': 'string'}, 'number of bins': {'default': 3, 'default_units': '', 'description': 'Number of bins:', 'enumeration': (), 'format_string': '', 'help_text': 'The number of equal-quantile bins of the spread metric. The clusters are accepted so that the bins fill roughly evenly.', 'kind': 'integer'}, 'number of clusters': {'default': 50, 'default_units': '', 'description': 'Clusters per size:', 'enumeration': (), 'format_string': '', 'help_text': 'How many clusters of each size to extract from each selected configuration (frame). Fewer are produced if the configuration does not contain enough distinct connected clusters, or if stratification quotas cannot fill.', 'kind': 'integer'}, 'random seed': {'default': 'random', 'default_units': '', 'description': 'Random seed:', 'enumeration': ('random',), 'format_string': '', 'help_text': "The seed for the random-number generator. Use 'random' for a fresh seed, or an integer for a reproducible selection. The seed actually used is always printed in the output, so a 'random' run can be reproduced by entering that value here. A supplementary run over the same frames must use a DIFFERENT seed, or it will largely regenerate the same clusters.", 'kind': 'string'}, 'source configuration name': {'default': '', 'default_units': '', 'description': '', 'enumeration': (), 'format_string': 's', 'help_text': 'The configuration name, wildcard pattern or regular expression.', 'kind': 'string'}, 'source configurations': {'default': 'current', 'default_units': '', 'description': 'Configurations:', 'enumeration': ('current', 'all', 'last', 'first', 'name is', 'name matches', 'name regexp'), 'format_string': 's', 'help_text': 'Which configurations of each selected system to use: its current configuration, all of them, the last or first, or those whose name is / matches (shell wildcards) / matches the regular expression given.', 'kind': 'string'}, 'source system name': {'default': '', 'default_units': '', 'description': '', 'enumeration': (), 'format_string': 's', 'help_text': 'The system name, wildcard pattern or regular expression.', 'kind': 'string'}, 'source systems': {'default': 'current', 'default_units': '', 'description': 'Systems:', 'enumeration': ('current', 'all', 'name is', 'name matches', 'name regexp'), 'format_string': 's', 'help_text': 'Which systems to take the structures from: the current system, all systems, or those whose name is / matches (shell wildcards) / matches the regular expression given. A variable ($name) holding a list of configurations or of systems may also be given.', 'kind': 'string'}, 'spread metric': {'default': 'radius of gyration', 'default_units': '', 'description': 'Spread metric:', 'enumeration': ('radius of gyration', 'maximum centroid distance'), 'format_string': '', 'help_text': 'The compactness coordinate of a cluster, computed from the molecular centroids: the radius of gyration, or the largest centroid-centroid distance. Used for stratification and stored on each cluster.', 'kind': 'enum'}, 'store properties': {'default': 'yes', 'default_units': '', 'description': 'Store descriptors as properties:', 'enumeration': ('yes', 'no'), 'format_string': '', 'help_text': "Store the cluster size, spread, motif, number of contacts and source molecules on each configuration as '#ExtractClusters#scan' properties. They are carried through SDF/extxyz output.", 'kind': 'boolean'}, 'stratification': {'default': 'quantile bins', 'default_units': '', 'description': 'Stratify by spread:', 'enumeration': ('none', 'quantile bins', 'explicit bin edges'), 'format_string': '', 'help_text': "Whether to accept clusters so that the set is flat in the spread metric. 'quantile bins' places the bin edges at equal quantiles of a pilot sample of the frame, so the bins adapt to the cluster size and system; 'explicit bin edges' uses the edges given below; 'none' accepts clusters as sampled (biased towards the compact clusters that dominate the liquid).", 'kind': 'enum'}, 'system name': {'default': 'from source', 'default_units': '', 'description': 'Name the cluster system:', 'enumeration': ('from source',), 'format_string': '', 'help_text': "The name of the system that receives the clusters, created if it does not exist. 'from source' uses '<source system> clusters', with the system of the first selected structure. The clusters from all selected frames go into this one system.", 'kind': 'string'}}

extract_clusters_step.extract_clusters_step module

class extract_clusters_step.extract_clusters_step.ExtractClustersStep(flowchart=None, gui=None)[source]

Bases: object

Helper class needed for the stevedore integration.

This must provide a description() method that returns a dict containing a description of this node, and create_node() and create_tk_node() methods for creating the graphical and non-graphical nodes.

my_description

A human-readable description of this step. It can be several lines long, and needs to be clear to non-expert users. It contains the following keys: description, group, name.

Type:

{description, group, name}

my_description[]

A description of the Extract Clusters step. It must be clear to non-experts.

Type:

tuple

my_description[]

Which group in the menus to put this step. If the group does not exist it will be created. Common groups are “Building”, “Calculations”, “Control” and “Data”.

Type:

str

my_description[]

The name of this step, to be displayed in the menus.

Type:

str

create_node(flowchart=None, **kwargs)[source]

Create and return the new node object.

Parameters:
  • flowchart (seamm.Node) – A non-graphical SEAMM node

  • **kwargs (keyworded arguments) – Various keyworded arguments such as title, namespace or extension representing the title displayed in the flowchart, the namespace for the plugins of a subflowchart and the extension, respectively.

Return type:

ExtractClusters

See also

ExtractClusters

create_tk_node(canvas=None, **kwargs)[source]

Create and return the graphical Tk node object.

Parameters:
  • canvas (tk.Canvas) – The Tk Canvas widget

  • **kwargs (keyworded arguments) – Various keyworded arguments such as tk_flowchart, node, x, y, w, h representing a graphical flowchart object, a non-graphical node for a step, and dimensions of the graphical node.

Return type:

TkExtractClusters

See also

TkExtractClusters

description()[source]

Return a description of what this extension does.

my_description = {'description': 'Extract molecular clusters (trimers, tetramers, ... larger n-mers) from a condensed-phase, typically periodic, configuration as unwrapped, non-periodic structures, e.g. for many-body training data and diagnostics for machine-learned force fields.', 'group': 'Building', 'name': 'Extract Clusters'}

extract_clusters_step.metadata module

This file contains metadata describing the results from Extract Clusters

extract_clusters_step.tk_extract_clusters module

The graphical part of a Extract Clusters step

class extract_clusters_step.tk_extract_clusters.TkExtractClusters(tk_flowchart=None, node=None, canvas=None, x=None, y=None, w=200, h=50)[source]

Bases: TkNode

The graphical part of a Extract Clusters step in a flowchart.

tk_flowchart

The flowchart that we belong to.

Type:

TkFlowchart = None

node

The corresponding node of the non-graphical flowchart

Type:

Node = None

canvas

The Tk Canvas to draw on

Type:

tkCanvas = None

dialog

The Pmw dialog object

Type:

Dialog

x

The x-coordinate of the center of the picture of the node

Type:

int = None

y

The y-coordinate of the center of the picture of the node

Type:

int = None

w

The width in pixels of the picture of the node

Type:

int = 200

h

The height in pixels of the picture of the node

Type:

int = 50

self[widget]

A dictionary of tk widgets built using the information contained in Extract Clusters_parameters.py

Type:

dict

See also

ExtractClusters, TkExtractClusters, ExtractClustersParameters

create_dialog()[source]

Create the dialog. A set of widgets will be chosen by default based on what is specified in the Extract Clusters_parameters module.

Parameters:

None

Return type:

None

edit()[source]

Present a dialog for editing the Extract Clusters input

Parameters:

None

Return type:

None

handle_dialog(result)[source]

Handle the closing of the edit dialog

What to do depends on the button used to close the dialog. If the user closes it by clicking the “x” of the dialog window, None is returned, which we take as equivalent to cancel.

Parameters:

result (None or str) – The value of this variable depends on what the button the user clicked.

Return type:

None

handle_help()[source]

Shows the help to the user when click on help button.

Parameters:

None

Return type:

None

reset_dialog(widget=None)[source]

Layout the widgets in the dialog.

Only the stratification controls that apply to the chosen scheme are shown: the number of bins for ‘quantile bins’, the edges for ‘explicit bin edges’, and neither when stratification is off, so an unusable combination cannot be built in the editor.

Parameters:

widget (Tk Widget = None)

Return type:

None

right_click(event)[source]

Handles the right click event on the node.

Parameters:

event (Tk Event)

Return type:

None

Module contents

extract_clusters_step A SEAMM plug-in for extracting molecular clusters from a periodic cell of molecules