Esempio n. 1
0
File: gcn.py Progetto: rvkmr1989/ARC
def gcn(ts_path, ):
    """
    Generates a TS guess using the updated graph convolutional network originally published by Pattanaik et al.
    https://chemrxiv.org/articles/Genereting_Transition_States_of_Isomerization_Reactions_with_Deep_Learning/12302084
    This function writes the TS guess as an xyz file to the corresponding TS directory.

    Args:
        ts_path (str): Path to the inputs for the network.

    Returns:
         ts_xyz_dict (dict): ARC xyz dictionary of TS guess
    """

    # run the GCN as a subprocess
    p = subprocess.run(
        f'{TS_GCN_PYTHON} {os.path.join(TS_GCN_PATH, "inference.py")} '
        f'--r_sdf_path {os.path.join(ts_path, "reactant.sdf")} '
        f'--p_sdf_path {os.path.join(ts_path, "product.sdf")} '
        f'--ts_xyz_path {os.path.join(ts_path, "TS.xyz")} ',
        shell=True)
    # if subprocess ran successfully, read the TS structure into ARC's dictionary format
    if p.returncode == 0:
        ts_xyz_dict = str_to_xyz(os.path.join(ts_path, "TS.xyz"))
    # otherwise, log the error
    else:
        logger.error(f'GCN subprocess did not give a successful return code:\n'
                     f'Got return code: {p.returncode}\n'
                     f'stdout: {p.stdout}\n'
                     f'stderr: {p.stderr}')
        ts_xyz_dict = None

    return ts_xyz_dict
Esempio n. 2
0
    def get_mapped_product_xyz(self):
        """
        Uses the mapping from product onto reactant to create a new ARC Species for the mapped product.
        For now, only functional for A <=> B reactions.

        Returns:
            Tuple[dict, ARCSpecies]:
                dict: Mapped product atoms in ARC dictionary format.
                ARCSpecies: ARCSpecies object created from mapped coordinates.
        """
        product = self.p_species[0]
        mapping = self.atom_map
        original_xyz_str = xyz_to_str(product.get_xyz())
        original_xyz = np.array(original_xyz_str.split('\n'))
        mapped_xyz = '\n'.join(original_xyz[mapping].tolist())
        # create another product with the mapped atoms since ARCSpecies objects preserve this ordering
        # in RDKit objects and in RMG-Py Molecule objects
        mapped_product = ARCSpecies(
            label=product.label,
            smiles=product.mol.smiles,
            multiplicity=product.multiplicity,
            charge=product.charge,
            xyz=mapped_xyz,
        )
        mapped_xyz = str_to_xyz(mapped_xyz)
        return mapped_xyz, mapped_product
Esempio n. 3
0
    def test_get_lp_vector(self):
        """Test the lone pair vector"""
        xyz1 = converter.str_to_xyz(
            """O       1.13971727   -0.35763357   -0.91809799
N      -0.16022228   -0.63832421   -0.32863338
C      -0.42909096    0.49864538    0.54457751
H      -1.36471297    0.33135829    1.08632108
H       0.37059419    0.63632068    1.27966893
H      -0.53867601    1.41749835   -0.03987146
H       0.03832076   -1.45968957    0.24914206
H       0.94407000   -0.42817536   -1.87310674""")
        spc1 = ARCSpecies(label='tst1', smiles='CN(O)', xyz=xyz1)
        vector = vectors.get_lp_vector(label='tst1',
                                       mol=spc1.mol,
                                       xyz=xyz1,
                                       pivot=1)
        self.assertAlmostEqual(vector[0], -0.7582151013592212, 5)
        self.assertAlmostEqual(vector[1], -0.14276808320949216, 5)
        self.assertAlmostEqual(vector[2], -0.6361816835523585, 5)
        self.assertAlmostEqual((sum([vi**2 for vi in vector]))**0.5, 1)
        # puts the following dummy atom in xyz1: 'Cl     -0.91844 -0.78109 -0.96482'

        xyz2 = converter.str_to_xyz(
            """N      -0.70735114    0.81971647    0.24999886
C       0.58016992    0.65919122   -0.42405305
C       1.44721132   -0.43727777    0.17945348
C      -1.63900905   -0.25796649   -0.04936095
H       1.11974047    1.60931343   -0.33768790
H       0.43764604    0.48458543   -1.49689220
H       1.00255021   -1.42757899    0.04242741
H       2.42947502   -0.44523307   -0.30432399
H       1.60341053   -0.27376799    1.25093890
H      -1.81252045   -0.34624671   -1.12667881
H      -2.60396918   -0.04100469    0.41960198
H      -1.29274859   -1.22036999    0.33877281
H      -0.56460509    0.87663914    1.25780346""")
        spc2 = ARCSpecies(label='tst2', smiles='CNCC', xyz=xyz2)
        vector = vectors.get_lp_vector(label='tst2',
                                       mol=spc2.mol,
                                       xyz=xyz2,
                                       pivot=0)
        self.assertAlmostEqual(vector[0], -0.40585301456248446, 5)
        self.assertAlmostEqual(vector[1], 0.8470158636326891, 5)
        self.assertAlmostEqual(vector[2], -0.34328917449449764, 5)
        self.assertAlmostEqual((sum([vi**2 for vi in vector]))**0.5, 1)
