def set_radii(self, igb=0, radius_set='mbondi'): """ Sets the radius set to a new one using parmed """ # If someone sets an igb, change to the appropriate radius set if igb: if igb == 1: radius_set = 'mbondi' elif igb == 2: radius_set = 'mbondi2' elif igb == 5: radius_set = 'mbondi2' elif igb == 7: radius_set = 'bondi' elif igb == 8: radius_set = 'mbondi3' if not radius_set in [ 'mbondi', 'mbondi2', 'mbondi3', 'bondi', 'amber6' ]: raise InputError('Bad radius set! Choose from ' + 'mbondi, mbondi2, mbondi3, bondi, and amber6') parmed = which('parmed.py') change_str = ("setOverwrite True\n" + "changeRadii %s\n" % radius_set + "parmout %s\n" % self.prmtop + "go\n") process = Popen( [parmed, '-q', '-n', str(self.prmtop)], stdin=PIPE, stderr=PIPE, stdout=PIPE) (output, error) = process.communicate(change_str) if process.wait(): raise ProgramError('parmed.py failed to change radii!') # Reload our topology file now that we've changed radius sets self.prmtop = AmberParm(str(self.prmtop))
def get_shrot_region(args, x, y, z, size): with open(args.pdb) as f: lines = f.readlines() atoms = [] for l in lines: if l.startswith('ATOM'): l = l.split() atoms.append(l[5:8]) atoms = np.array(atoms, dtype=float) parm = AmberParm(args.prmtop) radii = [] for atom in parm.atom_list: nbidx = parm.LJ_types[atom.attype] radii.append(float(parm.LJ_radius[nbidx - 1])) # convert meshgrid to a matrix and find indexes of all points # which are inside molecule xyz = np.c_[x.flatten(), y.flatten(), z.flatten()] ktree = cKDTree(xyz) mask = [] for atom, r in zip(atoms, radii): excluded_r = r * args.vdw_multiple excl_indxs = ktree.query_ball_point(atom, excluded_r) mask.extend(excl_indxs) mask = list(set(mask)) # create shrot range from indexes short_range = np.zeros(xyz.shape[0], dtype='bool') #all false array short_range[mask] = True return short_range.reshape(size)
def set_radii(self, igb=0, radius_set='mbondi'): """ Sets the radius set to a new one using parmed """ # If someone sets an igb, change to the appropriate radius set if igb: if igb == 1: radius_set = 'mbondi' elif igb == 2: radius_set = 'mbondi2' elif igb == 5: radius_set = 'mbondi2' elif igb == 7: radius_set = 'bondi' elif igb == 8: radius_set = 'mbondi3' if not radius_set in ['mbondi', 'mbondi2', 'mbondi3', 'bondi', 'amber6']: raise InputError('Bad radius set! Choose from ' + 'mbondi, mbondi2, mbondi3, bondi, and amber6') parmed = which('parmed.py') change_str = ("setOverwrite True\n" + "changeRadii %s\n" % radius_set + "parmout %s\n" % self.prmtop + "go\n") process = Popen([parmed, '-q', '-n', str(self.prmtop)], stdin=PIPE, stderr=PIPE, stdout=PIPE) (output, error) = process.communicate(change_str) if process.wait(): raise ProgramError('parmed.py failed to change radii!') # Reload our topology file now that we've changed radius sets self.prmtop = AmberParm(str(self.prmtop))
class AmberSystem(object): """ An Amber system with a topology file and input coordinate file """ # ============================== def __init__(self, prmtop, inpcrd): # Only load the inpcrd file if it actually exists. # if os.path.exists(inpcrd): self.prmtop = AmberParm(prmtop, inpcrd) # else: self.prmtop = AmberParm(prmtop) self.prmtop = AmberParm(prmtop) self.inpcrd = inpcrd # ============================== def periodic(self): """ Returns whether or not a topology file is set up for PBC """ # PBCs are indicated by a non-zero IFBOX pointer return bool(self.prmtop.ptr('ifbox')) # ============================== def query_radii(self): """ Returns the radii set in the topology file """ return self.prmtop.parm_data['RADIUS_SET'][0] # ============================== def set_radii(self, igb=0, radius_set='mbondi'): """ Sets the radius set to a new one using parmed """ # If someone sets an igb, change to the appropriate radius set if igb: if igb == 1: radius_set = 'mbondi' elif igb == 2: radius_set = 'mbondi2' elif igb == 5: radius_set = 'mbondi2' elif igb == 7: radius_set = 'bondi' elif igb == 8: radius_set = 'mbondi3' if not radius_set in ['mbondi', 'mbondi2', 'mbondi3', 'bondi', 'amber6']: raise InputError('Bad radius set! Choose from ' + 'mbondi, mbondi2, mbondi3, bondi, and amber6') parmed = which('parmed.py') change_str = ("setOverwrite True\n" + "changeRadii %s\n" % radius_set + "parmout %s\n" % self.prmtop + "go\n") process = Popen([parmed, '-q', '-n', str(self.prmtop)], stdin=PIPE, stderr=PIPE, stdout=PIPE) (output, error) = process.communicate(change_str) if process.wait(): raise ProgramError('parmed.py failed to change radii!') # Reload our topology file now that we've changed radius sets self.prmtop = AmberParm(str(self.prmtop))
def run(parm_file_name, traj_file_name, asu_prmtop_file_name, asu_rst7_file_name, prop_a, prob_b, prop_c, target_unit_cell, atoms_per_uc, wrap, buffer, spacegroup=' '): parm = AmberParm(parm_file_name) traj = NetCDFTraj.open_old(traj_file_name) n_frames = traj.frame U, invU, UCbox = get_U_invU(asu_rst7_file_name) start_atm, end_atm = calc_start_end_atm(atoms_per_uc, target_unit_cell, prop_a, prop_b, prop_c) # for frame in range(n_frames): # parm = AmberParm(parm_file_name) for frame in range(0, 1): coords = traj.coordinates(frame) frac_crds = get_frac_crds(coords, traj, U) cntred_frac_crds = center_frac_coords(frac_crds, parm, start_atm, end_atm) # atom_selection1 = select_atoms(cntred_frac_crds, parm, buffer, solvent=True) print frame # print atom_selection1 # print frac_crds[9794] # print cntred_frac_crds[9794] # if wrap: # wrap_coords(parm, frac_crds, cntred_frac_crds, prop_a, prop_b, prop_c, buffer, solvent=True) atom_selection = select_atoms(cntred_frac_crds, parm, buffer, solvent=True) frac_crds = rev_translate_frac_crds(frac_crds, target_unit_cell, prop_a, prop_b, prop_c) coords = get_cart_crds(frac_crds, traj, invU).flatten() # print atom_selection # print cntred_frac_crds[9794] write_pdb(coords, parm, atom_selection, 'uc%d_frame%d' % (target_unit_cell, frame), UCbox, spacegroup) # write_pdb(coords, parm, atom_selection1, 'uc%d_frame%d_nowrap' %(target_unit_cell,frame)) write_amber_files(coords, parm, 'uc%d_frame%d' % (target_unit_cell, frame), atom_selection) # import code; code.interact(local=dict(globals(), **locals())) return atom_selection
def read_amber_prm(pfile, cfile): prmtop = AmberParm(pfile) crds = read_rstf(cfile) atids = list(range(1, len(prmtop.parm_data['ATOM_NAME']) + 1)) resids = list(range(1, len(prmtop.parm_data['RESIDUE_LABEL']) + 1)) if len(prmtop.parm_data['ATOM_NAME']) != len(crds): raise ReadError('The toplogy and coordinates file are not \ consistent in the atom numbers.') residues = {} atoms = {} for i in range(0, len(prmtop.parm_data['RESIDUE_LABEL'])): resid = i + 1 resname = prmtop.parm_data['RESIDUE_LABEL'][i] if i < len(prmtop.parm_data['RESIDUE_LABEL']) - 1: resconter = list(range(prmtop.parm_data['RESIDUE_POINTER'][i], \ prmtop.parm_data['RESIDUE_POINTER'][i+1])) else: resconter = list(range(prmtop.parm_data['RESIDUE_POINTER'][i], \ len(prmtop.parm_data['ATOM_NAME'])+1)) residues[resid] = Residue(resid, resname, resconter) for j in resconter: gtype = 'ATOM' atid = j atname = prmtop.parm_data['ATOM_NAME'][j - 1] element = prmtop.parm_data['ATOMIC_NUMBER'][j - 1] atomtype = prmtop.parm_data['AMBER_ATOM_TYPE'][j - 1] crd = crds[j - 1] charge = prmtop.parm_data['CHARGE'][j - 1] try: element = AtnumRev[element] except: print(resname, atname, atomtype) element = 'X' atoms[j] = Atom(gtype, atid, atname, element, atomtype, crd, charge, \ resid, resname) mol = Molecule(atoms, residues) return prmtop, mol, atids, resids
def get_rmin2_radii(prmtop): """ Return a list of r_min/2 values """ try: parm = AmberParm(prmtop) radii = [] for atom in parm.atom_list: nbidx = parm.LJ_types[atom.attype] radii.append(float(parm.LJ_radius[nbidx - 1])) except IndexError: print('Couldnt open {} using AmberParm'.format(prmtop)) print('Assuming single atom topology') with open(prmtop) as f: for l in f: if 'JONES_ACOEF' in l: f.next() acoef = float(f.next()) f.next() f.next() bcoef = float(f.next()) radii = [(acoef / bcoef * 2)**(1. / 6) / 2] return radii
def visualize_molecule(args): with open(args.pdb) as f: lines = f.readlines() names = [] atoms = [] for l in lines: if l.startswith('ATOM'): l = l.split() names.append(l[2]) atoms.append(l[5:8]) atoms = np.array(atoms, dtype=float) colours = paint_atoms(names) #get vdw and plot if args.prmtop: parm = AmberParm(args.prmtop) radii = [] for atom in parm.atom_list: nbidx = parm.LJ_types[atom.attype] radii.append(float(parm.LJ_radius[nbidx - 1])) else: radii = [1. for i in atoms] for (x, y, z), r, c in zip(atoms, radii, colours): #print('visualizing atom') mlab.points3d(x, y, z, scale_factor=r * 1.25, resolution=20, color=c)
def natom(topfile): parm = AmberParm(topfile) return parm.ptr("NATOM")
#! /usr/bin/env python import sander from chemistry.amber.readparm import AmberParm, Rst7 import numpy as np pdb = '3stl' parm = AmberParm('4amber_%s.prmtop' % pdb) #topo rst = Rst7.open('4amber_%s.rst7' % pdb) #box sander.setup(parm, rst.coordinates, rst.box, sander.pme_input()) ene, frc = sander.energy_forces() print ene.tot print max(frc) import code code.interact(local=dict(globals(), **locals())) sander.cleanup()
def main(opt): # Check all of the arguments if not os.path.exists(opt.prmtop): raise CpinInputError('prmtop file (%s) is missing' % opt.prmtop) # Process the arguments that take multiple args resstates = process_arglist(opt.resstates, int) resnums = process_arglist(opt.resnums, int) notresnums = process_arglist(opt.notresnums, int) resnames = process_arglist(opt.resnames, str) notresnames = process_arglist(opt.notresnames, str) minpka = opt.minpka maxpka = opt.maxpka if not opt.igb in (2, 5, 8): raise CpinInputError('-igb must be 2, 5, or 8!') if resnums is not None and notresnums is not None: raise CpinInputError( 'Cannot specify -resnums and -notresnums together') if resnames is not None and notresnames is not None: raise CpinInputError( 'Cannot specify -resnames and -notresnames together') if opt.intdiel != 1 and opt.intdiel != 2: raise CpinInputError('-intdiel must be either 1 or 2 currently') # Set the list of residue names we will be willing to titrate titratable_residues = [] if notresnames is not None: for resname in residues.titratable_residues: if resname in notresnames: continue titratable_residues.append(resname) elif resnames is not None: for resname in resnames: if not resname in residues.titratable_residues: raise CpinInputError('%s is not a titratable residue!' % resname) titratable_residues.append(resname) else: titratable_residues = residues.titratable_residues[:] solvent_ions = [ 'WAT', 'Na+', 'Br-', 'Cl-', 'Cs+', 'F-', 'I-', 'K+', 'Li+', 'Mg+', 'Rb+', 'CIO', 'IB', 'MG2' ] # Filter titratable residues based on min and max pKa new_reslist = [] for res in titratable_residues: if getattr(residues, res).pKa < minpka: continue if getattr(residues, res).pKa > maxpka: continue new_reslist.append(res) titratable_residues = new_reslist del new_reslist # Make sure we still have a couple residues if len(titratable_residues) == 0: raise CpinInputError('No titratable residues fit your criteria!') # Load the topology file parm = AmberParm(opt.prmtop) # Replace an un-set notresnums with an empty list so we get __contains__() if notresnums is None: notresnums = [] # If we have a list of residue numbers, check that they're all titratable if resnums is not None: for resnum in resnums: if resnum > parm.ptr('nres'): raise CpinInputError('%s only has %d residues. (%d chosen)' % (parm, parm.ptr('nres'), resnum)) if resnum <= 0: raise CpinInputError('Cannot select negative residue numbers.') resname = parm.parm_data['RESIDUE_LABEL'][resnum - 1] if not resname in titratable_residues: raise CpinInputError( 'Residue number %s [%s] is not titratable' % (resnum, resname)) else: # Select every residue except those in notresnums resnums = [] for resnum in range(1, parm.ptr('nres') + 1): if resnum in notresnums: continue resnums.append(resnum) solvated = False first_solvent = 0 if 'WAT' in parm.parm_data['RESIDUE_LABEL']: solvated = True for i, res in enumerate(parm.parm_data['RESIDUE_LABEL']): if res in solvent_ions: first_solvent = parm.parm_data['RESIDUE_POINTER'][i] break main_reslist = TitratableResidueList(system_name=opt.system, solvated=solvated, first_solvent=first_solvent) for resnum in resnums: resname = parm.parm_data['RESIDUE_LABEL'][resnum - 1] if not resname in titratable_residues: continue res = getattr(residues, resname) # Filter out termini (make sure the residue in the prmtop has as many # atoms as the titratable residue defined in residues.py) if resnum == parm.ptr('nres'): natoms = parm.ptr('natom') - parm.parm_data['RESIDUE_POINTER'][ resnum - 1] else: natoms = (parm.parm_data['RESIDUE_POINTER'][resnum] - parm.parm_data['RESIDUE_POINTER'][resnum - 1]) if natoms != len(res.atom_list): continue # If we have gotten this far, add it to the list. main_reslist.add_residue(res, resnum, parm.parm_data['RESIDUE_POINTER'][resnum - 1]) # Set the states if requested if resstates is not None: main_reslist.set_states(resstates) # Open the output file if opt.output is None: output = sys.stdout else: output = open(opt.output, 'w', 0) main_reslist.write_cpin(output, opt.igb, opt.intdiel) if opt.output is not None: output.close() if solvated: if opt.outparm is None: has_carboxylate = False for res in main_reslist: if res is residues.AS4 or res is residues.GL4: has_carboxylate = True break if has_carboxylate: print >> sys.stderr, "Warning: Carboxylate residues in explicit ", print >> sys.stderr, "solvent simulations require a modified" print >> sys.stderr, "topology file! Use the -op flag to print one." else: changeradii(parm, 'mbondi2').execute() change(parm, 'RADII', ':AS4,GL4@OD=,OE=', 1.3).execute() parm.overwrite = True parm.writeParm(opt.outparm) else: if opt.outparm is not None: print >> sys.stderr, "A new prmtop is only necessary for explicit ", print >> sys.stderr, "solvent CpHMD simulations." sys.stderr.write('CPIN generation complete!\n')
def main(opt): # Check all of the arguments if not os.path.exists(opt.prmtop): raise CpinInputError('prmtop file (%s) is missing' % opt.prmtop) # Process the arguments that take multiple args resstates = process_arglist(opt.resstates, int) resnums = process_arglist(opt.resnums, int) notresnums = process_arglist(opt.notresnums, int) resnames = process_arglist(opt.resnames, str) notresnames = process_arglist(opt.notresnames, str) minpka = opt.minpka maxpka = opt.maxpka if not opt.igb in (2, 5, 8): raise CpinInputError('-igb must be 2, 5, or 8!') if resnums is not None and notresnums is not None: raise CpinInputError('Cannot specify -resnums and -notresnums together') if resnames is not None and notresnames is not None: raise CpinInputError('Cannot specify -resnames and -notresnames together') if opt.intdiel != 1 and opt.intdiel != 2: raise CpinInputError('-intdiel must be either 1 or 2 currently') # Set the list of residue names we will be willing to titrate titratable_residues = [] if notresnames is not None: for resname in residues.titratable_residues: if resname in notresnames: continue titratable_residues.append(resname) elif resnames is not None: for resname in resnames: if not resname in residues.titratable_residues: raise CpinInputError('%s is not a titratable residue!' % resname) titratable_residues.append(resname) else: titratable_residues = residues.titratable_residues[:] print str(titratable_residues) solvent_ions = ['WAT', 'Na+', 'Br-', 'Cl-', 'Cs+', 'F-', 'I-', 'K+', 'Li+', 'Mg+', 'Rb+', 'CIO', 'IB', 'MG2'] # Filter titratable residues based on min and max pKa new_reslist = [] for res in titratable_residues: if getattr(residues, res).pKa < minpka: continue if getattr(residues, res).pKa > maxpka: continue new_reslist.append(res) titratable_residues = new_reslist del new_reslist # Make sure we still have a couple residues if len(titratable_residues) == 0: raise CpinInputError('No titratable residues fit your criteria!') # Load the topology file parm = AmberParm(opt.prmtop) # Replace an un-set notresnums with an empty list so we get __contains__() if notresnums is None: notresnums = [] # If we have a list of residue numbers, check that they're all titratable if resnums is not None: for resnum in resnums: if resnum > parm.ptr('nres'): raise CpinInputError('%s only has %d residues. (%d chosen)' % (parm, parm.ptr('nres'), resnum)) if resnum <= 0: raise CpinInputError('Cannot select negative residue numbers.') resname = parm.parm_data['RESIDUE_LABEL'][resnum-1] if not resname in titratable_residues: raise CpinInputError('Residue number %s [%s] is not titratable' % (resnum, resname)) else: # Select every residue except those in notresnums resnums = [] for resnum in range(1, parm.ptr('nres') + 1): if resnum in notresnums: continue resnums.append(resnum) solvated = False first_solvent = 0 if 'WAT' in parm.parm_data['RESIDUE_LABEL']: solvated = True for i, res in enumerate(parm.parm_data['RESIDUE_LABEL']): if res in solvent_ions: first_solvent = parm.parm_data['RESIDUE_POINTER'][i] break main_reslist = TitratableResidueList(system_name=opt.system, solvated=solvated, first_solvent=first_solvent) for resnum in resnums: resname = parm.parm_data['RESIDUE_LABEL'][resnum-1] if not resname in titratable_residues: print resname continue res = getattr(residues, resname) # Filter out termini (make sure the residue in the prmtop has as many # atoms as the titratable residue defined in residues.py) if resnum == parm.ptr('nres'): natoms = parm.ptr('natom')-parm.parm_data['RESIDUE_POINTER'][resnum-1] else: natoms = (parm.parm_data['RESIDUE_POINTER'][resnum] - parm.parm_data['RESIDUE_POINTER'][resnum-1]) if natoms != len(res.atom_list): continue # If we have gotten this far, add it to the list. main_reslist.add_residue(res, resnum, parm.parm_data['RESIDUE_POINTER'][resnum-1]) # Set the states if requested if resstates is not None: main_reslist.set_states(resstates) # Open the output file if opt.output is None: output = sys.stdout else: output = open(opt.output, 'w', 0) main_reslist.write_cpin(output, opt.igb, opt.intdiel) if opt.output is not None: output.close() if solvated: if opt.outparm is None: has_carboxylate = False for res in main_reslist: if res is residues.AS4 or res is residues.GL4: has_carboxylate = True break if has_carboxylate: print >> sys.stderr, "Warning: Carboxylate residues in explicit ", print >> sys.stderr, "solvent simulations require a modified" print >> sys.stderr, "topology file! Use the -op flag to print one." else: changeradii(parm, 'mbondi2').execute() change(parm, 'RADII', ':AS4,GL4@OD=,OE=', 1.3).execute() parm.overwrite = True parm.writeParm(opt.outparm) else: if opt.outparm is not None: print >> sys.stderr, "A new prmtop is only necessary for explicit ", print >> sys.stderr, "solvent CpHMD simulations." sys.stderr.write('CPIN generation complete!\n')
def __init__(self, prmtop, inpcrd): # Only load the inpcrd file if it actually exists. # if os.path.exists(inpcrd): self.prmtop = AmberParm(prmtop, inpcrd) # else: self.prmtop = AmberParm(prmtop) self.prmtop = AmberParm(prmtop) self.inpcrd = inpcrd
class AmberSystem(object): """ An Amber system with a topology file and input coordinate file """ # ============================== def __init__(self, prmtop, inpcrd): # Only load the inpcrd file if it actually exists. # if os.path.exists(inpcrd): self.prmtop = AmberParm(prmtop, inpcrd) # else: self.prmtop = AmberParm(prmtop) self.prmtop = AmberParm(prmtop) self.inpcrd = inpcrd # ============================== def periodic(self): """ Returns whether or not a topology file is set up for PBC """ # PBCs are indicated by a non-zero IFBOX pointer return bool(self.prmtop.ptr('ifbox')) # ============================== def query_radii(self): """ Returns the radii set in the topology file """ return self.prmtop.parm_data['RADIUS_SET'][0] # ============================== def set_radii(self, igb=0, radius_set='mbondi'): """ Sets the radius set to a new one using parmed """ # If someone sets an igb, change to the appropriate radius set if igb: if igb == 1: radius_set = 'mbondi' elif igb == 2: radius_set = 'mbondi2' elif igb == 5: radius_set = 'mbondi2' elif igb == 7: radius_set = 'bondi' elif igb == 8: radius_set = 'mbondi3' if not radius_set in [ 'mbondi', 'mbondi2', 'mbondi3', 'bondi', 'amber6' ]: raise InputError('Bad radius set! Choose from ' + 'mbondi, mbondi2, mbondi3, bondi, and amber6') parmed = which('parmed.py') change_str = ("setOverwrite True\n" + "changeRadii %s\n" % radius_set + "parmout %s\n" % self.prmtop + "go\n") process = Popen( [parmed, '-q', '-n', str(self.prmtop)], stdin=PIPE, stderr=PIPE, stdout=PIPE) (output, error) = process.communicate(change_str) if process.wait(): raise ProgramError('parmed.py failed to change radii!') # Reload our topology file now that we've changed radius sets self.prmtop = AmberParm(str(self.prmtop))
quit """ % (extras, prev_str, resname, next_str, resname.lower(), resname.lower()) if igb == 1: tleap_script = tleap_script % 'mbondi' elif igb == 7: tleap_script = tleap_script % 'bondi' elif igb == 8: tleap_script = tleap_script % 'mbondi3' else: tleap_script = tleap_script % 'mbondi2' open("tleap.in","w").write(tleap_script) os.system(tleap + " -f tleap.in > tleap.log") prm = AmberParm("%s0.prmtop" % resname.lower()) prm.overwrite = True # allow the prmtop to be overwritten # check validity of prmtop if not prm.valid: sys.exit('Error: Invalid prmtop (%s)!' % prm) if isolated or not prev_str: act = changeprotstate(prm, ':1 %s' % opt.state0) else: act = changeprotstate(prm, ':2 %s' % opt.state0) act.execute() prm.writeParm(str(prm)) chg1 = netcharge(prm, '*').execute()
group = OptionGroup(parser, 'Output Files', 'Files that are made by this script') group.add_option('-o', '--outtraj', dest='outtraj', metavar='FILE', default='mutant.mdcrd', help='Name of mutant trajectory ' 'file to generate. Default %default') parser.add_option_group(group) opt, arg = parser.parse_args() if opt.norm_prm is None or opt.mut_prm is None: sys.stderr.write('Please provide a normal and mutated topology file\n') parser.print_help() sys.exit(1) if opt.inptraj is None: sys.stderr.write('Please provide a trajectory to mutate!\n') parser.print_help() sys.exit(1) norm_prm = AmberParm(opt.norm_prm) mut_prm = AmberParm(opt.mut_prm) mut_traj = GlyMutantMdcrd(opt.inptraj, norm_prm, mut_prm) mut_traj.MutateTraj(opt.outtraj) print 'FINALLY DONE!'
def resnum(topfile): parm = AmberParm(topfile) return parm.ptr("NRES")
from chemistry.amber.mask import AmberMask from chemistry.amber.readparm import AmberParm l = AmberParm('asu.prmtop') k = AmberMask(l, ':12,41,119,125,126') sel = k.Selected() sel2 = k.Selection() print sum(sel2) for i in sel: print 'Selected atom %d: %s' % (i + 1, l.atoms[i]) at = l.atoms[0] at.residue at.residue.name at.residue.number at.residue.idx at.atomic_number at.name at.type