Web Analytics Made Easy - Statcounter
Skip to content

Getting Nodes#

Collecting the right nodes is one of the most common tasks in SAMSON extension development.

You will do it when you:

  • read the current selection
  • find atoms, residues, or models of a specific kind
  • apply a command to a subset of the data graph
  • convert a query string into a concrete node set

The main low-level entry point is SBNode::getNodes, which collects descendants of a node such as a document, molecule, or residue. At the facade level, SAMSON::getNodes offers convenience functions based on NSL or viewport position.

Node predicates#

Node predicates are the most direct programmatic way to describe which nodes you want.

SBDDataGraphNode defines a family of predicates that can be passed to getNodes. For example, SBNode::IsType(...) filters by node type:

// Find all atoms in the active document
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::IsType(SBNode::Atom));
// Find all residues in the active document
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::IsType(SBNode::Residue));

Because filtering by type is very common, there is also a convenience overload that takes only SBNode::Type:

// Find all atoms in the active document
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::Atom);
// Find all residues in the active document
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::Residue);

SBNode::IsSelected() filters by selection state:

// Find all selected nodes in the active document
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::IsSelected());

Predicates can be combined through logical operators. For example, selected atoms can be collected with:

// Find all selected atoms in the active document
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::IsType(SBNode::Atom) && SBNode::IsSelected());

You can also collect from more than one source node or refine an existing node indexer. For example, if you already have a nodeIndexer and want all atoms it contains transitively:

SBNodeIndexer atomIndexer;
SB_FOR(SBNode* node, nodeIndexer)
    node->getNodes(atomIndexer, SBNode::IsType(SBNode::Atom));

Node getters#

Node getters are functors that retrieve properties and can be compared to build predicates. For example, collecting all atoms can also be written as:

// Find all atoms
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::GetType() == SBNode::Atom);

The expression SBNode::GetType() == SBNode::Atom builds a predicate that is then passed to getNodes.

In general, getters mirror ordinary getter functions but use an initial capital letter because they are classes. For example:

Predicates and getters can be combined to express fairly rich rules:

// Find all selected atoms with a large enough temperature factor
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer, 
    SBNode::IsSelected() &&
    SBNode::IsType(SBNode::Atom) &&
    (SBAtom::GetTemperatureFactor() > 2.0));
// Find all atoms which have a partial charge larger than 0.4f
SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer,
    SBNode::IsType(SBNode::Atom) &&
    SBAtom::HasPartialCharge() &&
    (SBAtom::GetPartialCharge() >= 0.4f));

These predicate and getter patterns are the programmatic foundation of the Node Specification Language.

Selection strings#

SAMSON also supports Node Specification Language (NSL) queries, which are useful when the selection should be expressed as text.

SAMSON::makeNodePredicate builds a node predicate from an NSL query string.

Examples:

// A predicate that is true if and only if 
// the node is an atom:
// "n.t a" is short of "node.type atom"
SBNodePredicate* nodePredicate = SAMSON::makeNodePredicate("n.t a");

SBNodeIndexer nodeIndexer;
SAMSON::getActiveDocument()->getNodes(nodeIndexer, *nodePredicate);
// A predicate that is true if and only if
// the node a residue in alpha helix:
// "r.ss h" is short of "residue.secondaryStructure helix"
SBNodePredicate* nodePredicate = SAMSON::makeNodePredicate("r.ss h");
// A predicate that is true if and only if 
// the node is a sidechain that has at least one Sulfur atom:
// "n.t sc h S" is short of "node.type sidechain having S"
SBNodePredicate* nodePredicate = SAMSON::makeNodePredicate("n.t sc h S");
// A predicate that is true if and only if 
// the node is a hydrogen atom bonded to an oxygen atom:
// "H l O" is short of "H linking O"
SBNodePredicate* nodePredicate = SAMSON::makeNodePredicate("H l O");

Or you can use an NSL string directly to get the nodes from the active document:

// Select from the active document
// all hydrogen atoms bonded to oxygen atoms
SBNodeIndexer nodeIndexer;
SAMSON::getNodes(nodeIndexer, "H linking O");

Choosing the right approach#

Use:

  • a type filter when the query is simple and static
  • predicates and getters when the logic is code-driven and composable
  • NSL when the query should be expressed, stored, or edited as text