Esempio n. 4
0
    def test_save_geo(self):
        """Test saving the geometry files for a species"""
        spc = ARCSpecies(label='methylamine',
                         smiles='CN',
                         multiplicity=1,
                         charge=0)
        spc.final_xyz = str_to_xyz(
            """N      -0.74566988   -0.11773792    0.00000000
C       0.70395487    0.03951260    0.00000000
H       1.12173564   -0.45689176   -0.87930074
H       1.06080468    1.07995075    0.00000000
H       1.12173564   -0.45689176    0.87930074
H      -1.16115119    0.31478894    0.81506145
H      -1.16115119    0.31478894   -0.81506145""")
        spc.opt_level = 'opt/level'
        project = 'arc_project_for_testing_delete_after_usage'
        project_directory = os.path.join(arc_path, 'Projects', project)
        xyz_path = os.path.join(project_directory, 'output', 'Species',
                                spc.label, 'geometry', 'methylamine.xyz')
        gjf_path = os.path.join(project_directory, 'output', 'Species',
                                spc.label, 'geometry', 'methylamine.gjf')
        plotter.save_geo(species=spc, project_directory=project_directory)
        xyz_data = """7
methylamine optimized at opt/level
N      -0.74566988   -0.11773792    0.00000000
C       0.70395487    0.03951260    0.00000000
H       1.12173564   -0.45689176   -0.87930074
H       1.06080468    1.07995075    0.00000000
H       1.12173564   -0.45689176    0.87930074
H      -1.16115119    0.31478894    0.81506145
H      -1.16115119    0.31478894   -0.81506145
"""
        gjf_data = """# hf/3-21g

methylamine optimized at opt/level

0 1
N      -0.74566988   -0.11773792    0.00000000
C       0.70395487    0.03951260    0.00000000
H       1.12173564   -0.45689176   -0.87930074
H       1.06080468    1.07995075    0.00000000
H       1.12173564   -0.45689176    0.87930074
H      -1.16115119    0.31478894    0.81506145
H      -1.16115119    0.31478894   -0.81506145
"""
        with open(xyz_path, 'r') as f:
            data = f.read()
        self.assertEqual(data, xyz_data)
        with open(gjf_path, 'r') as f:
            data = f.read()
        self.assertEqual(data, gjf_data)
Esempio n. 5
0
    def test_get_vector(self):
        """Test getting a vector between two atoms in the molecule"""
        xyz1 = converter.str_to_xyz("""O      0.0   0.0    0.0
N      1.0    0.0   0.0""")  # trivial
        vector = vectors.get_vector(pivot=0, anchor=1, xyz=xyz1)
        self.assertAlmostEqual(vector[0], 1.0, 5)
        self.assertAlmostEqual(vector[1], 0.0, 5)
        self.assertAlmostEqual(vector[2], 0.0, 5)

        xyz2 = converter.str_to_xyz("""O      -0.39141517   -1.49218505    0.23537907
N      -1.29594218    0.36660772   -0.33360920
C      -0.24369399   -0.21522785    0.47237314
C       1.11876670    0.24246665   -0.06138419
H      -0.34055624    0.19728442    1.48423848
H       1.27917500   -0.02124533   -1.11576163
H       1.93896021   -0.20110894    0.51754953
H       1.21599040    1.33219465    0.01900272
H      -2.12405283   -0.11420423    0.01492411
H      -1.15723190   -0.09458204   -1.23271202""")  # smiles='NC([O])(C)'
        vector = vectors.get_vector(pivot=1, anchor=2, xyz=xyz2)
        self.assertAlmostEqual(vector[0], 1.052248, 5)
        self.assertAlmostEqual(vector[1], -0.581836, 5)
        self.assertAlmostEqual(vector[2], 0.805982, 5)
