def __init__(self, solute, gro, traj, build_monomer, spline=False, npores=4): self.npores = npores print('Loading trajectory...', end='', flush=True) self.t = md.load(traj, top=gro) print('Done!') self.solute = topology.Solute(solute) self.monomer = topology.LC(build_monomer) # monomer head group only for testing purposes # ref = ['C', 'C1', 'C2', 'C3', 'C4', 'C5'] # solutes_indices = [a.index for a in self.t.topology.atoms if a.residue.name == solute and a.name in ref] # self.nsolute = 400 # self.solute_vectors = self.direction_vectors() # self.com = physical.center_of_mass(self.t.xyz[:, solutes_indices, :], [v for v in self.solute.mass.values()][:6]) solutes_indices = [a.index for a in self.t.topology.atoms if a.residue.name == solute] self.nsolute = len(solutes_indices) // self.solute.natoms self.solute_vectors = self.direction_vectors() self.com = physical.center_of_mass(self.t.xyz[:, solutes_indices, :], [v for v in self.solute.mass.values()]) reference_atoms = [a.index for a in self.t.topology.atoms if a.name in self.monomer.pore_defining_atoms and a.residue.name in self.monomer.residues] self.pore_centers = physical.avg_pore_loc(4, self.t.xyz[:, reference_atoms, :], self.t.unitcell_vectors) self.pore_vectors = self.pore_center_vectors() self.costheta = self.angles() self.nematic_order_parameter = self.nematic()
def restrict_to_pore(self, r, dwell_fraction=0.95, tails=False, build_monomer='NAcarb11V.gro', spline=False, buffer=0, npores=4): """ Restrict calculations to center of masses (COMs) that primarily stay in the pore OR tail region :param r: radius of pore. Anything greater than r from the pore center is considered the tail region :param dwell_fraction: Fraction of time spent in region of interest required in order to keep trajectory :param tails: if True, then restrict calculations to COMs primarily in the tail region :param build_monomer: monomer coordinate file of which liquid crystal membrane is mode :param spline: track pore centers with a 3D spline :param buffer: Do not count molecules below _buffer_ or above z-box-vector - _buffer_ :type r: float :type tails: bool :type build_monomer: str :type spline: bool :type buffer: float """ # find pore centers pore_defining_atoms = topology.LC(build_monomer).pore_defining_atoms pore_atoms = [a.index for a in self.t.topology.atoms if a.name in pore_defining_atoms] if spline: print('Creating pore splines') pore_centers = physical.trace_pores(self.t.xyz[:, pore_atoms, :], self.t.unitcell_vectors, 20) else: pore_centers = physical.avg_pore_loc(npores, self.t.xyz[:, pore_atoms, :], self.t.unitcell_vectors) results = 0 if tails: results = 1 inregion = physical.partition(self.com, pore_centers, r, buffer=buffer, unitcell=self.t.unitcell_vectors, npores=npores)[results] dwell = np.full((self.t.n_frames, self.com.shape[1]), False, dtype=bool) for t in range(self.t.n_frames): dwell[t, inregion[t]] = True fraction_dwelled = np.sum(dwell, axis=0) / self.t.n_frames # fraction of total time spend in region of interest keep = np.where(fraction_dwelled >= dwell_fraction)[0] self.com = self.com[:, keep, :]
def __init__(self, gro, top, monomer, rbounds=[0.3, 1], restraints=False, mpi=False, nproc=4): """Add set number of water molecules to the tail region of a given configuration :param gro: initial coordinate file to be solvated :param top: topology associated with gro :param nwater: number of water molecules to add to tails :param ref: Names of atoms where water molecules will be placed in proximity to :param rbounds: list with min, max (in that order) distance of water molecules from a reference atom (nm) :type gro: str :type top: str :type nwater: int :type ref: list :type rbounds: list """ self.t = md.load(gro) self.coordinates = self.t.xyz[0, :, :] # initial coordinates self.natoms = self.t.n_atoms # number of atoms in the system self.rmin, self.rmax = rbounds self.restraints = restraints self.mpi = mpi self.np = nproc self.gmx = "gmx" if self.mpi: self.gmx = "mpirun -np %s gmx_mpi" % self.np # handle mdtraj renaming SOL to HOH self.res = [] self.ids = [] for a in self.t.topology.atoms: if a.residue.name == 'HOH': self.res.append('SOL') if a.name == 'H1': self.ids.append('HW1') elif a.name == 'H2': self.ids.append('HW2') elif a.name == 'O': self.ids.append('OW') else: self.res.append(a.residue.name) self.ids.append(a.name) self.full_box = self.t.unitcell_vectors # unitcell vectors self.box_gromacs = [ self.full_box[0, 0, 0], self.full_box[0, 1, 1], self.full_box[0, 2, 2], self.full_box[0, 0, 1], self.full_box[0, 2, 0], self.full_box[0, 1, 0], self.full_box[0, 0, 2], self.full_box[0, 1, 2], self.full_box[0, 2, 0] ] self.water = topology.Molecule('HOH').xyz[0, ...] self.water_alignment_vector = self.water[0, :] - np.mean( self.water, axis=0) # vector around which water molecule can be rotated self.topname = top with open(self.topname, 'r') as f: self.top = [] for line in f: self.top.append(line) self.add_water_placeholder() self.monomer = topology.LC(monomer) self.ref_atoms = [ a.index for a in self.t.topology.atoms if a.name in self.monomer.tail_atoms ] # indices of reference atoms self.ref_atom_locations = self.t.xyz[ 0, self.ref_atoms, :] # coordinates of reference atoms self.placement_options = [ i for i in range(len(self.ref_atoms)) ] # list of indices corresponding to atoms in ref_atom_locations # need to remove hardcoding. Probably use llclib.topology.Residue self.water_ids = ['OW', 'HW1', 'HW2'] # water atom names self.water_res = ['SOL', 'SOL', 'SOL'] # water residue name write_em_mdp(5) # 5 step energy minimization
def __init__(self, gro, traj, residue, monomer, begin=0, end=-1, skip=1, npores=4, atoms=None): """ Calculate the radial distribution of residue in a hexagonal phase LLC Membrane :param gro: Coordinate file (.gro or .pdb) :param traj: Trajectory file (.trr or .xtc) :param residue: Name of residue whose rdf will be calculated :param monomer: Name of monomer used to build LLC Membrane :param begin: First frame index :param end: Last frame index :param skip: Skip every 'skip' frames :param npores: Number of pores :param atoms: Calculate RDF of atoms specified here which are a part of residue :type gro: str :type traj: str :type residue: str :type monomer: str :type begin: int :type end: int :type skip: int :type npores: int :type atoms: list """ self.t = md.load(traj, top=gro)[begin:end:skip] self.box = self.t.unitcell_vectors self.npores = npores if residue == 'SOL': # workaround for mdtraj residue = 'HOH' self.residue = topology.Residue(residue) self.monomer = topology.LC('%s.gro' % monomer) if atoms is not None and 'all' not in atoms: res = [ a.index for a in self.t.topology.atoms if a.residue.name == residue and a.name in atoms ] mass = [ self.residue.mass[v] for v in self.residue.mass.keys() if v in atoms ] else: res = [ a.index for a in self.t.topology.atoms if a.residue.name == residue ] mass = [v for v in self.residue.mass.values()] self.com = physical.center_of_mass(self.t.xyz[:, res, :], mass) self.r = None self.density = None self.bootstraps = None self.errorbars = None
def __init__(self, gro, build_monomer, residue, traj=False, begin=0, end=-1, skip=1, npores=4): """ Define the system and boundaries for pore and tail region :param gro: coordinate file :param build_monomer: name of annotated monomer coordinate file :param traj: trajectory file :param begin: first frame to include :param end: last frame to include :param skip: skip every n frames :param npores: number of pores. Assumes that atoms are number sequentially by pore """ print('Loading trajectory...', flush=True, end='') if traj: self.t = md.load(traj, top=gro)[begin:end:skip] else: self.t = md.load(gro) print('Done') # coordinates and unit cell dimensions self.pos = self.t.xyz box = self.t.unitcell_vectors self.box = [ box[0, 0, 0], box[0, 1, 1], box[0, 2, 2], box[0, 0, 1], box[0, 2, 0], box[0, 1, 0], box[0, 0, 2], box[0, 1, 2], box[0, 2, 0] ] # gromacs format self.ids = [a.name for a in self.t.topology.atoms] self.res = [a.residue.name for a in self.t.topology.atoms] self.pore_atoms = topology.LC(build_monomer).pore_defining_atoms self.npores = npores self.pore_centers = None self.pore_water = [] self.tail_water = [] if residue == 'SOL': for a in self.t.topology.atoms: if a.residue.name == 'HOH': # workaround for mdtraj if a.name == 'O': a.name = 'OW' elif a.name == 'H1': a.name = 'HW1' elif a.name == 'H2': a.name = 'HW2' for a in self.t.topology.atoms: if a.residue.name == 'HOH': a.residue.name = 'SOL' self.residue = topology.Residue(residue) self.residue_indices = np.array([ a.index for a in self.t.topology.atoms if a.residue.name == residue ]) if self.residue_indices.size == 0: sys.exit("No residue %s found" % residue) residue_atom_names = [ a.name for a in self.t.topology.atoms if a.residue.name == residue ] masses = [ self.residue.mass[x] for x in residue_atom_names[:self.residue.natoms] ] print('Calculating centers of mass...', end='', flush=True) self.com = physical.center_of_mass( self.pos[:, self.residue_indices, :], masses) print('Done!')
def add_dummies(t, residue, dummy_residue, out='dummies.gro', nmon=400): """ TODO: This script can be improved quite a bit, but it is functional for now while I develop xlink.py :param t: topology object created from mdtraj :return: """ LC = topology.LC('%s.gro' % dummy_residue) residues = [a.residue.name for a in t.topology.atoms] if 'HOH' in residues: for a in t.topology.atoms: if a.residue.name == 'HOH': if a.name == 'O': a.name = 'OW' elif a.name == 'H1': a.name = 'HW1' elif a.name == 'H2': a.name = 'HW2' for a in t.topology.atoms: # if you change residue name before changing names, this won't work if a.residue.name == 'HOH': a.residue.name = 'SOL' if a.residue.name == residue: a.residue.name = dummy_residue nsol = 0 for i in set(residues): if i != residue: nsol += residues.count(i) natoms = t.n_atoms - nsol nmonomers = nmon Hd = LC.dummies ndummies = len(Hd) atomspmon = int(natoms / nmonomers) v = t.unitcell_vectors with open(out, 'w') as f: f.write('This is a .gro file\n') f.write('%s\n' % (int((atomspmon + ndummies) * nmonomers) + nsol)) count = 1 count2 = 0 for a in t.topology.atoms: if count2 != 0 and count2 % atomspmon == 0 and count < (nmonomers * (atomspmon + ndummies)): for j in range(ndummies): f.write('{:5d}{:5s}{:>5s}{:5d}{:8.3f}{:8.3f}{:8.3f}\n'.format(int(count / atomspmon), dummy_residue, Hd[j], count, 0, 0, 0)) count += 1 f.write('{:5d}{:5s}{:>5s}{:5d}{:8.3f}{:8.3f}{:8.3f}\n'.format(a.residue.index + 1, a.residue.name, a.name, count, t.xyz[0, count2, 0], t.xyz[0, count2, 1], t.xyz[0, count2, 2])) count += 1 count2 += 1 f.write('{:10f}{:10f}{:10f}{:10f}{:10f}{:10f}{:10f}{:10f}{:10f}\n'.format(v[0, 0, 0], v[0, 1, 1], v[0, 2, 2], v[0, 0, 1], v[0, 2, 0], v[0, 1, 0], v[0, 0, 2], v[0, 1, 2], v[0, 2, 0]))