Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,66 @@ A python utility to convert between Cartesian and Z-matrix geometries.

RECENTLY ADDED: when converting from zmat to xyz, variables can now be read with no caveats.

Running the below will print the output to the standard output stream (i.e. the terminal in most cases); this can be piped into a file in the usual way, e.g.
Running the below will print the output to the standard output stream (i.e. the terminal in most cases); this can be piped into a file in the usual
way, e.g.

```bash
python3 gc.py -xyz test.xyz > test.zmat
```

## Usage

To convert from XYZ to Z-matrix:

```bash
python3 gc.py -xyz test.xyz
```

for files in XYZ format, i.e.

Number of atoms
```
<Number of atoms>

TITLE CARD

Atom x y z
<Atom> <x> <y> <z>

Atom x y z
<Atom> <x> <y> <z>

...
```

The default is to print the values of distances/angles/dihedrals. These can instead be printed as variables with the options

```
--rvar=True
--avar=True
--dvar=True
```

respectively. Alternative

```
--allvar=True
```

will set all the above to true.

To convert from Z-matrix to XYZ:

```bash
python gc.py -zmat test.zmat
```

for files containing a Z-matrix. This no longer assumes that the Z-matrix has values not variables for distances/angles/dihedrals, and can read variables with no additional options.
for files containing a Z-matrix. This no longer assumes that the Z-matrix has values not variables for distances/angles/dihedrals, and can read
variables with no additional options.


The precision of the output can be changed by means of the
```
--precision=12
--angle_precision=4
```
options. These affect the precision of the printed out coordinates and distances and the angles respectively. The first option has effects for both
XYZ and Z-matrix format, whereas the latter only applies to Z-matrices.

8 changes: 6 additions & 2 deletions gc.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
parser.add_argument("--avar", dest="avar", required=False, type=bool, default=False, help="Print angles as variables")
parser.add_argument("--dvar", dest="dvar", required=False, type=bool, default=False, help="Print dihedrals as variables")
parser.add_argument("--allvar", dest="allvar", required=False, type=bool, default=False, help="Print all values as variables")
parser.add_argument("--precision", dest="precision", required=False, type=int, default=8, help="Sets the precision of coordinates and distances")
parser.add_argument("--angle_precision", dest="angle_precision", required=False, type=int, default=5, help="Sets the precision of angles")
args = parser.parse_args()

xyzfilename = args.xyzfile
Expand All @@ -44,14 +46,16 @@
rvar = args.rvar or args.allvar
avar = args.avar or args.allvar
dvar = args.dvar or args.allvar
precision = args.precision
angle_precision = args.angle_precision

if (xyzfilename == None and zmatfilename == None):
print("Please specify an input geometry")

elif (zmatfilename == None):
xyzarr, atomnames = gc.readxyz(xyzfilename)
distmat = gc.distance_matrix(xyzarr)
gc.write_zmat(xyzarr, distmat, atomnames, rvar=rvar, avar=avar, dvar=dvar)
gc.write_zmat(xyzarr, distmat, atomnames, rvar=rvar, avar=avar, dvar=dvar, distprecision=precision, angleprecision=angle_precision)
else:
atomnames, rconnect, rlist, aconnect, alist, dconnect, dlist = gc.readzmat(zmatfilename)
gc.write_xyz(atomnames, rconnect, rlist, aconnect, alist, dconnect, dlist)
gc.write_xyz(atomnames, rconnect, rlist, aconnect, alist, dconnect, dlist, precision=precision)
29 changes: 17 additions & 12 deletions gcutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,13 @@ def dihedral(xyzarr, i, j, k, l):
chi = chi + 360.0
return chi

def write_zmat(xyzarr, distmat, atomnames, rvar=False, avar=False, dvar=False):
def write_zmat(xyzarr, distmat, atomnames, rvar=False, avar=False, dvar=False, distprecision=8, angleprecision=5):
"""Prints a z-matrix from xyz coordinates, distances, and atomnames,
optionally with the coordinate values replaced with variables.
"""
distformat = '{:>' + str(distprecision + 6) + '.' + str(distprecision) + 'f}'
angleformat = '{:>' + str(angleprecision + 6) + '.' + str(angleprecision) + 'f}'