Esempio n. 6
0
    def test_calculate_angle(self):
        """Test calculating an angle from xyz coordinates"""
        co2 = converter.str_to_xyz("""O      -1.40465894   -0.03095532    0.00000000
C      -0.00000000    0.00000004    0.00000000
O       1.40465895    0.03095528    0.00000000""")
        angle = vectors.calculate_angle(coords=co2['coords'], atoms=[0, 1, 2], index=0, units='degs')
        self.assertEqual(angle, 180.0)
        angle = vectors.calculate_angle(coords=co2['coords'], atoms=[1, 2, 3], index=1, units='degs')
        self.assertEqual(angle, 180.0)
        angle = vectors.calculate_angle(coords=co2['coords'], atoms=[0, 1, 2], index=0, units='rads')
        self.assertEqual(angle, math.pi)
        with self.assertRaises(VectorsError):
            angle = vectors.calculate_angle(coords=co2['coords'], atoms=[1, 2, 1], index=1, units='degs')

        fake_co2 = converter.str_to_xyz("""O      -1.40465894   -0.03095532    0.00000000
C      -0.00000000    0.00000004    0.00000000
O      -1.40465894   -0.03095532    0.00000000""")
        angle = vectors.calculate_angle(coords=fake_co2['coords'], atoms=[0, 1, 2], index=0, units='degs')
        self.assertEqual(angle, 0.0)

        propene = converter.str_to_xyz("""C       1.22905000   -0.16449200    0.00000000
    C      -0.13529200    0.45314000    0.00000000
    C      -1.27957200   -0.21983000    0.00000000
    H       1.17363000   -1.25551200    0.00000000
    H       1.79909600    0.15138400    0.87934300
    H       1.79909600    0.15138400   -0.87934300
    H      -0.16831500    1.54137600    0.00000000
    H      -2.23664600    0.28960500    0.00000000
    H      -1.29848800   -1.30626200    0.00000000""")
        angle = vectors.calculate_angle(coords=propene['coords'], atoms=[8, 3, 9], index=1, units='degs')
        self.assertAlmostEqual(angle, 117.02817, 4)
        angle = vectors.calculate_angle(coords=propene['coords'], atoms=[9, 3, 8], index=1, units='degs')
        self.assertAlmostEqual(angle, 117.02817, 4)
        angle = vectors.calculate_angle(coords=propene['coords'], atoms=[1, 2, 3], index=1, units='degs')
        self.assertAlmostEqual(angle, 125.18344, 4)
        angle = vectors.calculate_angle(coords=propene['coords'], atoms=[5, 1, 2], index=1, units='degs')
        self.assertAlmostEqual(angle, 110.82078, 4)
Esempio n. 7
0
 def test_calculate_distance(self):
     """Test calculating a distance between two atoms"""
     propene = converter.str_to_xyz("""C       1.22905000   -0.16449200    0.00000000
 C      -0.13529200    0.45314000    0.00000000
 C      -1.27957200   -0.21983000    0.00000000
 H       1.17363000   -1.25551200    0.00000000
 H       1.79909600    0.15138400    0.87934300
 H       1.79909600    0.15138400   -0.87934300
 H      -0.16831500    1.54137600    0.00000000
 H      -2.23664600    0.28960500    0.00000000
 H      -1.29848800   -1.30626200    0.00000000""")
     distance = vectors.calculate_distance(coords=propene['coords'], atoms=[1, 4], index=1)
     self.assertAlmostEqual(distance, 1.092426698)
     distance = vectors.calculate_distance(coords=propene['coords'], atoms=[1, 2], index=1)
     self.assertAlmostEqual(distance, 1.49763087)
     distance = vectors.calculate_distance(coords=propene['coords'], atoms=[2, 3], index=1)
     self.assertAlmostEqual(distance, 1.32750337)
