Subsections

 
2.2 Accessing Data

OEGrid provides three ways to index data inside a grid. They are ordered here by speed of access, ie, grid elements perform simple pointer arithmetic where spatial coordinates require floating point computation.

Grid Element
Index into the underlying data array
Grid Indices
Unsigned integers less than the dimension for that axis
Spatial Coordinates
Cartesian coordinates of any point inside the grid, where OEGrid determines the closest grid point

 
2.2.1 Spatial Coordinates

Assuming grid is already filled with relevant values, Listing 2.1 demonstrates how to retrieve the grid value closest to the atoms in the molecule mol.

float xyz[3];
for (OEIter<OEAtomBase> atom = mol.GetAtoms(); atom; ++atom)
{
  mol.GetCoords(atom, xyz);
  if (grid.IsInGrid(xyz[0], xyz[1], xyz[2]))
  {
    float val = grid(xyz[0], xyz[1], xyz[2]);
    // Do something with val
  }
}

Listing:2.1 Getting values associated with coordinates

Since operator() returns a reference, the same code can be used to assign values to grid points. This is demonstrated in Listing 2.2.

float xyz[3];
for (OEIter<OEAtomBase> atom = mol.GetAtoms(); atom; ++atom)
{
  mol.GetCoords(atom, xyz);
  if (grid.IsInGrid(xyz[0], xyz[1], xyz[2]))
    grid(xyz[0], xyz[1], xyz[2]) = atom.GetPartialCharge();
}

Listing:2.2 Setting values associated with coordinates

Note that in the preceding two code fragments bounds checking has been explicitly performed by the IsInGrid method. Using operator() without this bounds check can lead to a segmentation fault. However, IsInGrid can become an expensive operation if performed excessively. One way to avoid this is to make sure your grid is big enough to enclose the object being worked on. For example: using OEGetCenterAndExtents on the molecule and then using OEMakeGridFromCenterAndExtents to construct the grid, as shown in Listing 2.3.

//mol has already been defined as an OEGraphMol with relevant data
float center[3];
float extents[3];
OEScalarGrid grid;
float spacing = 0.75;

OEGetCenterAndExtents(mol, center, extents);
OEMakeGridFromCenterAndExtents(grid, center, extents, spacing);

Listing:2.3 Creating a grid large enough to hold a molecule

 
2.2.2 Grid Indices

Grid indices are faster than spatial coordinates because there is no floating point arithmetic to perform. Grid indices make it easy to quickly iterate over a small portion of the grid. Listing 2.4 demonstrates iterating over all 27 gird points adjacent to and including the grid point given by the grid index (ix, iy, iz).

unsigned int ix, iy, iz; // Some arbitrary grid point

// Make sure not to go past grid bounds
unsigned int mini = (ix == 0 ? 0 : ix - 1);
unsigned int minj = (iy == 0 ? 0 : iy - 1);
unsigned int mink = (iz == 0 ? 0 : iz - 1);
unsigned int maxi = min(ix + 1, grid.GetXDim());
unsigned int maxj = min(iy + 1, grid.GetYDim());
unsigned int maxk = min(iz + 1, grid.GetZDim());

for (unsigned int k = mink; k < maxk; k++)
  for (unsigned int j = minj; j < maxj; j++)
    for (unsigned int i = mini; i < maxi; i++)
      float val = grid(i, j, k);

Listing:2.4 Iterating over neighbor points

 
2.2.3 Grid Element

Grid values are actually stored in a large one dimensional block of memory. The fastest way to access all the data is to linearly scan through memory. Listing 2.5 demonstrates how to square every value in the grid.

for (unsigned int i = 0; i < grid.GetSize(); ++i)
  grid[i] = grid[i] * grid[i];

Listing:2.5 Iterating over all points

Direct access to the memory is given by the GetValues method. Listing 2.6 demonstrates the quickest way to zero out all the grid values.

memset(grid.GetValues(), 0, grid.GetSize()*sizeof(float));

Listing:2.6 Clearing all grid data

Listing 2.7 shows how grid elements relate to three dimensional indexes. This is meant to be an instructional piece of code, not to be actually used. To make a copy of a grid OEScalarGrid's copy constructor should be used.

OEScalarGrid grid;
// Fill grid with something relevant

OEScalarGrid cgrid;
OEGridCopyGeometry(cgrid, grid);

unsigned int el = 0;
for (unsigned int k = 0; k < grid.GetZDim(); k++)
  for (unsigned int j = 0; j < grid.GetYDim(); j++)
    for (unsigned int i = 0; i < grid.GetXDim(); i++)
    {
       cgrid[el] = grid(i, j, k);
       el++;
    }

Listing:2.7 Element ordering