def test_distarray(self): from MDAnalysis.lib.distances import distance_array from MDAnalysis.lib.distances import transform_StoR, transform_RtoS R_mol1 = transform_StoR(self.S_mol1, self.box, backend=self.backend) R_mol2 = transform_StoR(self.S_mol2, self.box, backend=self.backend) # Try with box dists = distance_array(R_mol1, R_mol2, box=self.box, backend=self.backend) # Manually calculate distance_array manual = np.zeros((len(R_mol1), len(R_mol2))) for i, Ri in enumerate(R_mol1): for j, Rj in enumerate(R_mol2): Rij = Rj - Ri Rij -= round(Rij[2] / self.box[2][2]) * self.box[2] Rij -= round(Rij[1] / self.box[1][1]) * self.box[1] Rij -= round(Rij[0] / self.box[0][0]) * self.box[0] Rij = np.linalg.norm(Rij) # find norm of Rij vector manual[i][j] = Rij assert_almost_equal(dists, manual, self.prec, err_msg="distance_array failed with box") # Now check using boxV dists = distance_array(R_mol1, R_mol2, box=self.boxV, backend=self.backend) assert_almost_equal(dists, manual, self.prec, err_msg="distance_array failed with boxV")
def process(self): if self.writer is not None: # Make liposome whole residues = self.lipids.residues for res2 in residues : dr = residues[0].center_of_geometry()-res2.center_of_geometry() dr = pbc.unwrap_vector(dr, self.processor.currbox) res2.set_positions(res2.get_positions()+dr) # Center liposome xyz = self.processor.currsnap._pos com1 = np.median(self.lipids.get_positions(),axis=0) for residue in self.residue_atoms : com2 = xyz[residue.first:residue.last+1].mean(axis=0) dr = pbc.unwrap_vector(com1 - com2, self.processor.currbox) xyz[residue.first:residue.last+1] = xyz[residue.first:residue.last+1] + dr delta = com1 - self.processor.currbox/2.0 self.processor.currsnap._pos = xyz - delta self.writer.write(self.processor.currsnap) innercom = self.inner.center_of_geometry() outercom = self.outer.center_of_geometry() lipcom = np.asarray([0.5*(innercom+outercom)]) rinner = mddist.distance_array(lipcom,self.inner.positions,None).mean()*0.1 router = mddist.distance_array(lipcom,self.outer.positions,None).mean()*0.1 eigval, asphericity = geo.sphericity(self.inner.positions) axdevinner = np.sqrt(eigval.max()/eigval.mean())*100 eigval, asphericity = geo.sphericity(self.outer.positions) axdevout = np.sqrt(eigval.max()/eigval.mean())*100 self.records.append(mdactions.MDRecord(self.processor.currtime, [rinner,router,rinner**2*self.innerfac,router**2*self.outerfac, axdevinner, axdevout]))
def test_distarray(self): from MDAnalysis.lib.distances import distance_array from MDAnalysis.lib.distances import transform_StoR, transform_RtoS R_mol1 = transform_StoR(self.S_mol1, self.box) R_mol2 = transform_StoR(self.S_mol2, self.box) # Try with box dists = distance_array(R_mol1, R_mol2, box=self.box) # Manually calculate distance_array manual = np.zeros((len(R_mol1), len(R_mol2))) for i, Ri in enumerate(R_mol1): for j, Rj in enumerate(R_mol2): Rij = Rj - Ri Rij -= round(Rij[2] / self.box[2][2]) * self.box[2] Rij -= round(Rij[1] / self.box[1][1]) * self.box[1] Rij -= round(Rij[0] / self.box[0][0]) * self.box[0] Rij = np.linalg.norm(Rij) # find norm of Rij vector manual[i][j] = Rij assert_almost_equal(dists, manual, self.prec, err_msg="distance_array failed with box") # Now check using boxV dists = distance_array(R_mol1, R_mol2, box=self.boxV) assert_almost_equal(dists, manual, self.prec, err_msg="distance_array failed with boxV")
def _singleframe(self): distance_array(self.g1.positions, self.g2.positions, box=self.u.dimensions, result=self._result) # Maybe exclude same molecule distances if not self._exclusion_mask is None: self._exclusion_mask[:] = self._maxrange count = np.histogram(self._result, **self.rdf_settings)[0] self.count += count self.volume += self._ts.volume
def getCurvature(particledata, dimensions, cutoff=13): # np.set_printoptions(threshold=np.nan, linewidth=np.nan, precision=4) # b = np.array([1,0,0]) # a = np.array([-0.2,1,0]) # a1 = np.dot(a, b) / np.linalg.norm(b) # print(a1) coms = particledata.filter(['shiftx', 'shifty', 'shiftz']) orientations = particledata.filter(['ux', 'uy', 'uz']) distances_array = distance_array(coms.values, coms.values, box=dimensions) pairs = getPairs(distances_array, cutoff) origin_orientations = orientations.values[pairs[:, 0]] origin_connections = np.subtract(coms.values[pairs[:, 1]], coms.values[pairs[:, 0]]) # origin_connections = np.divide(origin_connections, 10) projections = np.einsum( 'ij,ij->i', origin_connections, origin_orientations ) # same as (origin_connections * origin_orientations).sum(axis=1) BUT FASTER projections_array = np.zeros_like(distances_array) pairs_t = pairs.T projections_array[tuple(pairs_t)] = projections projections_array[tuple([pairs_t[1], pairs_t[0]])] = projections sums = np.sum(projections_array, axis=1) nums = np.count_nonzero(projections_array, axis=1) averages = np.zeros_like(sums) averages[np.where( nums > 0)] = sums[np.where(nums > 0)] / nums[np.where(nums > 0)] coms = particledata.filter(['x', 'y', 'z']) distances_array = distance_array(coms.values, coms.values, box=None) pairs = getPairs(distances_array, cutoff) if len(pairs) == 0: return np.full((len(particledata.index), 1), np.nan, dtype=np.float32) origin_orientations = orientations.values[pairs[:, 0]] origin_connections = np.subtract(coms.values[pairs[:, 1]], coms.values[pairs[:, 0]]) # origin_connections = np.divide(origin_connections, 10) projections = np.einsum( 'ij,ij->i', origin_connections, origin_orientations ) # same as (origin_connections * origin_orientations).sum(axis=1) BUT FASTER projections_array = np.zeros_like(distances_array) pairs_t = pairs.T projections_array[tuple(pairs_t)] = projections projections_array[tuple([pairs_t[1], pairs_t[0]])] = projections _sums = np.sum(projections_array, axis=1) _nums = np.count_nonzero(projections_array, axis=1) _averages = np.zeros_like(_sums) _averages[np.where( _nums > 0)] = _sums[np.where(_nums > 0)] / nums[np.where(_nums > 0)] # nonan = np.where(~np.isnan(averages)) # condition = np.where(np.logical_or(averages[nonan]<-1, averages[nonan]>1)) condition = np.where(np.logical_or(averages < -1, averages > 1)) averages[condition] = _averages[condition] return np.nan_to_num(averages)
def __init__(self, mobiles, refs, method="hard_cut", radius=4.5, kwargs=None): """ Parameters ---------- mobiles : tuple(AtomGroup, AtomGroup) two contacting groups that change over time refs : tuple(AtomGroup, AtomGroup) two contacting atomgroups in their reference conformation. This can also be a list of tuples containing different atom groups radius : float, optional (4.5 Angstroms) radius within which contacts exist in refgroup method : string | callable (optional) Can either be one of ``['hard_cut' , 'soft_cut']`` or a callable with call signature ``func(r, r0, **kwargs)`` (the "Contacts API"). kwargs : dict, optional dictionary of additional kwargs passed to `method`. Check respective functions for reasonable values. """ universe = mobiles[0].universe super(Contacts, self).__init__(universe, mobiles) if method == 'hard_cut': self.fraction_contacts = hard_cut_q elif method == 'soft_cut': self.fraction_contacts = soft_cut_q else: if not callable(method): raise ValueError("method has to be callable") self.fraction_contacts = method # contacts formed in reference self.r0 = [] self.initial_contacts = [] if isinstance(refs[0], mda.core.groups.AtomGroup): refA, refB = refs self.r0.append(distance_array(refA.positions, refB.positions)) self.initial_contacts.append(contact_matrix(self.r0[-1], radius)) else: for refA, refB in refs: self.r0.append(distance_array(refA.positions, refB.positions)) self.initial_contacts.append( contact_matrix(self.r0[-1], radius)) self.fraction_kwargs = kwargs if kwargs is not None else {}
def contact_matrix(coord, cutoff=15.0, returntype="numpy", box=None): '''Calculates a matrix of contacts within a numpy array of type float32. There is a fast, high-memory-usage version for small systems (*returntype* = 'numpy'), and a slower, low-memory-usage version for larger systems (*returntype* = 'sparse'). If *box* dimensions are passed (``box = [Lx, Ly, Lz]``), then periodic boundary conditions are applied. Only orthorhombic boxes are currently supported. .. versionchanged:: 0.11.0 Keyword *suppress_progmet* and *progress_meter_freq* were removed. ''' if returntype == "numpy": adj = (distance_array(coord, coord, box=box) < cutoff) return adj elif returntype == "sparse": # Initialize square List of Lists matrix of dimensions equal to number of coordinates passed sparse_contacts = sparse.lil_matrix((len(coord), len(coord)), dtype='bool') if box is not None: # if PBC contact_matrix_pbc(coord, sparse_contacts, box, cutoff) else: # if no PBC contact_matrix_no_pbc(coord, sparse_contacts, cutoff) return sparse_contacts
def isParticleInStructureEnvironment(df, attributes, dimensions, fga_mode): xyz = np.array(dimensions[:3]) if fga_mode == "plane": plane = np.array([ xyz / 2 - attributes["system.plane_edge"] / 2, xyz / 2 + attributes["system.plane_edge"] / 2 ]) plane[0, 2] = xyz[2] / 2 - attributes["system.ljsigma"] * 3 plane[1, 2] = xyz[2] / 2 + attributes["system.ljsigma"] * 3 xcond = np.logical_and(df["x"] >= plane[0, 0], df["x"] <= plane[1, 0]) ycond = np.logical_and(df["y"] >= plane[0, 1], df["y"] <= plane[1, 1]) zcond = np.logical_and(df["z"] >= plane[0, 2], df["z"] <= plane[1, 2]) return np.logical_and.reduce((xcond, ycond, zcond)) elif fga_mode == "sphere": center = np.array([xyz / 2]) radius = float( attributes["system.ljsigma"])**(1.0 / 6) / (2.0 * np.sin( attributes["system.gamma"])) + attributes["system.ljsigma"] * 3 return (distance_array(center, df.filter(["x", "y", "z"]).values, box=dimensions) <= radius).ravel() elif fga_mode == "pair": plane = np.array([ xyz / 2 - attributes["system.plane_edge"] / 2, xyz / 2 + attributes["system.plane_edge"] / 2 ]) plane[0, 1] = xyz[1] / 2 - attributes["system.ljsigma"] * 3 plane[1, 1] = xyz[1] / 2 + attributes["system.ljsigma"] * 3 plane[0, 2] = xyz[2] / 2 - attributes["system.ljsigma"] * 3 plane[1, 2] = xyz[2] / 2 + attributes["system.ljsigma"] * 3 xcond = np.logical_and(df["x"] >= plane[0, 0], df["x"] <= plane[1, 0]) ycond = np.logical_and(df["y"] >= plane[0, 1], df["y"] <= plane[1, 1]) zcond = np.logical_and(df["z"] >= plane[0, 2], df["z"] <= plane[1, 2]) return np.logical_and.reduce((xcond, ycond, zcond))
def make_correspondance_by_position2(clusters_prev, clusters_curr, to_group): if not clusters_prev: return clusters_curr[:ARGS.to_keep] kept_clusters = [] com_prev = np.array( [cluster_center_of_mass(c, to_group) for c in clusters_prev]) com_curr = np.array( [cluster_center_of_mass(c, to_group) for c in clusters_curr]) dist_matrix = distances.distance_array(com_prev, com_curr) for i, dist in enumerate(dist_matrix): closest_cluster = np.where(dist == min(dist))[0] if len(closest_cluster) > 1: logging.warn( f"More than one same center of mass distance for cluster {i} correspondance. Assign the first." ) if len(clusters_curr[closest_cluster[0]].residues) < 150: print("OOOO") kept_clusters.append(clusters_curr[closest_cluster[0]]) return kept_clusters
def test_pbc_dist(self): from MDAnalysis.lib.distances import distance_array results = np.array([[37.629944]]) dists = distance_array(self.S_mol1, self.S_mol2, box=self.boxV) assert_almost_equal(dists, results, self.prec, err_msg="distance_array failed to retrieve PBC distance")
def get_contact_sum(self, i, l): """A method for checking if selection exists""" Ci = -1 selection = self.get_contacts(i, l) if selection: r_ij = distance_array(self.reference.coordinates(), self.close_contacts.coordinates()) Ci = numpy.sum(numpy.exp(-1 * (r_ij / self.r_eff))) return Ci
def distance(): segA = u.segments[0] r50 = segA.atoms.select_atoms('resid 50') r60 = segA.atoms.select_atoms('resid 60') da = distance_array(r50.positions, r60.positions) return da.min()
def contact_matrix(coord, cutoff=15.0, returntype="numpy", box=None): '''Calculates a matrix of contacts. There is a fast, high-memory-usage version for small systems (*returntype* = 'numpy'), and a slower, low-memory-usage version for larger systems (*returntype* = 'sparse'). If *box* dimensions are passed then periodic boundary conditions are applied. Parameters --------- coord : array Array of coordinates of shape ``(N, 3)`` and dtype float32. cutoff : float, optional, default 15 Particles within `cutoff` are considered to form a contact. returntype : string, optional, default "numpy" Select how the contact matrix is returned. * ``"numpy"``: return as an ``(N. N)`` :class:`numpy.ndarray` * ``"sparse"``: return as a :class:`scipy.sparse.lil_matrix` box : array-like or ``None``, optional, default ``None`` Simulation cell dimensions in the form of :attr:`MDAnalysis.trajectory.base.Timestep.dimensions` when periodic boundary conditions should be taken into account for the calculation of contacts. Returns ------- array or sparse matrix The contact matrix is returned in a format determined by the `returntype` keyword. See Also -------- :mod:`MDAnalysis.analysis.contacts` for native contact analysis .. versionchanged:: 0.11.0 Keyword *suppress_progmet* and *progress_meter_freq* were removed. ''' if returntype == "numpy": adj = (distance_array(coord, coord, box=box) < cutoff) return adj elif returntype == "sparse": # Initialize square List of Lists matrix of dimensions equal to number # of coordinates passed sparse_contacts = scipy.sparse.lil_matrix((len(coord), len(coord)), dtype='bool') if box is not None: # with PBC contact_matrix_pbc(coord, sparse_contacts, box, cutoff) else: # without PBC contact_matrix_no_pbc(coord, sparse_contacts, cutoff) return sparse_contacts
def test_point(self): ag = self.universe.select_atoms('point 5.0 5.0 5.0 3.5') d = distance_array(np.array([[5.0, 5.0, 5.0]], dtype=np.float32), self.universe.atoms.positions, box=self.universe.dimensions) idx = np.where(d < 3.5)[1] assert_equal(set(ag.indices), set(idx))
def dist_measure(sel1, sel2): """ This function outputs the minimum measured distance between the two input selections. """ from numpy import min as npmin return npmin( mdadist.distance_array(sel1.positions, sel2.positions, backend='OpenMP'))
def test_sphlayer(self, u): r1 = u.select_atoms('resid 1') cog = r1.center_of_geometry().reshape(1, 3) ag = u.select_atoms('sphlayer 2.4 6.0 resid 1') d = distance_array(u.atoms.positions, cog, box=u.dimensions) idx = set(np.where((d > 2.4) & (d < 6.0))[0]) assert idx == set(ag.indices)
def test_sphzone(self): r1 = self.u.select_atoms('resid 1') cog = r1.center_of_geometry().reshape(1, 3) ag = self.u.select_atoms('sphzone 5.0 resid 1') d = distance_array(self.u.atoms.positions, cog, box=self.box) idx = set(np.where(d < 5.0)[0]) assert_(idx == set(ag.indices))
def test_pbc_dist(self): from MDAnalysis.lib.distances import distance_array results = np.array([[37.629944]]) dists = distance_array(self.S_mol1, self.S_mol2, box=self.boxV, backend=self.backend) assert_almost_equal(dists, results, self.prec, err_msg="distance_array failed to retrieve PBC distance")
def sample(self, g1=None, g2=None, kargs1=None, kargs2=None): kargs1 = kargs1 or {} kargs2 = kargs2 or {} self.n_frames += 1 self.g2 = g2 if g1 is not None: self.g1 = g1 if g2 is None: self.g2 = self.g1 # all atoms by default (see __init__) ka1 = self.kargs1.copy() ka1.update(kargs1) ka2 = self.kargs2.copy() ka2.update(kargs2) if self.observable is not None: # determine weights, otherwise assumes number of atoms (default) fg1, fg2, error = self._compute_observable(ka1, ka2) if error is True: raise Exception( "Error, the observable passed to RDF should output " "an array (of scalar or vectors) the same size of " "the group") # numpy.histogram accepts negative weights self.rdf_settings['weights'] = self._determine_weights(fg1, fg2) # This still uses MDA's distance_array. Pro: works also in triclinic # boxes. Con: could be faster (?) _distances = np.zeros((len(self.g1), len(self.g2)), dtype=np.float64) distances.distance_array( self.g1.positions, self.g2.positions, box=self.universe.dimensions, result=_distances) count = np.histogram(_distances, **self.rdf_settings)[0] self.count += count box = self.universe.dimensions self.volume += np.product(box[:3]) self.nsamples += 1 self.n_squared += len(self.g1) * len(self.g2)
def test_around(self): r1 = self.u.select_atoms('resid 1') ag = self.u.select_atoms('around 5.0 resid 1') d = distance_array(self.u.atoms.positions, r1.positions, box=self.box) idx = set(np.where(d < 5.0)[0]) # Around doesn't include atoms from the reference group idx.difference_update(set(r1.indices)) assert_(idx == set(ag.indices))
def test_point_1(self): # The example selection ag = self.u.select_atoms('point 5.0 5.0 5.0 3.5') d = distance_array(np.array([[5.0, 5.0, 5.0]], dtype=np.float32), self.u.atoms.positions, box=self.box) idx = np.where(d < 3.5)[1] assert_equal(set(ag.indices), set(idx))
def test_spherical_zone(self, u, meth, periodic): sel = Parser.parse('sphzone 5.0 resid 1', u.atoms) sel = self.choosemeth(sel, meth, periodic) result = sel.apply(u.atoms) r1 = u.select_atoms('resid 1') box = u.dimensions if periodic else None cog = r1.center_of_geometry(pbc=periodic).reshape(1, 3) d = distance_array(u.atoms.positions, cog, box=box) ref = set(np.where(d < 5.0)[0]) assert ref == set(result.indices)
def _add_bonds(self): positions = fmutils.AverageStructure(self.atu.atoms).run().result distmat = distance_array(positions, positions, backend="OpenMP") if self._rmin > 0.: a0, a1 = np.where((distmat >= self._rmin) & (distmat <= self._rmax)) else: a0, a1 = np.where((distmat > self._rmin) & (distmat <= self._rmax)) bonds = topologyattrs.Bonds( set([(x, y) for x, y in zip(a0, a1) if y > x])) self._topology.add_TopologyAttr(bonds) self._generate_from_topology()
def _check_point(self, meth, periodic): sel = Parser.parse('point 5.0 5.0 5.0 3.0', self.u.atoms) sel = self.choosemeth(sel, meth, periodic) result = sel.apply(self.u.atoms) box = self.u.dimensions if periodic else None d = distance_array(np.array([[5.0, 5.0, 5.0]], dtype=np.float32), self.u.atoms.positions, box=box) ref = set(np.where(d < 3.0)[1]) assert_(ref == set(result.indices))
def test_point_2(self): ag1 = self.u.atoms[:10000] ag2 = ag1.select_atoms('point 5.0 5.0 5.0 3.5') d = distance_array(np.array([[5.0, 5.0, 5.0]], dtype=np.float32), ag1.positions, box=self.box) idx = np.where(d < 3.5)[1] assert_equal(set(ag2.indices), set(idx))
def _check_spherical_layer(self, meth, periodic): sel = Parser.parse('sphlayer 2.4 6.0 resid 1', self.u.atoms) sel = self.choosemeth(sel, meth, periodic) result = sel.apply(self.u.atoms) r1 = self.u.select_atoms('resid 1') cog = r1.center_of_geometry().reshape(1, 3) box = self.u.dimensions if periodic else None d = distance_array(self.u.atoms.positions, cog, box=box) ref = set(np.where((d > 2.4) & (d < 6.0))[0]) assert_(ref == set(result.indices))
def _check_spherical_zone(self, meth, periodic): sel = Parser.parse('sphzone 5.0 resid 1', self.u.atoms) sel = self.choosemeth(sel, meth, periodic) result = sel.apply(self.u.atoms) r1 = self.u.select_atoms('resid 1') cog = r1.center_of_geometry().reshape(1, 3) box = self.u.dimensions if periodic else None d = distance_array(self.u.atoms.positions, cog, box=box) ref = set(np.where(d < 5.0)[0]) assert_(ref == set(result.indices))
def test_pbc_wrong_wassenaar_distance(self, backend): from MDAnalysis.lib.distances import distance_array box = MDAnalysis.lib.mdamath.triclinic_vectors([2, 2, 2, 60, 60, 60]) a, b, c = box point_a = a + b point_b = .5 * point_a dist = distance_array(point_a[np.newaxis, :], point_b[np.newaxis, :], box=box, backend=backend) assert_almost_equal(dist[0, 0], 1) # check that our distance is different then the wassenaar distance as # expected. assert np.linalg.norm(point_a - point_b) != dist[0, 0]
def static_SAS(system, dict): """Uses system without trajectory to return SAS. No CHICOs input.""" # Location check print "Pre-initialising relevant variables and arrays...\n" print "Warning: SAS is a score based on NACHOs. Please make sure you understand the concept before using " \ "any potential results.\n" # Create variable SAS global SAS SAS = 0 global minDistDict minDistDict = {} for key in dict: # Assign row values to variables and convert to strings resid1 = str("resid %s and not name H*") % dict[key][0] resid2 = str("resid %s and not name H*") % dict[key][1] # Debug statement # Check if code is assigning strings correctly # print resid1, resid2 # Grab coordinates from resid variables. WARNING: get_positions() will change in MDAnalysis 16.0! coords1 = system.select_atoms(resid1).get_positions() coords2 = system.select_atoms(resid2).get_positions() # Pass coords variables to cdists.distance_array function ContactsMatrix = cdists.distance_array(coords1, coords2) # Append minimum to minDistArray minDistDict[key] = np.amin(ContactsMatrix) # Restore ContactsMatrix to 0, or it will get confused. ContactsMatrix = 0 # Take output from minDistArray if minDistDict is not None: for key in minDistDict: # Enter the arbitrary score: SAS (System Activation Score) if key < 8: if minDistDict[key] < args.cutoff: SAS -= 1 elif key > 7: if minDistDict[key] < args.cutoff: SAS += 1 return minDistDict, SAS
def test_point(self, u, periodic): sel = Parser.parse('point 5.0 5.0 5.0 3.0', u.atoms) if periodic: sel.periodic = True else: sel.periodic = False result = sel.apply(u.atoms) box = u.dimensions if periodic else None d = distance_array(np.array([[5.0, 5.0, 5.0]], dtype=np.float32), u.atoms.positions, box=box) ref = set(np.where(d < 3.0)[1]) assert ref == set(result.indices)
def _check_around(self, meth, periodic): sel = Parser.parse('around 5.0 resid 1', self.u.atoms) sel = self.choosemeth(sel, meth, periodic) result = sel.apply(self.u.atoms) r1 = self.u.select_atoms('resid 1') cog = r1.center_of_geometry().reshape(1, 3) box = self.u.dimensions if periodic else None d = distance_array(self.u.atoms.positions, r1.positions, box=box) ref = set(np.where(d < 5.0)[0]) # Around doesn't include atoms from the reference group ref.difference_update(set(r1.indices)) assert_(ref == set(result.indices))
def compute(self, inp, *args, **kwarg): # TODO generalise to set of points? """Compute the observable. :param AtomGroup inp: the input atom group :returns: atomic positions """ inp = self._to_atomgroup(inp) inp2 = self._to_atomgroup(args[0]) mask = np.asarray([0., 0., 0]) mask[self.dirmask] = 1.0 return distances.distance_array( inp.positions * mask, inp2.positions * mask, box=inp.universe.dimensions).ravel()
def test_spherical_layer(self, u, periodic): sel = Parser.parse('sphlayer 2.4 6.0 resid 1', u.atoms) if periodic: sel.periodic = True else: sel.periodic = False result = sel.apply(u.atoms) r1 = u.select_atoms('resid 1') box = u.dimensions if periodic else None cog = r1.center_of_geometry().reshape(1, 3) d = distance_array(u.atoms.positions, cog, box=box) ref = set(np.where((d > 2.4) & (d < 6.0))[0]) assert ref == set(result.indices)
def test_spherical_zone(self, u, periodic): sel = Parser.parse('sphzone 5.0 resid 1', u.atoms) if periodic: sel.periodic = True else: sel.periodic = False result = sel.apply(u.atoms) r1 = u.select_atoms('resid 1') box = u.dimensions if periodic else None cog = r1.center_of_geometry().reshape(1, 3) d = distance_array(u.atoms.positions, cog, box=box) ref = set(np.where(d < 5.0)[0]) assert ref == set(result.indices)
def generate_contacts( universe, selection, upper_cutoff=6.0, lower_cutoff=0.0, resid_separation=3 ): gr = universe.select_atoms(selection) distances = cdists.distance_array(gr.positions, gr.positions) triu = np.triu(distances) mask = np.argwhere((triu < upper_cutoff) & (triu > lower_cutoff)) contacts = [(atom1, atom2) for atom1, atom2 in mask \ if not abs(gr.atoms[atom1].resid - gr.atoms[atom2].resid) <= resid_separation] return gr, triu, set([ frozenset(pair) for pair in contacts ])
def _add_bonds(self): print(self.atu.bonds) positions = fmutils.AverageStructure(self.atu.atoms).run().result distmat = distance_array(positions, positions, backend="OpenMP") if self._rmin > 0.: a0, a1 = np.where((distmat >= self._rmin) & (distmat <= self._rmax)) else: print(self._rmax) a0, a1 = np.where((distmat > self._rmin) & (distmat <= self._rmax)) skeleton_bonds = set([(skeleton[0].ix, skeleton[1].ix) for skeleton in self.atu.bonds]) rmax_bonds = set([(x, y) for x, y in zip(a0, a1) if y > x]) all_bonds = skeleton_bonds.union(rmax_bonds) bonds = topologyattrs.Bonds(all_bonds) self._topology.add_TopologyAttr(bonds) self._generate_from_topology()
def test_around(self, u, periodic): sel = Parser.parse('around 5.0 resid 1', u.atoms) if periodic: sel.periodic = True else: sel.periodic = False result = sel.apply(u.atoms) r1 = u.select_atoms('resid 1') cog = r1.center_of_geometry().reshape(1, 3) box = u.dimensions if periodic else None d = distance_array(u.atoms.positions, r1.positions, box=box) ref = set(np.where(d < 5.0)[0]) # Around doesn't include atoms from the reference group ref.difference_update(set(r1.indices)) assert ref == set(result.indices)
def _single_run(self, start, stop): """Perform a single pass of the trajectory""" self.u.trajectory[start] # Calculate partners at t=0 box = self.u.dimensions if self.pbc else None # 2d array of all distances d = distance_array(self.h.positions, self.a.positions, box=box) if self.exclusions: # set to above dist crit to exclude d[self.exclusions] = self.d_crit + 1.0 # find which partners satisfy distance criteria hidx, aidx = numpy.where(d < self.d_crit) a = calc_angles(self.d.positions[hidx], self.h.positions[hidx], self.a.positions[aidx], box=box) # from amongst those, who also satisfiess angle crit idx2 = numpy.where(a > self.a_crit) hidx = hidx[idx2] aidx = aidx[idx2] nbonds = len(hidx) # number of hbonds at t=0 results = numpy.zeros_like(numpy.arange(start, stop, self._skip), dtype=numpy.float32) if self.time_cut: # counter for time criteria count = numpy.zeros(nbonds, dtype=numpy.float64) for i, ts in enumerate(self.u.trajectory[start:stop:self._skip]): box = self.u.dimensions if self.pbc else None d = calc_bonds(self.h.positions[hidx], self.a.positions[aidx], box=box) a = calc_angles(self.d.positions[hidx], self.h.positions[hidx], self.a.positions[aidx], box=box) winners = (d < self.d_crit) & (a > self.a_crit) results[i] = winners.sum() if self.bond_type is 'continuous': # Remove losers for continuous definition hidx = hidx[numpy.where(winners)] aidx = aidx[numpy.where(winners)] elif self.bond_type is 'intermittent': if self.time_cut: # Add to counter of where losers are count[~ winners] += self._skip * self.u.trajectory.dt count[winners] = 0 # Reset timer for winners # Remove if you've lost too many times # New arrays contain everything but removals hidx = hidx[count < self.time_cut] aidx = aidx[count < self.time_cut] count = count[count < self.time_cut] else: pass if len(hidx) == 0: # Once everyone has lost, the fun stops break results /= nbonds return results
def distance(): segA = u.segments[0] r50 = segA.atoms.select_atoms("resid 50") r60 = segA.atoms.select_atoms("resid 60") da = distance_array(r50.positions, r60.positions) return da.min()
def main(): ap = argparse.ArgumentParser(description='Calculate Vina score for a static conformation') ap.add_argument('receptor', help='PDBQT file for receptor') ap.add_argument('ligand', help='PDBQT file for ligand, positioned where you want it relative to receptor') args = ap.parse_args() # Load receptor and ligand # This will take damn near forever due to guessing bonds ligand_u = mda.Universe(args.ligand, guess_bonds=True, vdwradii=autodock_vdw_radii) receptor_u = mda.Universe(args.receptor, guess_bonds=True, vdwradii=autodock_vdw_radii) # Vina score is described in: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3041641 # We are only calculating the c_inter component # Calculate distance matrix dists = mdadist.distance_array(receptor_u.atoms.positions, ligand_u.atoms.positions) # Calculate d_ij, which is just the distance minus the vdW radii of the two atoms # I'm sure this is incredibly slow and there is some fast numpy array way to do this. # Probably by pre-assembling arrays of vdW radii and doing array subtractions. dij = dists.copy() hydrophobic_mask = np.zeros_like(dists) hbond_mask = np.zeros_like(dists) for r_i in range(len(receptor_u.atoms)): for l_i in range(len(ligand_u.atoms)): r_atom = receptor_u.atoms[r_i] l_atom = ligand_u.atoms[l_i] r_vdw = atom_kind_data[r_atom.type][RADIUS] l_vdw = atom_kind_data[l_atom.type][RADIUS] dij[r_i, l_i] -= r_vdw dij[r_i, l_i] -= l_vdw # If both atoms are hydrophobic, we care about their hydrophobic interaction score if r_atom.type in hydrophobic_atom_types and l_atom.type in hydrophobic_atom_types: hydrophobic_mask[r_i, l_i] = 1 # Determine which atoms are involved in H-bonds if could_hbond(r_atom, l_atom): hbond_mask[r_i, l_i] = 1 print('There are {} atom pairs in total'.format(len(receptor_u.atoms)*len(ligand_u.atoms))) print('{} atom pairs have hydrophobic interactions'.format(int(np.sum(hydrophobic_mask)))) print('{} atom pairs can H-bond'.format(int(np.sum(hbond_mask)))) # Calculate gauss1 component of score. Weight = -0.0356 # gauss1(d) = exp(-(d/0.5)^2) gauss1 = np.exp(-np.square(dij/0.5)) # Calculate gauss2 component of score. Weight = -0.00516 # gauss2(d) = exp(-((d-3)/2)^2) gauss2 = np.exp(-np.square((dij-3.0)/2)) # Calculate repulsion component of score. Weight = 0.840 # repulsion(d) = d^2 if d < 0, or 0 otherwise repulsion = np.square(np.clip(dij, a_min=None, a_max=0.0)) # Calculate hydrophobic component of score. Weight = -0.0351 # Both atoms must be hydrophobic or score is zero. # hydrophobic(d) = 1 when d < 0.5 # = 0 when d > 1.5 # = linearly interpolated between these values otherwise hydrophobic = np.clip(1.5-dij, a_min=0.0, a_max=1.0) hydrophobic *= hydrophobic_mask # Calculate H-bonding component of score. Weight = -0.587 # hbond(d) = 1 when d < -0.7 # = 0 when d > 0 # = linearly interpolated between these values otherwise hbond = np.clip(-10*dij/7, a_min=0.0, a_max=1.0) hbond *= hbond_mask # Distance cutoff is 8A in Vina dist_cutoff_mask = np.zeros_like(dists) dist_cutoff_mask[dists <= 8] = 1 gauss1 *= dist_cutoff_mask gauss2 *= dist_cutoff_mask repulsion *= dist_cutoff_mask hydrophobic *= dist_cutoff_mask hbond *= dist_cutoff_mask print('Gauss1: {}'.format(GAUSS1_WEIGHT*np.sum(gauss1))) print('Gauss2: {}'.format(GAUSS2_WEIGHT*np.sum(gauss2))) print('Repuls: {}'.format(REPULSION_WEIGHT*np.sum(repulsion))) print('Hphobc: {}'.format(HYDROPHOBIC_WEIGHT*np.sum(hydrophobic))) print('H-bond: {}'.format(HBOND_WEIGHT*np.sum(hbond))) c_inter = GAUSS1_WEIGHT*np.sum(gauss1) + \ GAUSS2_WEIGHT*np.sum(gauss2) + \ REPULSION_WEIGHT*np.sum(repulsion) + \ HYDROPHOBIC_WEIGHT*np.sum(hydrophobic) + \ HBOND_WEIGHT*np.sum(hbond) print(c_inter)
def contact_matrix(coord, cutoff=15.0, returntype="numpy", box=None): '''Calculates a matrix of contacts. There is a fast, high-memory-usage version for small systems (*returntype* = 'numpy'), and a slower, low-memory-usage version for larger systems (*returntype* = 'sparse'). If *box* dimensions are passed then periodic boundary conditions are applied. Parameters --------- coord : array Array of coordinates of shape ``(N, 3)`` and dtype float32. cutoff : float, optional, default 15 Particles within `cutoff` are considered to form a contact. returntype : string, optional, default "numpy" Select how the contact matrix is returned. * ``"numpy"``: return as an ``(N. N)`` :class:`numpy.ndarray` * ``"sparse"``: return as a :class:`scipy.sparse.lil_matrix` box : array-like or ``None``, optional, default ``None`` Simulation cell dimensions in the form of :attr:`MDAnalysis.trajectory.base.Timestep.dimensions` when periodic boundary conditions should be taken into account for the calculation of contacts. Returns ------- array or sparse matrix The contact matrix is returned in a format determined by the `returntype` keyword. Note ---- :module:`scipy.sparse` is require for using *sparse* matrices; if it cannot be imported then an `ImportError` is raised. .. versionchanged:: 0.11.0 Keyword *suppress_progmet* and *progress_meter_freq* were removed. ''' if returntype == "numpy": adj = (distance_array(coord, coord, box=box) < cutoff) return adj elif returntype == "sparse": if sparse is None: # hack: if we are running with minimal dependencies then scipy was # not imported and we have to bail here (see scipy import at top) raise ImportError("For sparse matrix functionality you need to " "import scipy.") # Initialize square List of Lists matrix of dimensions equal to number # of coordinates passed sparse_contacts = sparse.lil_matrix((len(coord), len(coord)), dtype='bool') if box is not None: # with PBC contact_matrix_pbc(coord, sparse_contacts, box, cutoff) else: # without PBC contact_matrix_no_pbc(coord, sparse_contacts, cutoff) return sparse_contacts
def anal_jointdist(prot,rfirst,mols,cutoff,midz,box,mat,matburr,buried=None) : """ Calculates the joint probability of residue interactions Parameters ---------- prot : AtomSelection the protein atoms rfirst : NumpyArray the first atom of each residue in the protein mols : NumpyArray the centroid of the molecule of interest cutoff : float the contact cut-off midz : float the middle of the bilayer box : NumpyArray the box sides mat : NumpyArray the joint probability for non-buried molecules matburr : NumpyArray the joint probability for buried molecules buried : NumpyArray of boolean, optional flag to indicate buried molecule """ imat = np.zeros(mat.shape) imatburr = np.zeros(matburr.shape) # Calculate all distances at once if box is not None : dist_all = distances.distance_array(np.array(mols), prot.get_positions(), box) else : kdtree = KDTree(dim=3, bucket_size=10) kdtree.set_coords(prot.get_positions()) # Loop over all molecules for mi,mol in enumerate(mols) : if box is not None : dist = dist_all[mi,:] else : dist = np.ones(prot.get_positions().shape[0])+cutoff kdtree.search(np.array([mol]), cutoff) for i in kdtree.get_indices() : dist[i] = 0.0 # Check if this molecule is on if dist.min() >= cutoff : continue # Check contacts for reach residue for i in range(len(rfirst)-1) : if dist[rfirst[i]:rfirst[i+1]].min() >= cutoff : continue if (buried is not None and buried[mi]) : imatburr[i,i] = 1 else : imat[i,i] = 1 for j in range(i+1,len(rfirst)-1) : if dist[rfirst[j]:rfirst[j+1]].min() >= cutoff : continue if (buried is not None and buried[mi]) : imatburr[i,j] = 1 imatburr[j,i] = 1 else : imat[i,j] = 1 imat[j,i] = 1 return (mat+imat,matburr+imatburr)
def anal_contacts(prot,rfirst,mols,cutoff,midz,box,molfile,resfile, burresfile=None,buried=None,reslist=None,reslistfile=None) : """ Calculates a range of contacts and write out contact vectors to files Parameters ---------- prot : AtomSelection the protein atoms rfirst : NumpyArray the first atom of each residue in the protein mols : NumpyArray the centroid of the molecule of interest cutoff : float the contact cut-off midz : float the middle of the bilayer box : NumpyArray the box sides molfile : fileobject the file to write molecular contacts to resfile : fileobject the file to write residue contacts to burresfile : fileobject, optional the file to write buried residue contacts to buried : NumpyArray of boolean, optional flag to indicate buried molecule reslist : list a list of residues to write out individual mol contacts reslistfile : fileobject the file to write out individual mol contacts to """ molon = np.zeros(len(mols),dtype=bool) reson = np.zeros(len(rfirst)-1,dtype=bool) if buried is not None : burreson = np.zeros(len(rfirst)-1,dtype=bool) if reslist is not None : resonlist = np.zeros([len(reslist),len(mols)],dtype=bool) # Calculate all distances at once if box is not None : dist_all = distances.distance_array(np.array(mols), prot.get_positions(), box) else : kdtree = KDTree(dim=3, bucket_size=10) kdtree.set_coords(prot.get_positions()) # Loop over all molecules for mi,mol in enumerate(mols) : if box is not None : dist = dist_all[mi,:] else : dist = np.ones(prot.get_positions().shape[0])+cutoff kdtree.search(np.array([mol]), cutoff) for i in kdtree.get_indices() : dist[i] = 0.0 # Check if this molecule is on molon[mi] = dist.min() < cutoff if molon[mi] : # Check contacts for reach residue for i in range(len(rfirst)-1) : if dist[rfirst[i]:rfirst[i+1]].min() < cutoff : if (burresfile is not None and buried[mi]) : burreson[i] = True else : reson[i] = True if reslist is not None and i in reslist: resonlist[reslist.index(i),mi] = True # Write state information to file write_booleans(molfile,molon) write_booleans(resfile,reson) if buried is not None : write_booleans(burresfile,burreson) if reslist is not None: write_booleans(reslistfile,resonlist.reshape(len(reslist)*len(mols)))
# Author: Samuel Genheden [email protected] """ Script to find the space where to insert the solutes """ import sys import MDAnalysis import MDAnalysis.lib.distances as mddist import numpy as np u = MDAnalysis.Universe(sys.argv[1]) lipids = u.select_atoms("name PO4 and resid 9108:10688") com = np.asarray([lipids.center_of_geometry()]) radius = mddist.distance_array(com,lipids.positions,None).mean() print "outside sphere %.3f %.3f %.3f %.3f"%(com[0,0], com[0,1], com[0,2], radius+10) print "inside box 0.0 0.0 0.0 %.3f %.3f %.3f"%tuple(u.dimensions[:3])
def get_heavy_atom_distances(self): self.heavy_atoms = self.u.select_atoms("not type 102 103 104 109 111 112") dismat = distance_array(self.heavy_atoms.coordinates(), self.heavy_atoms.coordinates())