Esempio n. 8
0
def process_conformers_file(
        conformers_path: str) -> Tuple[List[Dict[str, tuple]], List[float]]:
    """
    Parse coordinates and energies from an ARC conformers file of either species or TSs.

    Args:
        conformers_path (str): The path to an ARC conformers file
                               (either a "conformers_before_optimization" or
                               a "conformers_after_optimization" file).

    Raises:
        InputError: If the file could not be found.

    Returns: Tuple[List[Dict[str, tuple]], List[float]]
        Conformer coordinates in a dict format, the respective energies in kJ/mol.
    """
    if not os.path.isfile(conformers_path):
        raise InputError(
            'Conformers file {0} could not be found'.format(conformers_path))
    with open(conformers_path, 'r') as f:
        lines = f.readlines()
    xyzs, energies = list(), list()
    line_index = 0
    while line_index < len(lines):
        if 'conformer' in lines[line_index] and ':' in lines[
                line_index] and lines[line_index].strip()[-2].isdigit():
            xyz, energy = '', None
            line_index += 1
            while len(lines) and line_index < len(lines) and lines[line_index].strip() \
                    and 'SMILES' not in lines[line_index] \
                    and 'energy' not in lines[line_index].lower() \
                    and 'guess method' not in lines[line_index].lower():
                xyz += lines[line_index]
                line_index += 1
            while len(lines) and line_index < len(
                    lines) and 'conformer' not in lines[line_index]:
                if 'relative energy:' in lines[line_index].lower():
                    energy = float(lines[line_index].split()[2])
                line_index += 1
            xyzs.append(str_to_xyz(xyz))
            energies.append(energy)
        else:
            line_index += 1
    return xyzs, energies
Esempio n. 9
0
def autotst(reaction_label=None, rmg_reaction=None, reaction_family=None):
    """
    Run AutoTST to generate a TS guess. Currently only works for H Abstraction reactions.
    Either `reaction_label` or `rmg_reaction` has to be given (ARC sends rmg_reaction).
    If reaction_family isn't specified, it is assumed to be H_Abstraction.

    Args:
        reaction_label (str): AutoTST's string format reaction, e.g., CCCC+[O]O_[CH2]CCC+OO
        rmg_reaction (Reaction): An RMG Reaction object.
        reaction_family (str): The RMG family corresponding to the RMG Reaction object

    Returns:
        xyz (dict): The TS guess.

    Raises:
        TSError: if neither ``rmg_reaction`` nor ``reaction_family`` were specified.
    """
    xyz_str = ''
    xyz_path = os.path.join(ARC_PATH, 'arc', 'ts', 'auto_tst.xyz')
    run_autotst_path = os.path.join(ARC_PATH, 'arc', 'ts', 'run_autotst.py')

    reaction_family = str('H_Abstraction') if reaction_family is None else str(
        reaction_family)

    if os.path.isfile(xyz_path):
        os.remove(xyz_path)
    if rmg_reaction is not None and reaction_label is None:
        reaction_label = get_reaction_label(rmg_reaction)
    elif reaction_label is None:
        raise TSError('Must get either reaction_label or rmg_reaction')
    os.system(
        'python {run_autotst_path} {reaction_label} {reaction_family}'.format(
            run_autotst_path=run_autotst_path,
            reaction_label=reaction_label,
            reaction_family=reaction_family))

    if os.path.isfile(xyz_path):
        with open(xyz_path, 'r') as f:
            lines = f.readlines()
            xyz_str = ''.join([str(line) for line in lines])
        os.remove(xyz_path)
    if not xyz_str or xyz_str == '\n':
        return None
    return str_to_xyz(xyz_str)
Esempio n. 10
0
def parse_1d_scan_coords(path: str) -> List[Dict[str, tuple]]:
    """
    Parse the 1D torsion scan coordinates from an ESS log file.

    Args:
        path (str): The ESS log file to parse from.

    Returns: list
        The Cartesian coordinates.
    """
    lines = _get_lines_from_file(path)
    log = ess_factory(fullpath=path, check_for_errors=False)
    if not isinstance(log, GaussianLog):
        raise NotImplementedError(
            f'Currently parse_1d_scan_coords only supports Gaussian files, got {type(log)}'
        )
    traj = list()
    done = False
    i = 0
    while not done:
        if i >= len(lines) or 'Normal termination of Gaussian' in lines[
                i] or 'Error termination via' in lines[i]:
            done = True
        elif 'Optimization completed' in lines[i]:
            while len(lines) and 'Input orientation:' not in lines[i]:
                i += 1
                if 'Error termination via' in lines[i]:
                    return traj
            i += 5
            xyz_str = ''
            while len(
                    lines
            ) and '--------------------------------------------' not in lines[
                    i]:
                splits = lines[i].split()
                xyz_str += f'{qcel.periodictable.to_E(int(splits[1]))}  {splits[3]}  {splits[4]}  {splits[5]}\n'
                i += 1
            traj.append(str_to_xyz(xyz_str))
        i += 1
    return traj
