How to build a small molecule with ISIS/Draw

 

1 Introduction
2 What's you need
3 The molecule to build
4 From 2D to 3D

 

1 Introduction

This tutorial explains how to build a small molecule using ISIS/Draw and how to convert it from 2D to 3D. It was superseded by the ISIS/Draw plug-in that perform the same operations in automatic way.

 

2 What's you need

 

3 The molecule to build

 

4 From 2D to 3D

In order to understand the procedure, the step-by step analysis of the 2D to 3D.c script is required. A base knowledge of C language programming is required. To see the script source code, click 2d to 3D.c with the right mouse button and select Edit.
In the first section of the script is included the generic vega.h header and the routines that will be used to fix the bond order (../Common/Bndord.h). The VGVLL definition is required to inform the vega.h header that it's a C-script compiled on-the-fly by VEGA ZZ.

/********************************************
****       2D to 3D Converter V1.2       ****
**** Add the hydrogens and convert to 3D ****
**** (c) 2006-2007, Alessandro Pedretti  ****
********************************************/
#define VGVLL
#include <vega.h>
#include "../Common/Bndord.h"

The C semantic requires to declare the function before its use. Error() is the routine to show the error messages.

/**** Prototypes ****/
void         Error(const char *Err);

The script entry point is defined by the following declaration. The function is called by VEGA ZZ when the script is started and some data is passed by the VegaInfo structure.

