def test_get_ts_guess_neb(): reactant = Reactant(name='inital', charge=-1, mult=0, solvent_name='water', atoms=xyz_file_to_atoms(init_xyz)) product = Reactant(name='final', charge=-1, mult=0, solvent_name='water', atoms=xyz_file_to_atoms(final_xyz)) xtb = XTB() # Don't run the NEB without a working XTB install if shutil.which('xtb') is None or not shutil.which('xtb').endswith('xtb'): return xtb.path = shutil.which('xtb') ts_guess = neb.get_ts_guess_neb(reactant, product, method=xtb, n=10) assert ts_guess is not None # Approximate distances at the TS guess assert 1.8 < ts_guess.get_distance(0, 2) < 2.2 # C-F assert 1.9 < ts_guess.get_distance(2, 1) < 2.3 # C-Cl if os.path.exists('NEB'): shutil.rmtree('NEB') if os.path.exists('neb.xyz'): os.remove('neb.xyz')
def test_calculate_reaction_profile_energies(): test_reac = Reactant(name='test', smiles='C') test_reac.energy = -1 test_prod = Product(name='test', smiles='C') test_prod.energy = -1.03187251 tsguess = TSguess(atoms=test_reac.atoms, reactant=ReactantComplex(test_reac), product=ProductComplex()) tsguess.bond_rearrangement = BondRearrangement() ts = TransitionState(tsguess) ts.energy = -0.96812749 reaction = Reaction(test_reac, test_prod) reaction.ts = ts energies = plotting.calculate_reaction_profile_energies(reactions=[reaction], units=KcalMol) # Energies have been set to ∆E = -20 and ∆E‡ = 20 kcal mol-1 respectively assert energies[0] == 0 assert 19 < energies[1] < 21 assert -21 < energies[2] < -19 # Copying the reaction should give relative energies [0, 20, -20, 0, -40] energies = plotting.calculate_reaction_profile_energies(reactions=[reaction, deepcopy(reaction)], units=KcalMol) # Energies have been set to ∆E = -20 and ∆E‡ = 20 kcal mol-1 respectively assert energies[0] == 0 assert -0.1 < energies[3] < 0.1 assert -41 < energies[4] < -39
def test_reaction_warnings(): test_reac = Reactant(name='test', smiles='C') test_reac.energy = -1 test_prod = Product(name='test', smiles='C') test_prod.energy = -1.03187251 tsguess = TSguess(atoms=test_reac.atoms, reactant=ReactantComplex(test_reac), product=ProductComplex()) tsguess.bond_rearrangement = BondRearrangement() ts = TransitionState(tsguess) ts.energy = -0.98 ts.imaginary_frequencies = [-100] reaction = Reaction(test_reac, test_prod) reaction.ts = None # Should be some warning with no TS assert len( plotting.get_reaction_profile_warnings(reactions=[reaction])) > 10 # Should be no warnings with a TS that exists and has an energy and one # imaginary freq reaction.ts = ts warnings = plotting.get_reaction_profile_warnings(reactions=[reaction]) assert 'None' in warnings
def _init_from_smiles(self, reaction_smiles): """ Initialise from a SMILES string of the whole reaction e.g. CC(C)=O.[C-]#N>>CC([O-])(C#N)C for the addition of cyanide to acetone Arguments: reaction_smiles (str): """ try: reacs_smiles, prods_smiles = reaction_smiles.split('>>') except ValueError: raise UnbalancedReaction('Could not decompose to reacs & prods') # Add all the reactants and products with interpretable names for i, reac_smiles in enumerate(reacs_smiles.split('.')): reac = Reactant(smiles=reac_smiles) reac.name = f'r{i}_{reac.formula()}' self.reacs.append(reac) for i, prod_smiles in enumerate(prods_smiles.split('.')): prod = Product(smiles=prod_smiles) prod.name = f'p{i}_{prod.formula()}' self.prods.append(prod) return None
def test_ts_conformer(tmpdir): os.chdir(tmpdir) ch3cl = Reactant(charge=0, mult=1, atoms=[ Atom('Cl', 1.63664, 0.02010, -0.05829), Atom('C', -0.14524, -0.00136, 0.00498), Atom('H', -0.52169, -0.54637, -0.86809), Atom('H', -0.45804, -0.50420, 0.92747), Atom('H', -0.51166, 1.03181, -0.00597) ]) f = Reactant(charge=-1, mult=1, atoms=[Atom('F', 4.0, 0.0, 0.0)]) ch3f = Product(charge=0, mult=1, atoms=[ Atom('C', -0.05250, 0.00047, -0.00636), Atom('F', 1.31229, -0.01702, 0.16350), Atom('H', -0.54993, -0.04452, 0.97526), Atom('H', -0.34815, 0.92748, -0.52199), Atom('H', -0.36172, -0.86651, -0.61030) ]) cl = Reactant(charge=-1, mult=1, atoms=[Atom('Cl', 4.0, 0.0, 0.0)]) f_ch3cl_tsguess = TSguess(reactant=ReactantComplex(f, ch3cl), product=ProductComplex(ch3f, cl), atoms=[ Atom('F', -2.66092, -0.01426, 0.09700), Atom('Cl', 1.46795, 0.05788, -0.06166), Atom('C', -0.66317, -0.01826, 0.02488), Atom('H', -0.78315, -0.58679, -0.88975), Atom('H', -0.70611, -0.54149, 0.97313), Atom('H', -0.80305, 1.05409, 0.00503) ]) f_ch3cl_tsguess.bond_rearrangement = BondRearrangement(breaking_bonds=[ (2, 1) ], forming_bonds=[(0, 2)]) f_ch3cl_ts = TransitionState(ts_guess=f_ch3cl_tsguess) atoms = conf_gen.get_simanl_atoms( species=f_ch3cl_ts, dist_consts=get_distance_constraints(f_ch3cl_ts)) regen = Molecule(name='regenerated_ts', charge=-1, mult=1, atoms=atoms) # regen.print_xyz_file() # Ensure the making/breaking bonds retain their length regen_coords = regen.get_coordinates() assert are_coords_reasonable(regen_coords) is True assert 1.9 < np.linalg.norm(regen_coords[0] - regen_coords[2]) < 2.1 assert 2.0 < np.linalg.norm(regen_coords[1] - regen_coords[2]) < 2.2 os.chdir(here)
def test_find_tss(): Config.num_conformers = 1 # Spoof ORCA install Config.ORCA.path = here # Don't run the calculation without a working XTB install if shutil.which('xtb') is None or not shutil.which('xtb').endswith('xtb'): return if os.path.exists('/dev/shm'): Config.ll_tmp_dir = '/dev/shm' Config.XTB.path = shutil.which('xtb') Config.ORCA.implicit_solvation_type = cpcm Config.make_ts_template = False Config.num_complex_sphere_points = 2 Config.num_complex_random_rotations = 1 # SN2 example flouride = Reactant(name='F-', smiles='[F-]') methyl_chloride = Reactant(name='CH3Cl', smiles='ClC') chloride = Product(name='Cl-', smiles='[Cl-]') methyl_flouride = Product(name='CH3F', smiles='CF') reaction = Reaction(flouride, methyl_chloride, chloride, methyl_flouride, name='sn2', solvent_name='water') # Will work in data/locate_ts/transition_states reaction.locate_transition_state() assert reaction.ts is not None os.chdir('transition_states') assert reaction.ts.is_true_ts() os.chdir('..') reaction.ts.save_ts_template(folder_path=os.getcwd()) assert os.path.exists('template0.txt') # There should now be a saved template templates = get_ts_templates(folder_path=os.getcwd()) assert len(templates) == 1 template = templates[0] assert template.solvent.name == 'water' assert template.mult == 1 assert template.charge == -1 assert template.graph.number_of_nodes() == 6 # Reset the configuration Config.ll_tmp_dir = None
def test_two_component_truncation(): propylbromide = Reactant(name='RBr', atoms=xyz_file_to_atoms('RBr.xyz')) chloride = Reactant(name='Cl', smiles='[Cl-]') mol = ReactantComplex(chloride, propylbromide) bond_rearr = BondRearrangement(forming_bonds=[(0, 3)], breaking_bonds=[(3, 4)]) truncated = get_truncated_complex(r_complex=mol, bond_rearrangement=bond_rearr) # Should truncate to ethylbromide + Cl- assert truncated.n_atoms == 9
def test_isomorphic_reactant_product(): r_water = Reactant(name='h2o', smiles='O') r_methane = Reactant(name='methane', smiles='C') p_water = Product(name='h2o', smiles='O') p_methane = Product(name='methane', smiles='C') # Reaction where the reactant and product complexes are isomorphic # should return no TS reaction = Reaction(r_water, r_methane, p_water, p_methane) reaction.locate_transition_state() assert reaction.ts is None
def test_plot_reaction_profile(): r = Reactant(name='reactant', smiles='C') p = Product(name='product', smiles='C') tsguess = TSguess(atoms=r.atoms, reactant=ReactantComplex(r), product=ProductComplex(p)) tsguess.bond_rearrangement = BondRearrangement() ts = TransitionState(tsguess) reaction = Reaction(r, p) reaction.ts = ts plotting.plot_reaction_profile(reactions=[reaction], units=KjMol, name='test') assert os.path.exists('test_reaction_profile.png') os.remove('test_reaction_profile.png') with pytest.raises(AssertionError): plotting.plot_reaction_profile(reactions=[reaction], units=KjMol, name='test', free_energy=True, enthalpy=True) return None
def test_graph_no_other_bonds(): reac = Reactant(name='r', atoms=xyz_file_to_atoms('h_shift_correct_ts_mode.xyz')) br = BondRearrangement(breaking_bonds=[(1, 10)], forming_bonds=[(5, 10)]) calc = Calculation(name='h_shift', molecule=reac, method=orca, keywords=orca.keywords.opt_ts, n_cores=1) calc.output.filename = 'h_shift_correct_ts_mode.out' calc.output.file_lines = open('h_shift_correct_ts_mode.out', 'r').readlines() f_ts = Species(name='f_displaced', charge=0, mult=1, atoms=get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=1.0)) b_ts = Species(name='b_displaced', charge=0, mult=1, atoms=get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=-1.0)) assert not imag_mode_generates_other_bonds(ts=reac, f_species=f_ts, b_species=b_ts, bond_rearrangement=br)
def _init_from_smiles(self, reaction_smiles): """ Initialise from a SMILES string of the whole reaction e.g. CC(C)=O.[C-]#N>>CC([O-])(C#N)C for the addition of cyanide to acetone Arguments: reaction_smiles (str): """ try: reacs_smiles, prods_smiles = reaction_smiles.split('>>') except ValueError: raise UnbalancedReaction('Could not decompose to reacs & prods') def name(smiles): """A more readable string as a name""" return ''.join([a for a in smiles if a.isalpha()]) # Add all the reactants and products for reac_smiles in reacs_smiles.split('.'): self.reacs.append(Reactant(name=name(reac_smiles), smiles=reac_smiles)) for prod_smiles in prods_smiles.split('.'): self.prods.append(Product(name=name(prod_smiles), smiles=prod_smiles)) return None
def test_enone_truncation(): enone = Reactant(name='enone', smiles='CC(O)=CC(=O)OC') reactant = ReactantComplex(enone) bond_rearr = BondRearrangement(breaking_bonds=[(2, 11)], forming_bonds=[(11, 5)]) truncated = get_truncated_complex(reactant, bond_rearr) assert truncated.n_atoms == 10 assert truncated.graph.number_of_edges() == 9
def test_2dpes_properties(): pes = pes_2d.PES2d(reactant=Reactant(smiles='O'), product=Product(), r1s=np.linspace(4.0, 1.5, 9), r1_idxs=(0, 2), r2s=np.linspace(1.78, 4.0, 8), r2_idxs=(1, 2)) assert not pes.products_made()
def test_get_ts_guess_neb(): reactant = Reactant(name='inital', charge=-1, mult=0, solvent_name='water', atoms=xyz_file_to_atoms('sn2_init.xyz')) product = Reactant(name='final', charge=-1, mult=0, solvent_name='water', atoms=xyz_file_to_atoms('sn2_final.xyz')) xtb = XTB() # Don't run the NEB without a working XTB install if shutil.which('xtb') is None or not shutil.which('xtb').endswith('xtb'): return xtb.path = shutil.which('xtb') ts_guess = get_ts_guess_neb(reactant, product, method=xtb, n=10) assert ts_guess is not None # Approximate distances at the TS guess assert 1.8 < ts_guess.distance(0, 2) < 2.3 # C-F assert 1.9 < ts_guess.distance(2, 1) < 2.5 # C-Cl if os.path.exists('NEB'): shutil.rmtree('NEB') if os.path.exists('neb.xyz'): os.remove('neb.xyz') # Trying to get a TS guess with an unavailable method should return None # as a TS guess orca = ORCA() orca.path = None orca_ts_guess = get_ts_guess_neb(reactant, product, method=orca, n=10) assert orca_ts_guess is None
def test_bonds(): h1 = Atom(atomic_symbol='H', x=0.0, y=0.0, z=0.0) h2 = Atom(atomic_symbol='H', x=0.0, y=0.0, z=0.7) h3 = Atom(atomic_symbol='H', x=0.0, y=0.0, z=1.7) hydrogen = Reactant(name='H2', atoms=[h1, h2], charge=0, mult=1) h = Reactant(name='H', atoms=[h3], charge=0, mult=2) reac = ReactantComplex(hydrogen, h) prod_h2 = Product(name='H2', atoms=[h1, h2], charge=0, mult=1) prod_h = Product(name='H', atoms=[h3], charge=0, mult=2) fbond = FormingBond(atom_indexes=(1, 2), species=reac) bbond = BreakingBond(atom_indexes=(0, 1), species=reac, reaction=Reaction(hydrogen, h, prod_h2, prod_h)) assert fbond.curr_dist == 1.0 assert 0.6 < fbond.final_dist < 0.8 assert 2.0 < bbond.final_dist < 2.5 assert bbond.curr_dist == 0.7
def test_large_truncation(): mol = ReactantComplex( Reactant(name='product', atoms=xyz_file_to_atoms('product.xyz'))) bond_rearr = BondRearrangement(breaking_bonds=[(7, 8), (14, 18)]) assert mol.n_atoms == 50 truncated = get_truncated_complex(r_complex=mol, bond_rearrangement=bond_rearr) assert truncated.n_atoms == 27 assert truncated.graph.number_of_edges() == 28
def test_correct_imag_mode(): os.chdir(os.path.join(here, 'data')) bond_rearrangement = BondRearrangement(breaking_bonds=[(4, 1), (4, 18)], forming_bonds=[(1, 18)]) g09 = G09() g09.available = True calc = Calculation(name='tmp', molecule=ReactantComplex( Reactant(smiles='CC(C)(C)C1C=CC=C1')), method=g09, keywords=Config.G09.keywords.opt_ts) calc.output.filename = 'correct_ts_mode_g09.log' calc.output.set_lines() f_displaced_atoms = get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=1.0) f_species = Species(name='f_displaced', atoms=f_displaced_atoms, charge=0, mult=1) # Charge & mult are placeholders b_displaced_atoms = get_displaced_atoms_along_mode(calc, mode_number=6, disp_magnitude=-1.0) b_species = Species(name='b_displaced', atoms=b_displaced_atoms, charge=0, mult=1) # With the correct mode no other bonds are made assert not imag_mode_generates_other_bonds( ts=calc.molecule, f_species=f_species, b_species=b_species, bond_rearrangement=bond_rearrangement) calc.output.filename = 'incorrect_ts_mode_g09.log' calc.output.set_lines() assert not imag_mode_has_correct_displacement(calc, bond_rearrangement) os.chdir(here)
def test_plot_reaction_profile(): # only tests the file is created with the right name os.chdir(os.path.join(here, 'data')) r = Reactant(name='reactant', smiles='C') p = Product(name='product', smiles='C') tsguess = TSguess(atoms=r.atoms, reactant=ReactantComplex(r), product=ProductComplex(p)) tsguess.bond_rearrangement = BondRearrangement() ts = TransitionState(tsguess) reaction = Reaction(r, p) reaction.ts = ts plotting.plot_reaction_profile(reactions=[reaction], units=KjMol, name='test_reaction') assert os.path.exists('test_reaction_reaction_profile.png') os.remove('test_reaction_reaction_profile.png') os.chdir(here)
def test_plot_reaction_profile(): r = Reactant(name='reactant', smiles='C') p = Product(name='product', smiles='C') tsguess = TSguess(atoms=r.atoms, reactant=ReactantComplex(r), product=ProductComplex(p)) tsguess.bond_rearrangement = BondRearrangement() ts = TransitionState(tsguess) reaction = Reaction(r, p) reaction.ts = ts plotting.plot_reaction_profile(reactions=[reaction], units=KjMol, name='test_reaction') assert os.path.exists('test_reaction_reaction_profile.png') os.remove('test_reaction_reaction_profile.png')
def has_correct_mode(name, fbonds, bbonds): reac = Reactant(name='r', atoms=xyz_file_to_atoms(f'{name}.xyz')) calc = Calculation(name=name, molecule=reac, method=orca, keywords=orca.keywords.opt_ts, n_cores=1) calc.output.filename = f'{name}.out' calc.output.file_lines = open(f'{name}.out', 'r').readlines() bond_rearr = BondRearrangement(breaking_bonds=bbonds, forming_bonds=fbonds) # Don't require all bonds to be breaking/making in a 'could be ts' function return imag_mode_has_correct_displacement(calc, bond_rearr, delta_threshold=0.05, req_all=False)
from autode.species.molecule import Reactant, Product from autode.atoms import Atom from autode.transition_states.templates import get_ts_templates from autode.transition_states.templates import get_value_from_file from autode.transition_states.templates import get_values_dict_from_file from autode.transition_states.templates import TStemplate from autode.mol_graphs import get_truncated_active_mol_graph from autode.transition_states.ts_guess import get_template_ts_guess from autode.wrappers.XTB import XTB here = os.path.dirname(os.path.abspath(__file__)) ch3cl = Reactant(charge=0, mult=1, atoms=[ Atom('Cl', 1.63664, 0.02010, -0.05829), Atom('C', -0.14524, -0.00136, 0.00498), Atom('H', -0.52169, -0.54637, -0.86809), Atom('H', -0.45804, -0.50420, 0.92747), Atom('H', -0.51166, 1.03181, -0.00597) ]) f = Reactant(charge=-1, mult=1, atoms=[Atom('F', 4.0, 0.0, 0.0)]) reac_complex = ReactantComplex(f, ch3cl) ch3f = Product(charge=0, mult=1, atoms=[ Atom('C', -0.05250, 0.00047, -0.00636), Atom('F', 1.31229, -0.01702, 0.16350), Atom('H', -0.54993, -0.04452, 0.97526), Atom('H', -0.34815, 0.92748, -0.52199), Atom('H', -0.36172, -0.86651, -0.61030)
def test_get_ts_guess_2dscan(): ch3cl_f = Reactant(name='CH3Cl_F-', charge=-1, mult=1, atoms=[ Atom('F', -4.14292, -0.24015, 0.07872), Atom('Cl', 1.63463, 0.09787, -0.02490), Atom('C', -0.14523, -0.00817, 0.00208), Atom('H', -0.47498, -0.59594, -0.86199), Atom('H', -0.45432, -0.49900, 0.93234), Atom('H', -0.56010, 1.00533, -0.04754) ]) ch3f_cl = Product(name='CH3Cl_F-', charge=-1, mult=1, atoms=[ Atom('F', 1.63463, 0.09787, -0.02490), Atom('Cl', -4.14292, -0.24015, 0.07872), Atom('C', -0.14523, -0.00817, 0.00208), Atom('H', -0.47498, -0.59594, -0.86199), Atom('H', -0.45432, -0.49900, 0.93234), Atom('H', -0.56010, 1.00533, -0.04754) ]) # H H # F- C--Cl -> F--C Cl- # H H H H pes = pes_2d.PES2d(reactant=ReactantComplex(ch3cl_f), product=ProductComplex(ch3f_cl), r1s=np.linspace(4.0, 1.5, 9), r1_idxs=(0, 2), r2s=np.linspace(1.78, 4.0, 8), r2_idxs=(1, 2)) pes.calculate(name='SN2_PES', method=xtb, keywords=xtb.keywords.low_opt) assert pes.species[0, 1] is not None assert -13.13 < pes.species[0, 1].energy < -13.11 assert pes.species.shape == (9, 8) assert pes.rs.shape == (9, 8) assert type(pes.rs[0, 1]) == tuple assert pes.rs[1, 1] == (np.linspace(4.0, 1.5, 9)[1], np.linspace(1.78, 4.0, 8)[1]) # Fitting the surface with a 2D polynomial up to order 3 in r1 and r2 i.e. # r1^3r2^3 pes.fit(polynomial_order=3) assert pes.coeff_mat is not None assert pes.coeff_mat.shape == (4, 4) # Includes r1^0 etc. pes.print_plot(name='pes_plot') assert os.path.exists('pes_plot.png') os.remove('pes_plot.png') # Products should be made on this surface assert pes.products_made() # Get the TS guess from this surface calling all the above functions reactant = ReactantComplex(ch3cl_f) fbond = FormingBond(atom_indexes=(0, 2), species=reactant) fbond.final_dist = 1.5 bbond = BreakingBond(atom_indexes=(1, 2), species=reactant, reaction=Reaction(ch3cl_f, ch3f_cl)) bbond.final_dist = 4.0 ts_guess = pes_2d.get_ts_guess_2d(reactant=reactant, product=ProductComplex(ch3f_cl), bond1=fbond, bond2=bbond, polynomial_order=3, name='SN2_PES', method=xtb, keywords=xtb.keywords.low_opt, dr=0.3) assert ts_guess is not None assert ts_guess.n_atoms == 6 assert ts_guess.energy is None assert 1.9 < ts_guess.get_distance(0, 2) < 2.1 assert 1.9 < ts_guess.get_distance(1, 2) < 2.0
from autode.transition_states.truncation import get_truncated_complex from autode.transition_states.locate_tss import translate_rotate_reactant from autode.bond_rearrangement import BondRearrangement from autode.input_output import xyz_file_to_atoms from autode.mol_graphs import is_isomorphic from autode.species.complex import ReactantComplex from autode.species.molecule import Reactant from autode.atoms import Atom import os here = os.path.dirname(os.path.abspath(__file__)) methane = Reactant(name='methane', charge=0, mult=1, atoms=[Atom('C', 0.93919, -0.81963, 0.00000), Atom('H', 2.04859, -0.81963, -0.00000), Atom('H', 0.56939, -0.25105, 0.87791), Atom('H', 0.56938, -1.86422, 0.05345), Atom('H', 0.56938, -0.34363, -0.93136)]) ethene = Reactant(name='ethene', charge=0, mult=1, atoms=[Atom('C', 0.84102, -0.74223, 0.00000), Atom('C', -0.20368, 0.08149, 0.00000), Atom('H', 1.63961, -0.61350, -0.72376), Atom('H', 0.90214, -1.54881, 0.72376), Atom('H', -0.26479, 0.88807, -0.72376), Atom('H', -1.00226, -0.04723, 0.72376)]) propene = Reactant(name='propene', charge=0, mult=1, atoms=[Atom('C', 1.06269, -0.71502, 0.09680), Atom('C', 0.01380, 0.10714, 0.00458), Atom('H', 0.14446, 1.16840, -0.18383),
def test_reactant_to_product(): methane = Reactant(smiles='C', charge=0, mult=1) prod = reactant_to_product(reactant=methane) assert type(prod) is Product
def test_find_tss(): os.chdir(os.path.join(here, 'data', 'locate_ts')) Config.num_conformers = 1 # Spoof ORCA install Config.ORCA.path = here # Don't run the calculation without a working XTB install if shutil.which('xtb') is None or not shutil.which('xtb').endswith('xtb'): return Config.XTB.path = shutil.which('xtb') Config.ORCA.implicit_solvation_type = 'cpcm' Config.make_ts_template = False Config.num_complex_sphere_points = 2 Config.num_complex_random_rotations = 1 # SN2 example flouride = Reactant(name='F-', smiles='[F-]') methyl_chloride = Reactant(name='CH3Cl', smiles='ClC') chloride = Product(name='Cl-', smiles='[Cl-]') methyl_flouride = Product(name='CH3F', smiles='CF') reaction = Reaction(flouride, methyl_chloride, chloride, methyl_flouride, name='sn2', solvent_name='water') # Will work in data/locate_ts/transition_states reaction.locate_transition_state() assert reaction.ts is not None os.chdir(os.path.join(here, 'data', 'locate_ts', 'transition_states')) for filename in os.listdir(os.getcwd()): if filename.endswith(('.inp', '.png')): os.remove(filename) assert reaction.ts.is_true_ts() reaction.ts.save_ts_template(folder_path=os.getcwd()) assert os.path.exists('template0.obj') # There should now be a saved template templates = get_ts_templates(folder_path=os.getcwd()) assert len(templates) == 1 template = templates[0] assert template.solvent.name == 'water' assert template.mult == 1 assert template.charge == -1 assert template.graph.number_of_nodes() == 6 # Tidy the generated files os.remove('template0.obj') os.chdir(here)