Esempio n. 11
0
def parse_geometry(path: str) -> Optional[Dict[str, tuple]]:
    """
    Parse the xyz geometry from an ESS log file.

    Args:
        path (str): The ESS log file to parse from.

    Returns: Optional[Dict[str, tuple]]
        The cartesian geometry.
    """
    log = ess_factory(fullpath=path)
    try:
        coords, number, _ = log.load_geometry()
    except LogError:
        logger.debug(f'Could not parse xyz from {path}')

        # try parsing Gaussian standard orientation instead of the input orientation parsed by Arkane
        lines = _get_lines_from_file(path)
        xyz_str = ''
        for i in range(len(lines)):
            if 'Standard orientation:' in lines[i]:
                xyz_str = ''
                j = i
                while len(lines) and not lines[j].split()[0].isdigit():
                    j += 1
                while len(lines) and '-------------------' not in lines[j]:
                    splits = lines[j].split()
                    xyz_str += f'{qcel.periodictable.to_E(int(splits[1]))}  {splits[3]}  {splits[4]}  {splits[5]}\n'
                    j += 1
                break

        if xyz_str:
            return str_to_xyz(xyz_str)

        return None

    return xyz_from_data(coords=coords, numbers=number)
Esempio n. 12
0
def parse_trajectory(path: str) -> List[Dict[str, tuple]]:
    """
    Parse all geometries from an xyz trajectory file or an ESS output file.

    Args:
        path (str): The file path.

    Raises:
        ParserError: If the trajectory could not be read.

    Returns: List[Dict[str, tuple]]
        Entries are xyz's on the trajectory.
    """
    lines = _get_lines_from_file(path)

    ess_file = False
    if path.split('.')[-1] != 'xyz':
        try:
            log = ess_factory(fullpath=path)
            ess_file = True
        except InputError:
            ess_file = False

    if ess_file:
        if not isinstance(log, GaussianLog):
            raise NotImplementedError(
                f'Currently parse_trajectory only supports Gaussian files, got {type(log)}'
            )
        traj = list()
        done = False
        i = 0
        while not done:
            if i >= len(lines) or 'Normal termination of Gaussian' in lines[
                    i] or 'Error termination via' in lines[i]:
                done = True
            elif 'Input orientation:' in lines[i]:
                i += 5
                xyz_str = ''
                while len(
                        lines
                ) and '--------------------------------------------' not in lines[
                        i]:
                    splits = lines[i].split()
                    xyz_str += f'{qcel.periodictable.to_E(int(splits[1]))}  {splits[3]}  {splits[4]}  {splits[5]}\n'
                    i += 1
                traj.append(str_to_xyz(xyz_str))
            i += 1

    else:
        # this is not an ESS output file, probably an XYZ format file with several Cartesian coordinates
        skip_line = False
        num_of_atoms = 0
        traj, xyz_lines = list(), list()
        for line in lines:
            splits = line.strip().split()
            if len(splits) == 1 and all([c.isdigit() for c in splits[0]]):
                if len(xyz_lines):
                    if len(xyz_lines) != num_of_atoms:
                        raise ParserError(
                            f'Could not parse trajectory, expected {num_of_atoms} atoms, '
                            f'but got {len(xyz_lines)} for point {len(traj) + 1} in the trajectory.'
                        )
                    traj.append(
                        str_to_xyz(''.join(
                            [xyz_line for xyz_line in xyz_lines])))
                num_of_atoms = int(splits[0])
                skip_line = True
                xyz_lines = list()
            elif skip_line:
                # skip the comment line
                skip_line = False
                continue
            else:
                xyz_lines.append(line)

        if len(xyz_lines):
            # add the last point in the trajectory
            if len(xyz_lines) != num_of_atoms:
                raise ParserError(
                    f'Could not parse trajectory, expected {num_of_atoms} atoms, '
                    f'but got {len(xyz_lines)} for point {len(traj) + 1} in the trajectory.'
                )
            traj.append(
                str_to_xyz(''.join([xyz_line for xyz_line in xyz_lines])))

    if not len(traj):
        raise ParserError(f'Could not parse trajectory from {path}')
    return traj