npart, ncoord = xyzarr.shape
rlist = [] # list of bond lengths
alist = [] # list of bond angles (degrees)
Expand All @@ -177,7 +180,7 @@ def write_zmat(xyzarr, distmat, atomnames, rvar=False, avar=False, dvar=False):
if (rvar):
r = 'R1'
else:
r = '{:>11.5f}'.format(rlist[0])
r = distformat.format(rlist[0])
print('{:<3s} {:>4d} {:11s}'.format(n, 1, r))

if npart > 2:
Expand All @@ -187,13 +190,13 @@ def write_zmat(xyzarr, distmat, atomnames, rvar=False, avar=False, dvar=False):
if (rvar):
r = 'R2'
else:
r = '{:>11.5f}'.format(rlist[1])
r = distformat.format(rlist[1])

alist.append(angle(xyzarr, 2, 0, 1))
if (avar):
t = 'A1'
else:
t = '{:>11.5f}'.format(alist[0])
t = angleformat.format(alist[0])

print('{:<3s} {:>4d} {:11s} {:>4d} {:11s}'.format(n, 1, r, 2, t))

Expand All @@ -205,35 +208,37 @@ def write_zmat(xyzarr, distmat, atomnames, rvar=False, avar=False, dvar=False):
if (rvar):
r = 'R{:<4d}'.format(i)
else:
r = '{:>11.5f}'.format(rlist[i-1])
r = distformat.format(rlist[i-1])

alist.append(angle(xyzarr, i, i-3, i-2))
if (avar):
t = 'A{:<4d}'.format(i-1)
else:
t = '{:>11.5f}'.format(alist[i-2])
t = angleformat.format(alist[i-2])

dlist.append(dihedral(xyzarr, i, i-3, i-2, i-1))
if (dvar):
d = 'D{:<4d}'.format(i-2)
else:
d = '{:>11.5f}'.format(dlist[i-3])
d = angleformat.format(dlist[i-3])
print('{:3s} {:>4d} {:11s} {:>4d} {:11s} {:>4d} {:11s}'.format(n, i-2, r, i-1, t, i, d))
if (rvar):
print(" ")
for i in range(npart-1):
print('R{:<4d} = {:>11.5f}'.format(i+1, rlist[i]))
print('R{:<4d} = '.format(i+1) + distformat.format(rlist[i]))
if (avar):
print(" ")
for i in range(npart-2):
print('A{:<4d} = {:>11.5f}'.format(i+1, alist[i]))
print('A{:<4d} = '.format(i+1) + angleformat.format(alist[i]))
if (dvar):
print(" ")
for i in range(npart-3):
print('D{:<4d} = {:>11.5f}'.format(i+1, dlist[i]))
print('D{:<4d} = '.format(i+1) + angleformat.format(dlist[i]))

def write_xyz(atomnames, rconnect, rlist, aconnect, alist, dconnect, dlist):
def write_xyz(atomnames, rconnect, rlist, aconnect, alist, dconnect, dlist, precision=8):
"""Prints out an xyz file from a decomposed z-matrix"""
coordformat = '{:>' + str(precision + 6) + '.' + str(precision) + 'f}'

npart = len(atomnames)
print(npart)
print('INSERT TITLE CARD HERE')
Expand Down Expand Up @@ -300,4 +305,4 @@ def write_xyz(atomnames, rconnect, rlist, aconnect, alist, dconnect, dlist):

# print results
for i in range(npart):
print('{:<4s}\t{:>11.5f}\t{:>11.5f}\t{:>11.5f}'.format(atomnames[i], xyzarr[i][0], xyzarr[i][1], xyzarr[i][2]))
print(('{:<4s}\t' + coordformat + '\t' + coordformat + '\t' + coordformat).format(atomnames[i], xyzarr[i][0], xyzarr[i][1], xyzarr[i][2]))