def init_histogram(self, **kwargs): # needs to be done separately because we might need additional information # after init (at least I cannot think of a better way...) smin = kwargs.pop("smin", self.min_coordinates(padding=self.padding)) smax = kwargs.pop("smax", self.max_coordinates(padding=self.padding)) BINS = fixedwidth_bins(self.delta, smin, smax) self.arange = zip(BINS["min"], BINS["max"]) self.bins = BINS["Nbins"] # create empty grid with the right dimensions (and get the edges) grid, edges = numpy.histogramdd(numpy.zeros((1, 3)), bins=self.bins, range=self.arange, normed=False) grid *= 0.0 h = grid.copy() self.grid = grid self.edges = edges self._h = h # temporary for accumulation
def density_from_Universe( universe, delta=1.0, atomselection="name OH2", metadata=None, padding=2.0, cutoff=0, soluteselection=None, verbosity=3, use_kdtree=True, **kwargs ): """Create a density grid from a MDAnalysis.Universe object. density_from_dcd(universe, delta=1.0, atomselection='name OH2', ...) --> density :Arguments: universe :class:`MDAnalysis.Universe` object with a trajectory :Keywords: atomselection selection string (MDAnalysis syntax) for the species to be analyzed ["name OH2"] delta approximate bin size for the density grid in Angstroem (same in x,y,z) (It is slightly adjusted when the box length is not an integer multiple of delta.) [1.0] metadata dictionary of additional data to be saved with the object padding increase histogram dimensions by padding (on top of initial box size) in Angstroem [2.0] soluteselection MDAnalysis selection for the solute, e.g. "protein" [``None``] cutoff With *cutoff*, select '<atomsel> NOT WITHIN <cutoff> OF <soluteselection>' (Special routines that are faster than the standard AROUND selection) [0] verbosity: int level of chattiness; 0 is silent, 3 is verbose [3] parameters dict with some special parameters for :class:`~hop.sitemap.Density` (see doc) kwargs metadata, parameters are modified and passed on to :class:`~hop.sitemap.Density` :Returns: :class:`hop.sitemap.Density` """ try: universe.selectAtoms("all") universe.trajectory.ts except AttributeError: errmsg = "density_from_Universe(): The universe must be a proper MDAnalysis.Universe instance." logger.fatal(errmsg) raise TypeError(errmsg) u = universe if cutoff > 0 and soluteselection is not None: # special fast selection for '<atomsel> not within <cutoff> of <solutesel>' notwithin_coordinates = notwithin_coordinates_factory( u, atomselection, soluteselection, cutoff, use_kdtree=use_kdtree ) def current_coordinates(): return notwithin_coordinates() else: group = u.selectAtoms(atomselection) def current_coordinates(): return group.coordinates() coord = current_coordinates() logger.info( "Selected %d atoms out of %d atoms (%s) from %d total.", coord.shape[0], len(u.selectAtoms(atomselection)), atomselection, len(u.atoms), ) # mild warning; typically this is run on RMS-fitted trajectories and # so the box information is rather meaningless box, angles = u.trajectory.ts.dimensions[:3], u.trajectory.ts.dimensions[3:] if tuple(angles) <> (90.0, 90.0, 90.0): logger.warn("Non-orthorhombic unit-cell --- make sure that it has been remapped properly!") # Make the box bigger to avoid as much as possible 'outlier'. This # is important if the sites are defined at a high density: in this # case the bulk regions don't have to be close to 1 * n0 but can # be less. It's much more difficult to deal with outliers. The # ideal solution would use images: implement 'looking across the # periodic boundaries' but that gets complicate when the box # rotates due to RMS fitting. smin = numpy.min(coord, axis=0) - padding smax = numpy.max(coord, axis=0) + padding BINS = fixedwidth_bins(delta, smin, smax) arange = zip(BINS["min"], BINS["max"]) bins = BINS["Nbins"] # create empty grid with the right dimensions (and get the edges) grid, edges = numpy.histogramdd(numpy.zeros((1, 3)), bins=bins, range=arange, normed=False) grid *= 0.0 h = grid.copy() pm = CustomProgressMeter( u.trajectory.numframes, interval=10, format="Histograming %(other)d atoms in frame %(step)5d/%(numsteps)d [%(percentage)5.1f%%]\r", ) for ts in u.trajectory: coord = current_coordinates() if len(coord) == 0: continue h[:], edges[:] = numpy.histogramdd(coord, bins=bins, range=arange, normed=False) grid += h # accumulate average histogram pm.echo(ts.frame, len(coord)) numframes = u.trajectory.numframes / u.trajectory.skip grid /= float(numframes) # pick from kwargs metadata = kwargs.pop("metadata", {}) metadata["psf"] = u.filename # named psf for historical reasons metadata["dcd"] = u.trajectory.filename # named dcd for historical reasons metadata["atomselection"] = atomselection metadata["numframes"] = numframes metadata["totaltime"] = round( u.trajectory.numframes * u.trajectory.delta * u.trajectory.skip_timestep * hop.constants.get_conversion_factor("time", "AKMA", "ps"), 3, ) metadata["dt"] = ( u.trajectory.delta * u.trajectory.skip_timestep * hop.constants.get_conversion_factor("time", "AKMA", "ps") ) metadata["time_unit"] = "ps" metadata["dcd_skip"] = u.trajectory.skip_timestep # frames metadata["dcd_delta"] = u.trajectory.delta # in AKMA if cutoff > 0 and soluteselection is not None: metadata["soluteselection"] = soluteselection metadata["cutoff"] = cutoff # in Angstrom parameters = kwargs.pop("parameters", {}) parameters["isDensity"] = False # must override # all other kwargs are discarded # Density automatically converts histogram to density for isDensity=False g = Density(grid=grid, edges=edges, unit=dict(length="Angstrom"), parameters=parameters, metadata=metadata) logger.info("Histogram completed (initial density in Angstrom**-3)") return g
def __init__( self, psf, pdb, delta=1.0, atomselection="name OH2", metadata=None, padding=4.0, sigma=None, verbosity=3 ): """Construct the density from psf and pdb and the atomselection. DC = BfactorDensityCreator(psf, pdb, delta=<delta>, atomselection=<MDAnalysis selection>, metadata=<dict>, padding=2, sigma=None) density = DC.PDBDensity() psf Charmm psf topology file pdb PDB file atomselection selection string (MDAnalysis syntax) for the species to be analyzed delta approximate bin size for the density grid (same in x,y,z) (It is slightly adjusted when the box length is not an integer multiple of delta.) metadata dictionary of additional data to be saved with the object padding increase histogram dimensions by padding (on top of initial box size) sigma width (in Angstrom) of the gaussians that are used to build up the density; if None then uses B-factors from pdb verbosity=int level of chattiness; 0 is silent, 3 is verbose For assigning X-ray waters to MD densities one might have to use a sigma of about 0.5 A to obtain a well-defined and resolved x-ray water density that can be easily matched to a broader density distribution. """ from MDAnalysis import Universe set_verbosity(verbosity) # set to 0 for no messages u = Universe(psf, pdbfilename=pdb) group = u.selectAtoms(atomselection) coord = group.coordinates() logger.info( "BfactorDensityCreator: Selected %d atoms (%s) out of %d total.", coord.shape[0], atomselection, len(u.atoms), ) smin = numpy.min(coord, axis=0) - padding smax = numpy.max(coord, axis=0) + padding BINS = fixedwidth_bins(delta, smin, smax) arange = zip(BINS["min"], BINS["max"]) bins = BINS["Nbins"] # get edges by doing a fake run grid, self.edges = numpy.histogramdd(numpy.zeros((1, 3)), bins=bins, range=arange, normed=False) self.delta = numpy.diag(map(lambda e: (e[-1] - e[0]) / (len(e) - 1), self.edges)) self.midpoints = map(lambda e: 0.5 * (e[:-1] + e[1:]), self.edges) self.origin = map(lambda m: m[0], self.midpoints) numframes = 1 if sigma is None: # histogram individually, and smear out at the same time # with the appropriate B-factor if numpy.any(group.bfactors == 0.0): wmsg = "BfactorDensityCreator: Some B-factors are Zero." warnings.warn(wmsg, category=hop.MissingDataWarning) logger.warn(wmsg) rmsf = Bfactor2RMSF(group.bfactors) grid *= 0.0 # reset grid self.g = self._smear_rmsf(coord, grid, self.edges, rmsf) else: # histogram 'delta functions' grid, self.edges = numpy.histogramdd(coord, bins=bins, range=arange, normed=False) logger.info("Histogrammed %6d atoms from pdb.", len(group.atoms)) # just a convolution of the density with a Gaussian self.g = self._smear_sigma(grid, sigma) try: metadata["psf"] = psf except TypeError: metadata = dict(psf=psf) metadata["pdb"] = pdb metadata["atomselection"] = atomselection metadata["numframes"] = numframes metadata["sigma"] = sigma self.metadata = metadata # Density automatically converts histogram to density for isDensity=False logger.info("BfactorDensityCreator: Histogram completed (initial density in Angstrom**-3)\n")