Esempio n. 13
0
def parse_xyz_from_file(path: str) -> Optional[Dict[str, tuple]]:
    """
    Parse xyz coordinated from:
    - .xyz: XYZ file
    - .gjf: Gaussian input file
    - .out or .log: ESS output file (Gaussian, Molpro, Orca, QChem, TeraChem) - calls parse_geometry()
    - other: Molpro or QChem input file

    Args:
        path (str): The file path.

    Raises:
        ParserError: If the coordinates could not be parsed.

    Returns: Optional[Dict[str, tuple]]
        The parsed cartesian coordinates.
    """
    lines = _get_lines_from_file(path)
    file_extension = os.path.splitext(path)[1]

    xyz = None
    relevant_lines = list()

    if file_extension == '.xyz':
        for i, line in enumerate(reversed(lines)):
            splits = line.strip().split()
            if len(splits) == 1 and all([c.isdigit() for c in splits[0]]):
                # this is the last number of atoms line (important when parsing trajectories)
                num_of_atoms = int(splits[0])
                break
        else:
            raise ParserError(
                f'Could not identify the number of atoms line in the xyz file {path}'
            )
        index = len(lines) - i - 1
        relevant_lines = lines[index + 2:index + 2 + num_of_atoms]
    elif file_extension == '.gjf':
        start_parsing = False
        for line in lines:
            if start_parsing and line and line != '\n' and line != '\r\n':
                relevant_lines.append(line)
            elif start_parsing:
                break
            else:
                splits = line.split()
                if len(splits) == 2 and all([s.isdigit() for s in splits]):
                    start_parsing = True
    elif 'out' in file_extension or 'log' in file_extension:
        xyz = parse_geometry(path)
    else:
        record = False
        for line in lines:
            if '$end' in line or '}' in line:
                break
            if record and len(line.split()) == 4:
                relevant_lines.append(line)
            elif '$molecule' in line:
                record = True
            elif 'geometry={' in line:
                record = True
        if not relevant_lines:
            raise ParserError(
                f'Could not parse xyz coordinates from file {path}')
    if xyz is None and relevant_lines:
        xyz = str_to_xyz(''.join([line for line in relevant_lines if line]))
    return xyz
Esempio n. 14
0
    def test_calculate_dihedral_angle(self):
        """Test calculating a dihedral angle from xyz coordinates"""
        propene = converter.str_to_xyz("""C       1.22905000   -0.16449200    0.00000000
    C      -0.13529200    0.45314000    0.00000000
    C      -1.27957200   -0.21983000    0.00000000
    H       1.17363000   -1.25551200    0.00000000
    H       1.79909600    0.15138400    0.87934300
    H       1.79909600    0.15138400   -0.87934300
    H      -0.16831500    1.54137600    0.00000000
    H      -2.23664600    0.28960500    0.00000000
    H      -1.29848800   -1.30626200    0.00000000""")
        hydrazine = converter.str_to_xyz("""N       0.70683700   -0.07371000   -0.21400700
    N      -0.70683700    0.07371000   -0.21400700
    H       1.11984200    0.81113900   -0.47587600
    H       1.07456200   -0.35127300    0.68988300
    H      -1.11984200   -0.81113900   -0.47587600
    H      -1.07456200    0.35127300    0.68988300""")
        cj_11974 = converter.str_to_xyz("""C 	5.675	2.182	1.81
    O 	4.408	1.923	1.256
    C 	4.269	0.813	0.479
    C 	5.303	-0.068	0.178
    C 	5.056	-1.172	-0.639
    C 	3.794	-1.414	-1.169
    C 	2.77	-0.511	-0.851
    C 	2.977	0.59	-0.032
    C 	1.872	1.556	0.318
    N 	0.557	1.029	-0.009
    C 	-0.537	1.879	0.448
    C 	-0.535	3.231	-0.298
    C 	-1.831	3.983	0.033
    C 	-3.003	3.199	-0.61
    N 	-2.577	1.854	-0.99
    C 	-1.64	1.962	-2.111
    C 	-0.501	2.962	-1.805
    C 	-1.939	1.236	0.178
    C 	-1.971	-0.305	0.069
    C 	-3.385	-0.794	-0.209
    C 	-4.336	-0.893	0.81
    C 	-5.631	-1.324	0.539
    C 	-5.997	-1.673	-0.759
    C 	-5.056	-1.584	-1.781
    C 	-3.764	-1.147	-1.505
    C 	-1.375	-1.024	1.269
    C 	-1.405	-0.508	2.569
    C 	-0.871	-1.226	3.638
    C 	-0.296	-2.475	3.429
    C 	-0.259	-3.003	2.14
    C 	-0.794	-2.285	1.078
    C 	3.533	-2.614	-2.056
    C 	2.521	-3.574	-1.424
    C 	3.087	-2.199	-3.461
    H 	5.569	3.097	2.395
    H 	6.433	2.338	1.031
    H 	6.003	1.368	2.47
    H 	6.302	0.091	0.57
    H 	5.874	-1.854	-0.864
    H 	1.772	-0.654	-1.257
    H 	1.963	1.832	1.384
    H 	2.033	2.489	-0.239
    H 	0.469	0.13	0.461
    H 	-0.445	2.089	1.532
    H 	0.328	3.83	0.012
    H 	-1.953	4.059	1.122
    H 	-1.779	5.008	-0.352
    H 	-3.365	3.702	-1.515
    H 	-3.856	3.118	0.074
    H 	-1.226	0.969	-2.31
    H 	-2.211	2.259	-2.999
    H 	-0.639	3.906	-2.348
    H 	0.466	2.546	-2.105
    H 	-2.586	1.501	1.025
    H 	-1.36	-0.582	-0.799
    H 	-4.057	-0.647	1.831
    H 	-6.355	-1.396	1.347
    H 	-7.006	-2.015	-0.97
    H 	-5.329	-1.854	-2.798
    H 	-3.038	-1.07	-2.311
    H 	-1.843	0.468	2.759
    H 	-0.904	-0.802	4.638
    H 	0.125	-3.032	4.262
    H 	0.189	-3.977	1.961
    H 	-0.772	-2.708	0.075
    H 	4.484	-3.155	-2.156
    H 	1.543	-3.093	-1.308
    H 	2.383	-4.464	-2.049
    H 	2.851	-3.899	-0.431
    H 	3.826	-1.542	-3.932
    H 	2.134	-1.659	-3.429
    H 	2.951	-3.078	-4.102""")

        dihedral0 = vectors.calculate_dihedral_angle(coords=propene['coords'], torsion=[9, 3, 2, 7], index=1)
        dihedral1 = vectors.calculate_dihedral_angle(coords=propene['coords'], torsion=[5, 1, 2, 7], index=1)
        self.assertAlmostEqual(dihedral0, 180, 2)
        self.assertAlmostEqual(dihedral1, 59.26447, 2)
        dihedral2 = vectors.calculate_dihedral_angle(coords=propene['coords'], torsion=[8, 2, 1, 6], index=0)
        self.assertEqual(dihedral0, dihedral2)

        dihedral3 = vectors.calculate_dihedral_angle(coords=hydrazine['coords'], torsion=[3, 1, 2, 5], index=1)
        self.assertAlmostEqual(dihedral3, 148.31829, 2)

        dihedral2 = vectors.calculate_dihedral_angle(coords=cj_11974['coords'], torsion=[15, 18, 19, 20], index=1)
        self.assertAlmostEqual(dihedral2, 308.04758, 2)
