I am having trouble understanding what exactly the Density object produces from the DensityAnalysis class. The documentation is found here.
Running the code is not the problem, but understanding what exactly the Density object produces and how to interpret the information.
What is meant by the "(113, 113, 113) bins" I've seen examples from the MDAnalysis User guide but I still can't understand what this is or how to interpret it.
from MDAnalysis.analysis.density import Density
from MDAnalysis.analysis.density import DensityAnalysis
from MDAnalysis import *
import numpy as np
PDB = '/Users/joveyosagie/Desktop/1vmd6lu7.pdb'
DCD = '/Users/joveyosagie/Desktop/1vmd6lu7.dcd'
u = Universe(PDB, DCD)
protein = u.select_atoms('protein')
OH2 = u.select_atoms('name OH2')
OH2 = u.select_atoms('name OH2') #select for water atoms
D = DensityAnalysis(OH2, delta = 1.0) # each bin in histogram has size of 1 Angstrom
D.run()
D.density
[Out]Density density with (113, 113, 113) bins
The
MDAnalysis.analysis.density.Densityobject holds the 3D histogram that was generated withDensityAnalysis. The way a density is generated is by counting how often a particle shows up in one small region of space — a volume element or voxel (orthorhombic box with e.g., 1 Å length, butDensity.deltatells you exactly the voxel dimensions) or called a "bin". We average over all frames of a trajectory and normalize the count to get a density (particles per volume). The raw NumPy array with shape(num_bins_x, num_bins_y, num_bins_z)is accessible asDensity.gridThe density is associated with the coordinate system of the original simulation. Thus, we also need to know where the origin of the grid of voxels is (
Density.originholds this information). Withorigin,delta, and the shape of the array we can now calculate where each bin is located in space. TheDensity.edgesattribute provides the value of the bin edge along the x, y, and z axes. For instanceedges = [np.array(-2.5, -0.5, 1.5, 3.5]), np.array([0., 1., 2.]), np.array([2.5, 4.5])]belongs to a grid with shape(3, 2, 1)withdelta = np.array(2.0, 1.0, 2.0]). The bin in the lower left hand front corner is at origin(-1.5, 0.5, 3.5)(the origin is at the bin's center) and contains points with coordinates -2.5 ≤ x < -0.5, 0 ≤ y < 1, and 2.5 ≤ z < 4.5.The class contains methods to change in which units the density is stored, namely
Density.convert_density(). This method changes the underlying data by multiplying the values stored ingridwith an appropriate factor.Other methods are inherited from the
gridData.core.Gridclass that forms the basis forDensity. See the GridDataFormats documentation for what else one can do with these classes. For instance, one can treat twoDensityobjects as numpy arrays and perform arithmetic on them such as subtracting them to get a difference density.Example: comparing water densities
You can subtract densities if they were generated on the same coordinate system (i.e., have the same edges).
Let's compare the water density for two simulations to see what the ligand does to the water:
u_apoUniverseu_holoFirst superimpose trajectories on a common reference structure so that the proteins are in the same coordinate system. You can use
MDAnalysis.analysis.align.AlignTrajas described under Aligning a trajectory with AlignTraj or see the more elaborate instructions in the User Guide on density analysis under Centering, aligning, and making molecules whole with on-the-fly transformations.We then need to make sure that our densities are analyzed in the same coordinate system.
More help?
If you have more questions please have a look at how to participate in the MDAnalysis community — we have a discord server and mailing lists where people (users and developers) are happy to help and discuss.