def get_unique_atomtypes(fit_dir): """ given a list of xyz-files, determine the atomic numbers that are present in any file. For each atom combination a repulsive potential is fitted. """ xyz_filenames = glob.glob("%s/FIT_PATHS/*.xyz" % fit_dir) unique_atomtypes = [] for f in xyz_filenames: for atomlist in XYZ.read_xyz_it(f): # atomic numbers in first frame for Zi, posi in atomlist: if not Zi in unique_atomtypes: unique_atomtypes.append(Zi) unique_atomtypes = np.sort(unique_atomtypes) print("") print("Atom Types:") print("-----------") for Zi in unique_atomtypes: print(" %s" % AtomicData.atom_names[Zi - 1]) print("") return unique_atomtypes
def pyrene_dimer_analysis(xyz_traj_file, out_file, qmmm_partitioning=None): """ This function analyses the relative displacement between two pyrene units in a dimer. 'xyz_traj_file' is a xyz-file that contains the geometries for each time step. The horizontal (Rx,Ry) and vertical (Rz) displacements are written to a table in 'out_file'. If the file contains additional molecules (e.g. MM molecules), the atom indeces belonging to the dimer should be specified as a list in qmmm_partioning. """ fh = open(out_file, "w") print("# TSTEP R_X / Angstrom R_Y / Angstrom R_Z / Angstrom", file=fh) # process one geometry after the other for i, atomlist in enumerate(XYZ.read_xyz_it(xyz_traj_file)): if qmmm_partitioning != None: # select the atoms belonging to the dimer pair atomlist = [atomlist[j] for j in qmmm_partitioning] nat = len(atomlist) assert nat == 52, "Pyrene dimer should contain 52 atoms!" # monomer1 = atomlist[:nat / 2] monomer2 = atomlist[nat / 2:] # compute the enclosing box for each pyrene unit box1 = MoleculeBox(monomer1) box2 = MoleculeBox(monomer2) # distance between the centers of the enclosing boxes vec = box2.center - box1.center # decompose distance between centers into a part that is perpendicular to the # plane of the 1st monomer and another one that is horizontal to it by projecting # onto the z-axis of the box belonging to the 1st monomer vec_vertical = np.dot(box1.axes[2], vec) * box1.axes[2] ## The x-axis is parallel to the vector passing through atoms C12 and C10 #xaxis = np.array(atomlist[9][1]) - np.array(atomlist[11][1]) # In the geometries with periodic boundary conditions the x-axis passes # through atoms C3 and C23 xaxis = np.array(atomlist[2][1]) - np.array(atomlist[22][1]) # remove z-component from x-axis xaxis -= np.dot(box1.axes[2], xaxis) * box1.axes[2] xaxis /= la.norm(xaxis) ## The y-axis is parallel to the vector passing through atoms C11 and C13 #yaxis = np.array(atomlist[10][1]) - np.array(atomlist[12][1]) # In the geometries with periodic boundary conditions the y-axis passes # through atoms C14 and C4 yaxis = np.array(atomlist[13][1]) - np.array(atomlist[3][1]) yaxis -= np.dot(box1.axes[2], yaxis) * box1.axes[2] yaxis /= la.norm(yaxis) vec_horizontal = vec - vec_vertical Rx = np.dot(xaxis, vec_horizontal) * AtomicData.bohr_to_angs Ry = np.dot(yaxis, vec_horizontal) * AtomicData.bohr_to_angs Rz = la.norm(vec_vertical) * AtomicData.bohr_to_angs print("%d %8.6f %8.6f %8.6f" % (i, Rx, Ry, Rz), file=fh) fh.close()
for arg in args: try: atom_ids = [int(i)-1 for i in arg.split()] coord_specs.append(atom_ids) except ValueError: # probably this argument is an xyz-file assert ".xyz" in arg, "%s does not have .xyz suffix nor is it a list of integer" % arg xyz_files.append(arg) if len(xyz_files) < 1: print("At least one xyz-file should be specified!") exit(-1) coords_trajs = [] for f in xyz_files: coords_timeseries = [] for geom in XYZ.read_xyz_it(f): coords = [] for atom_ids in coord_specs: coords.append( get_coord(geom, atom_ids) ) coords_timeseries.append(coords) coords_trajs.append( np.array(coords_timeseries) ) ntrajs = len(xyz_files) nsteps = min(list(map(len, coords_trajs))) # find length of shorted trajectories ncoords = len(coord_specs) # coords_data = np.zeros((ntrajs,nsteps,ncoords), dtype=float) for i in range(0, ntrajs): coords_data[i,:,:] = coords_trajs[i][:nsteps,:] # average over trajectories coords_avg = np.sum(coords_data, axis=0) / float(ntrajs)
show a plot of the calculated bond indeces """ from matplotlib.pyplot import plot, xlabel, ylabel, legend, show, savefig from numpy import loadtxt b = loadtxt(out_file) (ntraj, ndist) = b.shape xlabel("MD steps") ylabel("bond index $b_i = \\sum_j r_{ij}$") for n in range(0, ndist): at = AtomicData.atom_names[atomlist[n][0] - 1] plot(b[:, n], label="%s%d" % (at, n)) legend() savefig(out_file + ".png") show() if __name__ == "__main__": if len(sys.argv) < 3: print "Usage: %s <xyz-file with list of nuclear geometries> <output file with bond indeces>" % sys.argv[ 0] exit(-1) xyz_file = sys.argv[1] out_file = sys.argv[2] fh = open(out_file, 'w') for atomlist in XYZ.read_xyz_it(xyz_file): for bi in bond_indeces(atomlist): print >> fh, "%.7f " % bi, print >> fh, "" fh.close() plot_bond_indeces(atomlist, out_file)
# all isomers should have different connectivities n = len(isomers) for i in range(0, n): for j in range(i + 1, n): if np.sum( (isomer_connectivities[i] - isomer_connectivities[j])**2) == 0: print "WARNING: Isomer %d and %d in file '%s' have the same adjacency matrices!" % ( i + 1, j + 1, isomer_file) fh = open(opts.out_file, "w") print >> fh, "# isomer indeces refer to the geometries in '%s'" % isomer_file print >> fh, "# GEOMETRY ISOMER(S)" print "classify geometries by comparison with isomers" for i_step, atomlist in enumerate(XYZ.read_xyz_it(dynamics_file)): if i_step % opts.step != 0: continue # Each fragment has to be analyzed separately separately fragments = MolecularGraph.disconnected_fragments(atomlist, hydrogen_bonds=True) # The geometry is assigned the index of the isomer which it resembles. # If the molecule consists of several fragments each fragment is assigned # separately. if len(fragments) == 1: # disconnected_fragments sometimes messes up, ;(. If there is only one fragment, # it is better to use the original ordering of the atoms.