def zmat_to_cart(zmat):
numbers = zmat["<STR_LIT>"]<EOL>N = len(numbers)<EOL>coordinates = np.zeros((N, <NUM_LIT:3>), float)<EOL>coordinates[<NUM_LIT:1>, <NUM_LIT:2>] = zmat["<STR_LIT>"][<NUM_LIT:1>]<EOL>if zmat["<STR_LIT>"][<NUM_LIT:2>] == <NUM_LIT:1>:<EOL><INDENT>sign = -<NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>sign = <NUM_LIT:1><EOL><DEDENT>coordinates[<NUM_LIT:2>, <NUM_LIT:2>] = zmat["<STR_LIT>"][<NUM_LIT:2>]*sign*np.cos(zmat["<STR_LIT>"][<NUM_LIT:2>])<EOL>coordinates[<NUM_LIT:2>, <NUM_LIT:1>] = zmat["<STR_LIT>"][<NUM_LIT:2>]*sign*np.sin(zmat["<STR_LIT>"][<NUM_LIT:2>])<EOL>coordinates[<NUM_LIT:2>] += coordinates[<NUM_LIT:2>-zmat["<STR_LIT>"][<NUM_LIT:2>]]<EOL>ref0 = <NUM_LIT:3><EOL>for (number, distance, rel1, angle, rel2, dihed, rel3) in zmat[<NUM_LIT:3>:]:<EOL><INDENT>ref1 = ref0 - rel1<EOL>ref2 = ref0 - rel2<EOL>ref3 = ref0 - rel3<EOL>if ref1 < <NUM_LIT:0>: ref1 = <NUM_LIT:0><EOL>if ref2 < <NUM_LIT:0>: ref2 = <NUM_LIT:0><EOL>if ref3 < <NUM_LIT:0>: ref3 = <NUM_LIT:0><EOL>origin = coordinates[ref1]<EOL>new_z = coordinates[ref2] - origin<EOL>norm_z = np.linalg.norm(new_z)<EOL>if norm_z < <NUM_LIT>:<EOL><INDENT>new_z = np.array([<NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>], float)<EOL><DEDENT>else:<EOL><INDENT>new_z /= np.linalg.norm(new_z)<EOL><DEDENT>new_x = coordinates[ref3] - origin<EOL>new_x -= np.dot(new_x, new_z)*new_z<EOL>norm_x = np.linalg.norm(new_x)<EOL>if norm_x < <NUM_LIT>:<EOL><INDENT>new_x = random_orthonormal(new_z)<EOL><DEDENT>else:<EOL><INDENT>new_x /= np.linalg.norm(new_x)<EOL><DEDENT>new_y = -np.cross(new_z, new_x)<EOL>x = distance*np.cos(dihed)*np.sin(angle)<EOL>y = distance*np.sin(dihed)*np.sin(angle)<EOL>z = distance*np.cos(angle)<EOL>coordinates[ref0] = origin + x*new_x + y*new_y + z*new_z<EOL>ref0 += <NUM_LIT:1><EOL><DEDENT>return numbers, coordinates<EOL>
Converts a ZMatrix back to cartesian coordinates.