/**** Main code ****/
int VllMain(VGP_VEGAINFO *VegaInfo)
{

This is the declaration of the variables that are used inside the VllMain() function:

  ATOMO *             Atm;
  float               Zmax, Zmin;
  VG_BOOL             AddH   = TRUE;
  VG_BOOL             Charge = FALSE;
  VG_BOOL             Planar = TRUE;

Atm is an ATOMO pointer used to scan the atom list (see below), Zmax and Zmin are floating point variables to calculate if a molecule is 2D, AddH, Charge and Planar are Boolean variables to establish respectively to add the hydrogens, fix the atom charges and to determine the algorithm to add the hydrogens if the molecule is planar (2D).

Check if the workspace is empty reading the total number of atoms in the TotalAtm item of the VegaInfo structure. If no atoms are present, an error message is shown calling the Error() function:

  /**** Check if the molecule is in the workspace ****/
  if (!*(VegaInfo -> TotalAtm)) {
    Error("No molecule");
    return 0;
  }

Check if a calculation is already running, retrieving the IsRunning variable value from VEGA ZZ. The library VegaCmd function defined in the vega.h header, allows to send commands to VEGA ZZ. In this specific case the Get command is sent with the IsRunning argument. The returning value is put in the Result pointer of the VegaInfo structure (for more information see the C-script programming section in the VEGA ZZ manual).  If a calculation is already running, the script aborts and shows an error message.

  /**** Check if a calc is already running ****/
  VegaCmd("Get IsRunning");
  if (*VegaInfo -> Result == '1') {
    Error("A calculation is already running");
    return 0;
  }

In order to decide to add or not the hydrogens, a check is performed:

  /**** Check if the molecule has the hydrogens ****/
  for(Atm = *VegaInfo -> BegAtm; Atm; Atm = Atm -> Ptr) {
    if ((!Atm -> Elem.C[1]) && (Atm -> Elem.C[0] == 'H')) {
      AddH = FALSE;
      break;
    }
  } /* End of for (Atm) */

The for loop scans the atom list and if a hydrogen atom is found, the AddH variable is set to FALSE and the loop is ended.

Now check if the molecule is really 2D, evaluating if all Z coordinates are in the ±0.5 Å range referred to the Z coordinate of the first atom in the list:

  /**** Check if the molecule is 2D ****/
  Atm  = *VegaInfo -> BegAtm;
  Zmax = Atm -> z + 0.5f;
  Zmin = Atm -> z - 0.5f;
  Atm  = Atm -> Ptr;
  while(Atm) {
    if ((Atm -> z > Zmax) || (Atm -> z < Zmin)) {
      Planar = FALSE;
      break;
    }
    Atm = Atm -> Ptr;
  } /* End of while (Atm) */

If the Z coordinate of one atom exceed the range, the Planar variable is set to FALSE and the while loop ends.

If needed (evaluating if the AddH variable is TRUE), add the hydrogen with the more appropriate algorithm:

  /**** Add the hydrogens ****/
  if (AddH) {
    if (Planar) VegaCmd("AddHydrog GenBo ResEnd 1 0");
    else VegaCmd("AddHydrog Gen ResEnd 1 0");
    Charge = FALSE;
  } else {

If the molecule is 2D (Planar is TRUE), the bond order-based algorithm is used, otherwise the geometry-based algorithm is applied. The Charge variable is set to FALSE, because adding the hydrogens the atom charges must always reassigned.

If the molecule doesn't require the procedure to add the hydrogens, check if the charges are already assigned:

    /**** Check if the charges are assigned ****/
    for(Atm = *VegaInfo -> BegAtm; Atm; Atm = Atm -> Ptr) {
      if (Atm -> Charge) {
        Charge = TRUE;
        break;
      }
    } /* End of for (Atm) */
  }

If a non-zero charged atom is found, the Charge variable is set to TRUE and the for loop exits.

If needed (Charge is TRUE), the atom charges are assigned with the Gasteiger-Marsili method:

  /**** Fix the charges ****/
  if (!Charge) VegaCmd("Charge Gasteiger 0");

AMMP requires the bond order correctly assigned to calculate the bond length, the aromatic rings need to be fixed in order to obtain all bonds in partial double form and not in single - double alternated form as built by ISIS/Draw. For this reason, the AromFix() routine is called:

  /**** Fix the aromatic bonds ****/
  AromFix(*VegaInfo -> BegAtm);

To understand how it works, please see its source code in the Bndord.h header.

Normalize the coordinates, translating the molecule at the Cartesian axis origin (0, 0, 0):

  /**** Normalize the coordinates ****/
  VegaCmd("mNormalize");

Now the AMMP interface initialization is required. The first step consists in the force field type selection:

  /**** Set the AMMP force field ****/
  VegaCmd("AmmpSetFF SP4");

than the structure is sent to the AMMP host:

  /**** Send the molecule to AMMP ****/
  VegaCmd("AmmpSendMol None");

Before starting the AMMP calculation, you need to notify to VEGA ZZ that you intend to use that software. This procedure is required because the AMMP run is totally asynchronous.

  /**** Notify a new AMMP calc to VEGA ZZ ****/
  VegaCmd("AmmpStartCalc");

Now perform the Gauss-Siedel distance geometry optimization. This is the first rough optimization, consisting in the finding of the best bond length. Angles, torsions and impropers (hybrids) are kept fixed.

  /**** Gauss-Siedel distance geometry optimization ****/
  VegaCmd("AmmpSend \""
          "use none bond angle torsion hybrid nonbon;"
          "setf mxdq 1.0;"
          "gsdg 15 0;"
          "bindump coord;"
          "\"");

The AmmpSend VEGA ZZ command allows to send one or more concatenated commands to AMMP. Each command must be separated by a semicolon character (;): Use sets the force field terms, Setf is a floating point assignment command and it sets the Mxqd AMMP variable to 1.0 (electrostatic update term), Gsdg starts the bond length optimization (15 steps) and when the calculation is finish, Bindump returns the atom coordinates from AMMP to VEGA ZZ.

After the bond length optimization, a geometry minimization is required and so 50 steps of steepest descent minimization are performed (toler = 1):

  /**** Perform the steepest minimization ****/
  VegaCmd("AmmpSend \""
          "steep 50 1;"
          "bindump coord;"
          "\"");

At the end of the minimization, the structure is dumped into VEGA ZZ.

The final structure is obtained performing 3000 steps of conjugate gradients minimization (toler = 0.01):

  /**** Perform the conjugate minimization ****/
  VegaCmd("AmmpSend \""
          "cngdel 3000 0 0.01;"
          "confirmend;"          /* Required to revert VEGA ZZ to the normal */
          "bindump coord;"       /* when the last command is finish.         */
          "\"");

The ConfirmEnd command is required to notify to VEGA ZZ when the conjugate gradient calculation is finish.

The script is now finish and it must return that it's all right:

  return 0;
}

 This is the code for the error handling:

/**** Show an error ****/
void Error(const char *Err)
{
  VegaCmdEx("MessageBox \"%s.\" \"ERROR\" 16", Err);
}

Show the formatted error message.

On this ground, you can understand the power of the VEGA ZZ script engine that allows not only to execute several operations in few seconds, but also to expand the standard capabilities.