def replicate(xyz_info, args): fname = args.f[0] nlines = xyz_info.natoms + 2 nframe = xyzBlock(fname, nlines) na, nb, nc = args.nbox if nframe >= 0: for i in range(nframe+1): if not xyz_info.restart: a = Xyz("output%05d.xyz"%i) b = a.parser() b.pbc = xyz_info.pbc b.step = i toPdb(b, "output%05d.pdb"%i) # replicate the box using external code (genconf in Gromacs) subprocess.Popen(["genconf", "-f", "output%05d.pdb"%i, "-o", "s_%05d.pdb"%i, "-nbox", "%d"%na, "%d"%nb, "%d"%nc], stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.Popen(["cat s_*.pdb > movie_%d_%d_%d.pdb"%(na, nb, nc)], shell=True) # clear up o = open("clear.sh", "w") o.write("rm output*.xyz\n") o.write("rm output*.pdb\n") o.write("rm s_*.pdb\n") o.close() st = os.stat('clear.sh') os.chmod('clear.sh', st.st_mode | stat.S_IEXEC)
def sort_with_connect(fname): """Sort the atoms: gather the same atoms, and atoms in same molecules according to connectivity (.mdf). This is very good for generating gromacs input files, and organize the atoms into a well defined order. """ mdffile = "%s.mdf" % fname carfile = "%s.car" % fname mdf = Mdf(mdffile) car = Car(carfile) a = car.parser() Li = [] Ge = [] P = [] atom_names = mdf.atom_names for i in range(len(mdf.atoms)): if mdf.atoms[i].element == "Li": Li.append(i) elif mdf.atoms[i].element == "Ge": Ge.append(i) for j in mdf.atoms[i].connect: Ge.append(atom_names.index(j)) elif mdf.atoms[i].element == "P": P.append(i) for j in mdf.atoms[i].connect: P.append(__get_index(atom_names, j)) seq_new = Li + Ge + P a.sortNdx(seq_new) toPdb(a)
def withPbc(testfile="supper.pdb", args=''): a = Pdb(testfile) b = a.parser() b.assignAtomTypes() b.assignEleTypes() b.assignIdNumbers() b.toFrac() #b.translate(12.0, "z") toXyz(b, "out.xyz") toMusic(b, "out.music") if len(b.pbc) == 0: b.geotag = "BIOGRF 200" else: b.geotag = "XTLGRF 200" toReaxLammps(b, "lammps.data") toGeo(b, "sim.geo") toMsd(b, "sim.msd") toPoscar(b, ) toCfg(b, ) toJdft(b, ) toTowheecoords(b) if args: if args.element: toPdb(b, "out.pdb", 1) else: toPdb(b, "out.pdb")
def main(args): xyz_info = XyzInfo() if args.f: fname = args.f[0] else: fname = "movie.xyz" sys.stderr.write("Using default xyz file: movie.xyz\n") if args.c: a = Xyz(fname) b = a.parser() b.pbc = [100, 100, 100, 90, 90, 90] toPdb(b) if args.s: config = ConfigParser.ConfigParser() config.read(args.s[0]) read_info(xyz_info, config) if args.nbox: if not args.s: sys.stderr.write("No configure file found!\n") sys.stderr.write("Prepare a sample configure file (test.ini)\n") write_config() sys.exit() else: replicate(xyz_info, args)
def main(args): xyz_info = XyzInfo() if args.f: fname = args.f[0] else: fname = "movie.xyz" sys.stderr.write("Using default xyz file: movie.xyz\n") if args.c: a = Xyz(fname) b = a.parser() if args.pbc: b.pbc = args.pbc else: b.pbc = [20, 20, 23, 90, 90, 90] toPdb(b) if args.s: config = ConfigParser.ConfigParser() config.read(args.s[0]) read_info(xyz_info, config) if args.nbox: if not args.s: sys.stderr.write("No configure file found!\n") sys.stderr.write("Prepare a sample configure file (test.ini)\n") write_config() sys.exit() else: replicate(xyz_info, args)
def add_h(b, centers, cn): dx = DELTA_X zl = b.pbc[2] b1 = copy.deepcopy(b) n_cut = 10 for i in range(len(cn)): n = int(cn[i]) print "processing %d"%(n*1.0/8183*100) if n < n_cut: a = Atom() a.name = "H" a.element = "H" x0 = b.atoms[i].x[0] y0 = b.atoms[i].x[1] z0 = b.atoms[i].x[2] z0 = z0 - int(z0/zl)*zl n_sl = int(z0/dx) x1 = centers[n_sl][0] y1 = centers[n_sl][1] z1 = centers[n_sl][2] r2 = (x0-x1)*(x0-x1) r2 += (y0-y1)*(y0-y1) r2 += (z0-z1)*(z0-z1) r1 = math.sqrt(r2) r = r1 + 1.5 s = r/r1 x = s*(x0-x1) + x1 y = s*(y0-y1) + y1 z = s*(z0-z1) + z1 a.x[0] = x a.x[1] = y a.x[2] = z b1.atoms.append(a) toPdb(b1, "add_h.pdb")
def replicate(xyz_info, args): fname = args.f[0] nlines = xyz_info.natoms + 2 nframe = xyzBlock(fname, nlines) na, nb, nc = args.nbox if nframe >= 0: for i in range(nframe + 1): if not xyz_info.restart: a = Xyz("output%05d.xyz" % i) b = a.parser() b.pbc = xyz_info.pbc b.step = i toPdb(b, "output%05d.pdb" % i) # replicate the box using external code (genconf in Gromacs) subprocess.Popen([ "gmx", "genconf", "-f", "output%05d.pdb" % i, "-o", "s_%05d.pdb" % i, "-nbox", "%d" % na, "%d" % nb, "%d" % nc ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.Popen(["cat s_*.pdb > movie_%d_%d_%d.pdb" % (na, nb, nc)], shell=True) # clear up o = open("clear.sh", "w") o.write("rm output*.xyz\n") o.write("rm output*.pdb\n") o.write("rm s_*.pdb\n") o.close() st = os.stat('clear.sh') os.chmod('clear.sh', st.st_mode | stat.S_IEXEC)
def convertors(b): #toGeo(b, b.name+'.geo') toGeo(b, 'geo') toXyz(b, b.name+'.xyz') toGjf(b, b.name+'.gjf') toPdb(b, b.name+'.pdb') toReaxLammps(b)
def convert(fname): a = Jaguar(fname) b = a.parser() b.assignAtomTypes() b.assignEleTypes() toXyz(b, "out.xyz") toPdb(b, "output.pdb", 1) toReaxLammps(b, "lammps.data")
def surface_atoms_read(b): sur = np.loadtxt("sur_sas.dat") b1 = copy.deepcopy(b) atoms = [] for i in range(len(sur)): if int(sur[i]) == 1: atoms.append(b.atoms[i]) b1.atoms = atoms toPdb(b1, "surface_atoms.pdb") toXyz(b1, "surface_atoms.xyz")
def main(log): d1_file = "lammps.data.3" d2_file = "./slice_03/conf2/lammps.data" d1 = read_data(d1_file) d2 = read_data(d2_file) logfile = "./slice_03/conf2/build.log" z0, ndx = read_build_log(logfile) toPdb(d1, "t0.pdb") update_coords(d1, d2, z0, ndx) toPdb(d1, "t1.pdb") toReaxLammps(d1, "lammps.data.4")
def filter_center(center, dx, nl, b): o = open("ndx_original.dat", "w") atoms = [] for i in range(len(b.atoms)): x = b.atoms[i].x[0] z = b.atoms[i].x[2] an = b.atoms[i].an zn = int(z/dx) if x >= center[zn][0]: atoms.append(b.atoms[i]) o.write("%d\n"%an) o.close() b.atoms = atoms toPdb(b)
def filter_center(center, dx, nl, b): o = open("ndx_original.dat", "w") atoms = [] for i in range(len(b.atoms)): x = b.atoms[i].x[0] z = b.atoms[i].x[2] an = b.atoms[i].an zn = int(z / dx) if x >= center[zn][0]: atoms.append(b.atoms[i]) o.write("%d\n" % an) o.close() b.atoms = atoms toPdb(b)
def fortranOut(testfile="output.pdb", args=''): a = Pdb(testfile) b = a.parser() b.assignAtomTypes() b.assignEleTypes() b.pbc = [50.00, 50.00, 50.00, 90.0, 90.0, 90.0] b.geotag = "XTLGRF 200" toReaxLammps(b, "lammps.data") if args: if args.element: toPdb(b, "out.pdb", 1) else: toPdb(b, "out.pdb") toMsd(b, "sim.msd") toGeo(b, "sim.geo")
def fortranOut(testfile = "output.pdb", args=''): a = Pdb(testfile) b = a.parser() b.assignAtomTypes() b.assignEleTypes() b.pbc = [50.00, 50.00, 50.00, 90.0, 90.0, 90.0] b.geotag = "XTLGRF 200" toReaxLammps(b, "lammps.data") if args: if args.element: toPdb(b, "out.pdb", 1) else: toPdb(b, "out.pdb") toMsd(b, "sim.msd") toGeo(b, "sim.geo")
def surface_atoms_read(b): sur = np.loadtxt("sur_sas.dat") b1 = copy.deepcopy(b) b2 = copy.deepcopy(b) atoms_sur = [] atoms_bulk = [] for i in range(len(sur)): if int(sur[i]) == 1: atoms_sur.append(b.atoms[i]) else: atoms_bulk.append(b.atoms[i]) b1.atoms = atoms_sur b2.atoms = atoms_bulk toPdb(b1, "surface_atoms.pdb") toXyz(b1, "surface_atoms.xyz") toPdb(b2, "bulk_atoms.pdb") toXyz(b2, "bulk_atoms.xyz")
def main(): parser = argparse.ArgumentParser() parser.add_argument("fname", default="POSCAR", nargs="?", help="geo file name") args = parser.parse_args() poscar_file = args.fname a = Poscar(poscar_file) b = a.parser() b.assignAtomTypes() b.assignEleTypes() print b.getVol() #print b.pbc toXyz(b) toGeo(b, "geo") toPdb(b, "sim.pdb") toReaxLammps(b, "lammps.data") toJdft(b, "coords")
def output_pdb(control, b, ndx): """Output the atoms in ndx to pdb file """ c = copy.deepcopy(b) c.atoms = [] sphere = [] void = [] for i in range(len(ndx)): for j in range(len(ndx[i])): sphere.append((ndx[i][j])) for i in range(len(b.atoms)): if i not in sphere: void.append(i) if control.void == "yes": for i in void: c.atoms.append(b.atoms[i]) else: for i in sphere: c.atoms.append(b.atoms[i]) toPdb(c, control.output)
def surface_atoms_cut_off(b): """ """ cn = np.loadtxt("cn.dat") o = open("sur.dat", "w") n_cut = 10 sur = np.where(cn <= 10, 1, 0) b1 = copy.deepcopy(b) atoms = [] for i in range(len(sur)): if sur[i] == 1: atoms.append(b.atoms[i]) o.write("1\n") else: o.write("0\n") o.close() b1.atoms = atoms toPdb(b1, "surface_atoms.pdb") toXyz(b1, "surface_atoms.xyz")
def withPbc(testfile="supper.pdb", args=''): a = Pdb(testfile) b = a.parser() b.assignAtomTypes() b.assignEleTypes() #b.translate(12.0, "z") toXyz(b, "out.xyz") toMusic(b, "out.music") if len(b.pbc) == 0: b.geotag = "BIOGRF 200" else: b.geotag = "XTLGRF 200" toReaxLammps(b, "lammps.data") toGeo(b, "sim.geo") toMsd(b, "sim.msd") if args: if args.element: toPdb(b, "out.pdb", 1) else: toPdb(b, "out.pdb")
def main(): parser = argparse.ArgumentParser() parser.add_argument("fname", default="POSCAR", nargs="?", help="geo file name") args = parser.parse_args() poscar_file = args.fname a = Poscar(poscar_file) b = a.parser() b.assignAtomTypes() b.assignEleTypes() vol = b.getVol() mass = b.getMass() density = mass/vol*ATOMIC_MASS_CONSTANT*1e27 print density #print b.pbc toXyz(b, "contcar.xyz") toGeo(b, "geo") toPdb(b, "sim.pdb") toReaxLammps(b, "lammps.data") toJdft(b, "coords")
def main(counter): # Set up x = np.linspace(1,32,32) delta = 6.0 miu = 17.0 # get the distribution al_natoms, o_natoms = gaussian(x, delta, miu) # read pdb a = read_pdb() # build the atoms list ca_list, o_list = build_list(a) # replace al_list, ignore_list = replace(ca_list, o_list, al_natoms, o_natoms) # do the replace process(a, al_list, ignore_list) # output the data toPdb(a, "case%02d.pdb"%counter)
def main(counter): # Set up x = np.linspace(1, 32, 32) delta = 6.0 miu = 17.0 # get the distribution al_natoms, o_natoms = gaussian(x, delta, miu) # read pdb a = read_pdb() # build the atoms list ca_list, o_list = build_list(a) # replace al_list, ignore_list = replace(ca_list, o_list, al_natoms, o_natoms) # do the replace process(a, al_list, ignore_list) # output the data toPdb(a, "case%02d.pdb" % counter)
def add_o(b, centers, cn): """add o """ dx = DELTA_X zl = b.pbc[2] b1 = copy.deepcopy(b) n_cut = 10 for i in range(len(cn)): print "processing %d"%(i*1.0/8183*100) n = int(cn[i]) token = random.random() if n < n_cut and token > 0.9: a = Atom() a.name = "O" a.element = "O" x0 = b.atoms[i].x[0] y0 = b.atoms[i].x[1] z0 = b.atoms[i].x[2] z0 = z0 - int(z0/zl)*zl n_sl = int(z0/dx) x1 = centers[n_sl][0] y1 = centers[n_sl][1] z1 = centers[n_sl][2] r2 = (x0-x1)*(x0-x1) r2 += (y0-y1)*(y0-y1) r2 += (z0-z1)*(z0-z1) r1 = math.sqrt(r2) r = r1 + 2.0 s = r/r1 x = s*(x0-x1) + x1 + 1.0 y = s*(y0-y1) + y1 + 1.0 z = s*(z0-z1) + z1 a.x[0] = x a.x[1] = y a.x[2] = z b1.atoms.append(a) toPdb(b1, "add_o.pdb")
def fconv(fname): a = FullData(fname) b = a.parser() b.assignAtomTypes() toPdb(b)
def sortXYZ(testfile="input.pdb", axis="z"): a = Pdb(testfile) b = a.parser() atoms = b.atoms b.sortXYZ(axis) toPdb(b, "out_sorted.pdb")
""" read the geo file and output to data (LAMMPS), geo and xyz file. """ import sys, os from mytype import System, Molecule, Atom from g03 import G03LogConf from output_conf import toXyz, toGeo, toPdb usage = """gau2xyz g03logfiles""" if len(sys.argv) < 2: print usage else: for i in sys.argv[1:]: outfile = i.split(".")[0] if os.path.exists(i): a = G03LogConf(i) b = a.parser() b.assignEleTypes() b.geotag = "BIOGRF 200" toXyz(b, outfile + ".xyz") toGeo(b, outfile + ".geo") b.pbc = [50, 50, 50, 90.0, 90.0, 90.0] toPdb(b, outfile + ".pdb") else: print "missing file %s" % i
""" read the geo file and output to data (LAMMPS), geo and xyz file. """ import sys, os from mytype import System, Molecule, Atom from g03 import G03LogConf from output_conf import toXyz, toGeo, toPdb usage = """gau2xyz g03logfiles""" if len(sys.argv) < 2: print usage else: for i in sys.argv[1:]: outfile = i.split(".")[0] if os.path.exists(i): a = G03LogConf(i) b = a.parser() b.assignEleTypes() b.geotag = "BIOGRF 200" toXyz(b, outfile+".xyz") toGeo(b, outfile+".geo") b.pbc = [50, 50, 50, 90.0, 90.0, 90.0] toPdb(b, outfile+".pdb") else: print "missing file %s"%i
def add_oh(b, centers, cn, n_ignore, ndx): dx = DELTA_X zl = b.pbc[2] b1 = copy.deepcopy(b) b2 = copy.deepcopy(b) a = Atom() a.name = "O" a.element = "O" b2.atoms.append(a) a = Atom() a.name = "H" a.element = "H" b2.atoms.append(a) n_cut = 10 r_pt_oh = 2.0 r_oh = 1.0 for i in range(len(cn)): #print "processing %d"%(i*1.0/len(cn)*100) token = random.random() n = int(cn[i]) if n < n_cut and token >= 0.0: a1 = Atom() a1.name = "O" a1.element = "O" x0 = b.atoms[i].x[0] y0 = b.atoms[i].x[1] z0 = b.atoms[i].x[2] z0 = z0 - int(z0/zl)*zl n_sl = int(z0/dx) x1 = centers[n_sl][0] y1 = centers[n_sl][1] z1 = centers[n_sl][2] r2 = (x0-x1)*(x0-x1) r2 += (y0-y1)*(y0-y1) r2 += (z0-z1)*(z0-z1) r1 = math.sqrt(r2) r = r1 + r_pt_oh s = r/r1 x = s*(x0-x1) + x1 y = s*(y0-y1) + y1 z = s*(z0-z1) + z1 a1.x[0] = x a1.x[1] = y a1.x[2] = z b1.atoms.append(a1) b2.atoms[-2].x[0] = x b2.atoms[-2].x[1] = y b2.atoms[-2].x[2] = z a2 = Atom() a2.name = "H" a2.element = "H" r = r1 + r_pt_oh + r_oh s = r/r1 x = s*(x0-x1) + x1 y = s*(y0-y1) + y1 z = s*(z0-z1) + z1 a2.x[0] = x a2.x[1] = y a2.x[2] = z b1.atoms.append(a2) b2.atoms[-1].x[0] = x b2.atoms[-1].x[1] = y b2.atoms[-1].x[2] = z if i >= n_ignore - 1: toPdb(b2, "%05d_%05d.pdb"%(i, ndx[i])) toPdb(b1, "add_oh.pdb")
from block import dumpBlock from dump import Dump from output_conf import toXyz, toPdb lmpfile = "dump.lammpstrj" sepfile = "dump.sep" dt = 1 # parse the dump file with multi configurations into seperated dump files nframe = dumpBlock(lmpfile, sepfile, dt) nframe += 1 for i in range(0, nframe, dt): #for i in range(10): a = Dump("%s%05d.dump"%(sepfile,i)) b = a.parser() #toXyz(b, "xyz%05d.xyz"%i) #b.sortXYZ("z") toPdb(b, "pdb%05d.pdb"%i)
from block import dumpBlock from dump import Dump from output_conf import toXyz, toPdb, toPoscar, toReaxLammps lmpfile = "dump.lammpstrj" sepfile = "dump.sep" dt = 1 # parse the dump file with multi configurations into seperated dump files nframe = dumpBlock(lmpfile, sepfile, dt) nframe += 1 for i in range(0, nframe, dt): #for i in range(10): a = Dump("%s%05d.dump" % (sepfile, i)) b = a.parser() b.assignAtomTypes() b.assignEleTypes() b.toFrac() toXyz(b, "xyz%05d.xyz" % i) #b.sortXYZ("z") toPdb(b, "pdb%05d.pdb" % i) toReaxLammps(b, "lammps.data") toPoscar(b, )
""" read the geo file and output to data (LAMMPS), geo and xyz file. """ from mytype import System, Molecule, Atom from data import ReaxData from output_conf import toPdb testfile = "e_2_data.data" a = ReaxData(testfile) b = a.parser() b.assignAtomTypes() toPdb(b)
def get_slice(b, id0): logfile = "build.log" o = open(logfile, "w") a0 = b.atoms[id0-1] id0 = a0.an x0, y0, z0 = a0.x o.write("Reference atoms is %d.\n"%id0) o.write("The coordination of reference atom is %.4f %.4f %.4f.\n"% (x0, y0, z0)) o.write("Cut from z direction.\n") zl = b.pbc[2] z0 = z0 - int(z0/zl)*zl dz1 = DELTA_Z1 dz2 = DELTA_Z2 z1 = z0 - dz1 z2 = z0 + dz1 z1 = z1 - math.floor(z1/zl)*zl z2 = z2 - math.floor(z2/zl)*zl b1 = copy.deepcopy(b) o.write("Starting from %.4f to %.4f.\n"%(z1, z2)) o.write("Cut radius is %.4f.\n"%dz1) #o.write("Buffer distance is %.4f.\n"%dz2) #o.write("Fixed L1 from %.4f to %.4f\n"%(z1, z2)) #o.write("Fixed L2 from %.4f to %.4f\n"%(z3, z4)) ca = [] a_ref = [] for i in range(len(b.atoms)): id = b.atoms[i].an z = b.atoms[i].x[2] z = z - math.floor(z/zl)*zl #pbc b1.atoms[i].x[2] = z if id == id0: a_ref.append(b1.atoms[i]) else: if z1 < z2: if z >= z1 and z < z2: ca.append(b1.atoms[i]) else: if z >= 0 and z < z2: ca.append(b1.atoms[i]) elif z >= z1 and z < zl: ca.append(b1.atoms[i]) # Shift the atoms according to reference atom for i in range(len(ca)): z = ca[i].x[2] z = z - z1 z = z - math.floor(z/zl)*zl ca[i].x[2] = z z = a_ref[0].x[2] z = z - z1 z = z - math.floor(z/zl)*zl a_ref[0].x[2] = z o.write("Sort the atom index according to z.\n") ca.sort(key=lambda x: x.x[2]) c1 = [] c2 = [] for i in ca: z = i.x[2] if z <= dz2: c1.append(i) elif z > 2*dz1 - dz2: c1.append(i) else: c2.append(i) o.write("Fixed atoms is %d.\n"%(len(c1))) ca = ca + a_ref o.write("Total number of atoms is %d.\n"%len(ca)) o.write("Index is as following:\n") counter = 0 for i in ca: if counter % 10 == 0: o.write("\n") o.write("%8d"%i.an) counter += 1 o.write("\n") b1.atoms = c1 + c2 + a_ref b1.pbc[2] = 2*dz1 o.write("Output to pdb.\n") toPdb(b1, "input.pdb") toReaxLammps(b1) o.close() return ca, c1, c2, a_ref
from mytype import System, Molecule, Atom from poscar import Poscar from output_conf import toXyz, toGeo, toPdb, toReaxLammps import sys if len(sys.argv) > 1: fname = sys.argv[1] else: fname = "CONTCAR" a = Poscar(fname) b = a.parser() b.assignAtomTypes() b.assignEleTypes() print b.getVol() toXyz(b) toGeo(b, "geo") toPdb(b, "sim.pdb") toReaxLammps(b, "lammps.data")
def add_oh(b, centers, cn, n_ignore, ndx): """add oh """ dx = DELTA_X zl = b.pbc[2] b1 = copy.deepcopy(b) b2 = copy.deepcopy(b) a = Atom() a.name = "O" a.element = "O" b2.atoms.append(a) a = Atom() a.name = "H" a.element = "H" b2.atoms.append(a) n_cut = 10 r_pt_oh = 2.0 r_oh = 1.0 for i in range(len(cn)): #print "processing %d"%(i*1.0/len(cn)*100) token = random.random() n = int(cn[i]) if n < n_cut and token >= 0.0: a1 = Atom() a1.name = "O" a1.element = "O" x0 = b.atoms[i].x[0] y0 = b.atoms[i].x[1] z0 = b.atoms[i].x[2] z0 = z0 - int(z0/zl)*zl n_sl = int(z0/dx) x1 = centers[n_sl][0] y1 = centers[n_sl][1] z1 = centers[n_sl][2] r2 = (x0-x1)*(x0-x1) r2 += (y0-y1)*(y0-y1) r2 += (z0-z1)*(z0-z1) r1 = math.sqrt(r2) r = r1 + r_pt_oh s = r/r1 x = s*(x0-x1) + x1 y = s*(y0-y1) + y1 z = s*(z0-z1) + z1 a1.x[0] = x a1.x[1] = y a1.x[2] = z b1.atoms.append(a1) b2.atoms[-2].x[0] = x b2.atoms[-2].x[1] = y b2.atoms[-2].x[2] = z a2 = Atom() a2.name = "H" a2.element = "H" r = r1 + r_pt_oh + r_oh s = r/r1 x = s*(x0-x1) + x1 y = s*(y0-y1) + y1 z = s*(z0-z1) + z1 a2.x[0] = x a2.x[1] = y a2.x[2] = z b1.atoms.append(a2) b2.atoms[-1].x[0] = x b2.atoms[-1].x[1] = y b2.atoms[-1].x[2] = z if i >= n_ignore - 1: toPdb(b2, "%05d_%05d.pdb"%(i, ndx[i])) toPdb(b1, "add_oh.pdb")