Exhaustive Ring Perception With MX

The latest release of MX now supports exhaustive ring perception. Both a platform-independent jarfile and source distribution can be downloaded.

Background

The ability to perceive all rings in a chemical structure is essential for a number of important cheminformatics capabilities including Structure Diagram Generation, aromaticity detection, and binary fingerprint generation.

A recent Depth-First article described a ring-perception algorithm that efficiently returns the set of all rings for any molecule. The algorithm, developed by Hanser and coworkers has now been implemented in MX.

MX is a platform-independent, cross-language cheminformatics toolkit written in Java and made available to the cheminformatics community by Metamolecular, LLC.

Examples

Ring perception can be tested conveniently using either JRuby or Jython. In these examples, we'll use JRuby.

To find all rings in benzene, we'd use something like:

jirb
irb(main):001:0> require 'mx-0.108.1.jar'                         
=> true
irb(main):002:0> import com.metamolecular.mx.ring.HanserRingFinder
=> Java::ComMetamolecularMxRing::HanserRingFinder
irb(main):003:0> import com.metamolecular.mx.io.Molecules         
=> Java::ComMetamolecularMxIo::Molecules
irb(main):004:0> benzene = Molecules.create_benzene               
=> #<Java::ComMetamolecularMxModel::DefaultMolecule:0x1971eb3 @java_object=com.metamolecular.mx.model.DefaultMolecule@126ba64>
irb(main):005:0> finder = HanserRingFinder.new                    
=> #<Java::ComMetamolecularMxRing::HanserRingFinder:0x76f2e8 @java_object=com.metamolecular.mx.ring.HanserRingFinder@1458dcb>
irb(main):006:0> rings = finder.find_rings benzene                
=> #<Java::JavaUtil::ArrayList:0x1b83048 @java_object=[[com.metamolecular.mx.model.DefaultMolecule$AtomImpl@169dd64, com.metamolecular.mx.model.DefaultMolecule$AtomImpl@145f5e3, com.metamolecular.mx.model.DefaultMolecule$AtomImpl@122d9c, com.metamolecular.mx.model.DefaultMolecule$AtomImpl@170984c, com.metamolecular.mx.model.DefaultMolecule$AtomImpl@11ed166, com.metamolecular.mx.model.DefaultMolecule$AtomImpl@45aa2c, com.metamolecular.mx.model.DefaultMolecule$AtomImpl@169dd64]]>
irb(main):007:0> rings[0].collect{|atom| atom.get_index}.join("-")
=> "5-0-1-2-3-4-5"
irb(main):008:0> rings.size
=> 1

Here, we're taking advantage of the Ruby Array.join function to place a dash between each atom index.

To really push the system, we could find all rings in cubane:

jirb
irb(main):001:0> require 'mx-0.108.1.jar'                         
=> true
irb(main):002:0> import com.metamolecular.mx.ring.HanserRingFinder
=> Java::ComMetamolecularMxRing::HanserRingFinder
irb(main):003:0> import com.metamolecular.mx.io.Molecules         
=> Java::ComMetamolecularMxIo::Molecules
irb(main):004:0> cubane = Molecules.create_cubane                 
=> #<Java::ComMetamolecularMxModel::DefaultMolecule:0xe391c4 @java_object=com.metamolecular.mx.model.DefaultMolecule@182a033>
irb(main):005:0> finder = HanserRingFinder.new                    
=> #<Java::ComMetamolecularMxRing::HanserRingFinder:0x1458dcb @java_object=com.metamolecular.mx.ring.HanserRingFinder@1603522>
irb(main):006:0> rings = finder.find_rings cubane                 
=> #collection with many objects
irb(main):007:0> rings.size                                       
=> 28
irb(main):008:0> rings[0].collect{|atom| atom.get_index}.join("-")
=> "3-0-1-2-3"

Other Improvements

The MX-0.108.1 release includes some other changes as well.

  • Fixes a bug in which multiline SD file data was not read.
  • Adds a resources directory containing atomic_system.xml so that the source distribution can compile and all tests will pass.

Conclusions

This first implementation of the Hanser algorithm focuses on correctness, readability, and test coverage over performance. Future releases will address performance in the context of a open, multi-toolkit cheminformatics benchmark suite.