Calculator Plugins
Contents
Introduction
Plugins are generally used to add dynamically loaded modules to an application based on user defined configuration.
Our chemical calculator plugin structure is added to Marvin for the following reasons:
- There are a large number of chemical calculations and the set of necessary calculations may vary by user
- Users may need special calculations that are available on the internet or even more specific ones for which they have their own implementation
- A general mechanism is needed to enable both graphical java applications and command line tools to set chemical calculation parameters, perform the required calculation and display the results
There are some built-in calculations such as charge, pKa, logP and logD computations that can be purchased from . If a user needs another calculation, then he/she can integrate that calculation into Marvin as a custom plugin.
We developed a mechanism to handle these calculations in a uniform way. This common interface is utilized as a common java API for developers, as a command line tool and also in our graphical applications and applets MarvinSketch and MarvinView.
Mechanism
The implementation of the general plugin handling mechanism can be found in the
chemaxon.marvin.plugin package. Our specific plugin implementations
are in the chemaxon.marvin.calculations package.
Calculator plugins have a common base class:
chemaxon.marvin.plugin.CalculatorPlugin.
This base class declares methods to be implemented by the specific plugin classes for
input molecule setting, parameter setting, performing the calculation and getting the results,
implements the license handling, and provides some helper functions (e.g. for number
formatting).
Apart from this main plugin class, our graphical applications and applets
MarvinSketch and MarvinView require a
chemaxon.marvin.plugin.CalculatorPluginDisplay class to provide result GUI components.
For most plugins, the default implementation is sufficient as long as the
CalculatorPlugin.getResultMolecule() method is implemented such that molecular results
are written to molecule properties by
Molecule.setProperty(String key, String value) and atomic properties are written to
extra lables by
MolAtom.setExtraLabel(String label). It is also possible to set the atom label display color by
MolAtom.setExtraLabelColor(long color).
The CalculatorPluginDisplay base class provides a MarvinView display for all of these in
CalculatorPluginDisplay.getResultComponent().
However, your plugin may require a different display, in which case you should write a custom display class
extending
chemaxon.marvin.plugin.CalculatorPluginDisplay which overrides
CalculatorPluginDisplay.getResultComponent(). You can also rewrite
CalculatorPluginDisplay.store() to store results - this is mainly useful when more molecules
are drawn as a multi-fragment molecule in the sketcher and your plugin handles these one-by-one
(
CalculatorPlugin.handlesMultiFragmentMolecules() returns false).
In Marvin applications and applets plugin parameters can be set in a plugin specific parameter panel which can be
configured in a corresponding XML code. If the parameter
setting panel is more complicated then it is also possible to return it in
CalculatorPluginDisplay.getParameterPanel().
There is an example plugin implementation with a test application among the Marvin Beans Examples.
The cxcalc command line tool uses
chemaxon.marvin.plugin.CalculatorPluginOutput
to generate the plugin results in table form.
This class implements the default table output with one result row for each input molecule,
the molecule ID in the first column followed by the plugin results in the subsequent
columns. A specific output table format can be defined by subclassing this class.
Configuration
Both the cxcalc command line tool and the
graphical applications and applets require separate configuration files that specify the
available calculations / calculator plugins. For the configuration of the command line tool see the
Configuration File section in the
Calculator user manual. The plugin configuration for
MarvinSketch and MarvinView
describes the calculator plugins accessible from the Tools menu. It is read from
plugins/plugins.properties file (taken relative to the Marvin root
directory), or from xjars/plugins.properties file (located inside MarvinBeans.jar)
if the previous doesn't exist. It is also possible to specify the configuration in
java properties file given in the toolfiles application or applet parameter
(the file name should be given relative to the CLASSPATH). Marvin applets
load configuration files from the server computer.
The configuration file syntax is best shown by an example:
#$<plugin class name>$<plugin JAR URL>$<menu>$<mnemonics>$<group>$<groupmnemonics>$<NOPARAMS> #first char is separator, you can choose any ASCII character that is not contained in the fields plugin_01=$chemaxon.marvin.calculations.ElementalAnalyserPlugin$ElementalAnalyserPlugin.jar$Elemental Analysis$EA$$ plugin_11=$chemaxon.marvin.calculations.pKaPlugin$pKaPlugin.jar$pKa$pK$Protonation$P
The property keys should be unique within one configuration file.
The Tools menu is constructed with submenus specified in group strings with menuitems defined in menu strings.
Mnemonics can be set for groups using groupmnemonics and for plugins defining mnemonics strings. If group string is
left empty then the plugin is listed directly in the Tools menu.
Each property value defines a plugin configuration by giving the following fields:
- the full package name of the plugin class
- the plugin JAR (with path relative to the
pluginsdirectory) - the label in the
Toolsmenu - the menu label mnemonics character (only first character is considered if a string is given)
- the menu group label in the
Toolsmenu - the menu group label mnemonics character (only first character is considered if a string is given)
- an optional "NOPARAMS" string indicating that the plugin has no parameters
At least one of the plugin class and the plugin JAR is mandatory. If the plugin class is not
specified then it is read from the Plugin-Class attribute of the JAR manifest. If the
JAR is not specified then the plugin is loaded from the CLASSPATH.
The ending "NOPARAMS" option can simply be omitted, while if an intermediate field
is omitted then the corresponding separator character should be added.
Plugin loading:
The central plugin loader class is the
chemaxon.marvin.plugin.PluginFactory:
this class reads the configuration from a java.util.Properties object or from
a configuration file. In the latter case the Tools menu is also constructed
based on this configuration. The parameter panels are dynamically constructed from the plugin specific parameter panel descriptor XMLs or fetched from the display class. In the former case
the parameter panel can be constructed and displayed before the plugin class is loaded.
The plugin loading mechanism is the following: first the program tries to load the plugin class by the default class loader from the CLASSPATH; if the plugin class is not found then the JAR is loaded and the system tries to load the plugin class from there.
If the plugin name is omitted then the plugin is loaded directly from the JAR where
the Plugin-Class manifest attribute specifies the plugin class.
If the JAR name is omitted then the plugin is loaded from the CLASSPATH.
For example, here is the above plugin configuration with omitted fields:
#$<plugin class name>$<plugin JAR URL>$<menu>$<mnemonics>$<group>$<groupmnemonics>$<NOPARAMS> #first char is separator, you can choose any ASCII character that is not contained in the fields plugin_01=$chemaxon.marvin.calculations.ElementalAnalyserPlugin$$Elemental Analysis$EA$$ plugin_11=$$pKaPlugin.jar$pKa$pK$Protonation$P
Your plugin
The following table shows the items needed for the different plugin uses:
| CalculatorPlugin subclass | CalculatorPluginDisplay class or subclass | CalculatorPluginOutput class or subclass | plugins.properties | calc.properties | |
| sketcher/viewer | ![]() | ![]() | ![]() | ![]() | ![]() |
| cxcalc tool | ![]() | ![]() | ![]() | ![]() | ![]() |
| java API | ![]() | ![]() | ![]() | ![]() | ![]() |
Naming convention:
The plugin handling mechanism currently requires the following naming convention:
- Plugin class: any class name will do, but built-in plugins are named
...Plugin(e.g.chemaxon.marvin.calculations.HBDAPlugin) - Display class:
<plugin class name>Display(e.g.chemaxon.marvin.calculations.HBDAPluginDisplay) - Output class:
<plugin class name>Output(e.g.chemaxon.marvin.calculations.HBDAPluginOutput)
There is an example plugin implementation (plugin and display classes) with a test application among the Marvin Beans Examples.
Here are some guidelines to follow when designing your own plugin, as a
CalculatorPlugin subclass
The first step: go to the internet and download some code or write your own. The calculation code is assumed to work on one input molecule at a time, perform the calculation and then return various results of the calculation. The plugin class will first set the input molecule, then run the calculation and finally query the results, so it is a good idea to follow roughly the same implementation style in the calculation module: the more the calculation code follows this model, the easier your work will be when you write the plugin wrapper.
Then extend the abstract base plugin class chemaxon.marvin.plugin.CalculatorPlugin.
Here is the list of methods that have to be implemented:
This method sets the input molecule. Throw aabstract protected void setInputMolecule(Molecule mol) throws PluginExceptionPluginExceptionon any error.
This method sets the plugin specific parameters: thepublic void setParameters(Properties params) throws PluginExceptionparamsargument contains the plugin parameters aslong parameter name -> parameter valuepairs. (Thelong parameter namehere is without the "--" prefix: e.g. if you have--typeas a command line parameter then it will be present with keytypein this property table.) Your task is to convert the parameter values from string to the required format and set the parameter in the calculation module or store it in the plugin for later use. Throw aPluginExceptionon any error (unexpected format, unexpected value). All possible plugin parameters have a default value so a missing parameter should not cause any error: use its default value instead.
Checks the input molecule. Throws apublic void checkMolecule(Molecule mol) throws PluginExceptionPluginExceptionif the plugin calculation result is not defined for the given molecule (e.g. molecule is a reaction molecule or a molecule with R-groups). The exception message will be formed to an error message to the user and the molecule will not be processed if aPluginExceptionis thrown. Do nothing if the molecule is accepted.
This method performs the calculation and stores the results. Include those tasks that must be run once for each molecule and produce the calculation results in the end. Returnsabstract public boolean run() throws PluginExceptiontrueif the calculation was successful,falseon calculation problems. Again, throw aPluginExceptionon any error.
This method returns the queried result types. For example, thepublic Object[] getResultTypes()chargecalculation may have three result types:sigma,piandtotal, thelogpcalculation may have two result types:incrementsandmolecule. The built-in pluginscharge,logpandpkahave the--typecommand line parameter that specifies the required result types: this method returns those that are specified in this parameter. However, it is possible to return all available result types and not provide this choice.
This returns the domain that the calculation result for the specified result type refers to: currently it can bepublic int getResultDomain(Object type)ATOMorMOLECULE. For example, thelogPPluginreturnsATOMiftypeis"increments"and returnsMOLECULEiftypeis"molecule".
This returns the number of result items for the specified result type. Forpublic int getResultCount(Object type)ATOMresult domain this is usually the number of atoms in the molecule, forMOLECULEdomain this is usually1.
This returns the result for the specified result type and the specified result index: this index must be at leastpublic Object getResult(Object type, int index) throws PluginException0and less than the result count returned bygetResultCount(Object type)for this result type. In our case the result is a number: it must be wrapped into the derived class ofjava.lang.Numbercorresponding to its primitive type (e.g.doublemust be wrapped intojava.lang.Double).PluginExceptioncan be thrown on any error.
This returns a string representation of the result. The result type and index are also given: in some cases the string representation may include these or depend on these as well. Thepublic String getResultAsString(Object type, int index, Object result) throws PluginExceptionprotected String format(double x)can be used todouble -> Stringconversion with a given number of fractional digits. If you intend to use this formatting thenprotected void setDoublePrecision(int precision)has to be called once beforehand to set the maximum number of decimal digits allowed in the fractional portion of a number.PluginExceptioncan be thrown on any error.
Returns the color to be used when displaying the result. For example, this method is used when acidic pKa values are displayed in red while basic pKa values are displayed in blue. The color is returned as a singlepublic String getResultAsRGB(Object type, int index, Object result) throws PluginExceptionint(see the java.awt.Color.(int) for a definition of encoding a color into a singleint). The default implementation returns0which means that the result will be displayed using the current foreground color.PluginExceptioncan be thrown on any error.
This method is used to bring the molecule to a standardized form. Some calculations require a certain standardization preprocess, such as aromatization or a common form of certain functional groups (one prescribed tautomer or mezomer form). The current implementation performs only aromatization and nitro group and sulphynil group conversions (transforms to the neutral forms). If any other transformation is needed or no such transformation is necessary then you must implement this method. Be careful with transformations that change the atom set of the molecule since these change the atom indices as well: if the result domain ispublic void standardize(Molecule mol)ATOMthen after querying the results withgetResult(Object key, int index)andgetResultAsString(Object key, int index, Object result)the program will output the returned result for the specified atom index in the original molecule and not in the transformed one. If the standardization procedure changes the atom indices then the index given in these result query methods must be transformed to the corresponding atom index in the transformed molecule and the result for that atom index must be returned.
Returnspublic boolean isLicensed()trueif the plugin is licensed. Implement this only if you want to sell your plugin and protect it with a license key. The default implementation always returnstruewhich means that the plugin is free: no license key is required. This method returns only information about the licensing, license checking has to be implemented separately.
Do you have a question? Would you like to learn more? Please browse among the related topics on our support forum or search the website. If you want to suggest modifications or improvements to our documentation email our support directly!