Esempio n. 15
0
    def test_colliding_atoms(self):
        """Check that we correctly determine when atoms collide in xyz"""
        xyz_no_0 = """C	0.0000000	0.0000000	0.6505570"""  # monoatomic
        xyz_no_1 = """C      -0.84339557   -0.03079260   -0.13110478
N       0.53015060    0.44534713   -0.25006000
O       1.33245258   -0.55134720    0.44204567
H      -1.12632103   -0.17824612    0.91628291
H      -1.52529493    0.70480833   -0.56787044
H      -0.97406455   -0.97317212   -0.67214713
H       0.64789210    1.26863944    0.34677470
H       1.98414750   -0.79355889   -0.24492049"""  # no colliding atoms
        xyz_no_2 = """C      0.0 0.0 0.0
H       0.0 0.0 1.09"""  # no colliding atoms
        xyz_no_3 = """N      -0.29070308    0.26322835    0.48770927
N       0.29070351   -0.26323281   -0.48771096
N      -2.61741263    1.38275080    2.63428181
N       2.61742270   -1.38276006   -2.63427425
C      -1.77086206    0.18100754    0.43957605
C       1.77086254   -0.18101028   -0.43957552
C      -2.22486176   -1.28143567    0.45202312
C      -2.30707039    0.92407663   -0.78734681
C       2.30707074   -0.92407071    0.78735246
C       2.22485929    1.28143406   -0.45203080
C      -2.23868798    0.85547218    1.67084736
C       2.23869247   -0.85548109   -1.67084185
H      -1.90398693   -1.81060764   -0.45229645
H      -3.31681639   -1.35858536    0.51240600
H      -1.80714051   -1.81980551    1.31137107
H      -3.40300863    0.95379538   -0.78701415
H      -1.98806037    0.44494681   -1.71978670
H      -1.94802915    1.96005927   -0.81269573
H       1.98805486   -0.44493850    1.71978893
H       1.94803425   -1.96005464    0.81270509
H       3.40300902   -0.95378386    0.78702431
H       1.90398036    1.81061002    0.45228426
H       3.31681405    1.35858667   -0.51241516
H       1.80713611    1.81979843   -1.31138136"""  # check that N=N and C#N do not collide

        self.assertFalse(common.colliding_atoms(
            converter.str_to_xyz(xyz_no_0)))
        self.assertFalse(common.colliding_atoms(
            converter.str_to_xyz(xyz_no_1)))
        self.assertFalse(common.colliding_atoms(
            converter.str_to_xyz(xyz_no_2)))
        self.assertFalse(common.colliding_atoms(
            converter.str_to_xyz(xyz_no_3)))

        xyz_0 = """C      0.0 0.0 0.0
H       0.0 0.0 0.5"""  # colliding atoms
        xyz_1 = """C      -0.84339557   -0.03079260   -0.13110478
N       0.53015060    0.44534713   -0.25006000
O       1.33245258   -0.55134720    0.44204567
H      -1.12632103   -0.17824612    0.91628291
H      -1.52529493    0.70480833   -0.56787044
H      -0.97406455   -0.97317212   -0.67214713
H       1.33245258   -0.55134720    0.48204567
H       1.98414750   -0.79355889   -0.24492049"""  # colliding atoms
        xyz_2 = """ N                 -0.29070308    0.26322835    0.48770927
 N                  0.29070351   -0.26323281   -0.48771096
 N                 -2.48318439    1.19587180    2.29281971
 N                  2.61742270   -1.38276006   -2.63427425
 C                 -1.77086206    0.18100754    0.43957605
 C                  1.77086254   -0.18101028   -0.43957552
 C                 -2.22486176   -1.28143567    0.45202312
 C                 -2.30707039    0.92407663   -0.78734681
 C                  2.30707074   -0.92407071    0.78735246
 C                  2.22485929    1.28143406   -0.45203080
 C                 -2.23868798    0.85547218    1.67084736
 C                  2.23869247   -0.85548109   -1.67084185
 H                 -1.90398693   -1.81060764   -0.45229645
 H                 -3.31681639   -1.35858536    0.51240600
 H                 -1.80714051   -1.81980551    1.31137107
 H                 -3.40300863    0.95379538   -0.78701415
 H                 -1.98806037    0.44494681   -1.71978670
 H                 -1.94802915    1.96005927   -0.81269573
 H                  1.98805486   -0.44493850    1.71978893
 H                  1.94803425   -1.96005464    0.81270509
 H                  3.40300902   -0.95378386    0.78702431
 H                  1.90398036    1.81061002    0.45228426
 H                  3.31681405    1.35858667   -0.51241516
 H                  1.80713611    1.81979843   -1.31138136"""  # check that C-N collide
        xyz_3 = """ N                 -0.29070308    0.26322835    0.48770927
 N                  0.29070351   -0.26323281   -0.48771096
 N                 -2.61741263    1.38275080    2.63428181
 N                  2.61742270   -1.38276006   -2.63427425
 C                 -1.77086206    0.18100754    0.43957605
 C                  1.77086254   -0.18101028   -0.43957552
 C                 -2.22486176   -1.28143567    0.45202312
 C                 -2.30707039    0.92407663   -0.78734681
 C                  2.30707074   -0.92407071    0.78735246
 C                  2.22485929    1.28143406   -0.45203080
 C                 -2.23868798    0.85547218    1.67084736
 C                  2.23869247   -0.85548109   -1.67084185
 H                 -1.90398693   -1.81060764   -0.45229645
 H                 -2.77266137   -1.32013927    0.48231533
 H                 -1.80714051   -1.81980551    1.31137107
 H                 -3.40300863    0.95379538   -0.78701415
 H                 -1.98806037    0.44494681   -1.71978670
 H                 -1.94802915    1.96005927   -0.81269573
 H                  1.98805486   -0.44493850    1.71978893
 H                  1.94803425   -1.96005464    0.81270509
 H                  3.40300902   -0.95378386    0.78702431
 H                  1.90398036    1.81061002    0.45228426
 H                  3.31681405    1.35858667   -0.51241516
 H                  1.80713611    1.81979843   -1.31138136"""  # check that C-H collide

        self.assertTrue(common.colliding_atoms(converter.str_to_xyz(xyz_0)))
        self.assertTrue(common.colliding_atoms(converter.str_to_xyz(xyz_1)))
        self.assertTrue(common.colliding_atoms(converter.str_to_xyz(xyz_2)))
        self.assertTrue(common.colliding_atoms(converter.str_to_xyz(xyz_3)))