Skip to content

Commit 793fdec

Browse files
committed
Added fix_mol_electronic_configuration() to species
Also added get_atom_theoretical_charge()
1 parent 438af0c commit 793fdec

1 file changed

Lines changed: 62 additions & 5 deletions

File tree

arc/species/species.py

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,11 +1935,7 @@ def _scissors(self,
19351935
added_radical = list()
19361936
for mol, label in zip([mol1, mol2], [label1, label2]):
19371937
for atom in mol.atoms:
1938-
theoretical_charge = elements.PeriodicSystem.valence_electrons[atom.symbol] \
1939-
- atom.get_total_bond_order() \
1940-
- atom.radical_electrons - \
1941-
2 * atom.lone_pairs
1942-
if theoretical_charge == atom.charge + 1:
1938+
if get_atom_theoretical_charge(atom) == atom.charge + 1:
19431939
# we're missing a radical electron on this atom
19441940
if label not in added_radical or label == 'H':
19451941
atom.radical_electrons += 1
@@ -2708,3 +2704,64 @@ def split_mol(mol: Molecule) -> Tuple[List[Molecule], List[List[int]]]:
27082704
molecules.append(Molecule(atoms=[mol.atoms[index] for index in frag_indices]))
27092705
fragments.append(frag_indices)
27102706
return molecules, fragments
2707+
2708+
2709+
def get_atom_theoretical_charge(atom: Atom) -> float:
2710+
"""
2711+
Get the theoretical charge of an atom based on its electronic properties.
2712+
2713+
Args:
2714+
atom (Atom): The atom to check.
2715+
2716+
Returns:
2717+
float: The theoretical charge of the atom.
2718+
"""
2719+
return elements.PeriodicSystem.valence_electrons[atom.symbol] \
2720+
- atom.get_total_bond_order() \
2721+
- atom.radical_electrons - \
2722+
2 * atom.lone_pairs
2723+
2724+
2725+
def fix_mol_electronic_configuration(mol: Optional[Molecule] = None) -> Optional[Molecule]:
2726+
"""
2727+
Fix the electronic configuration (number of radicals, lone pairs, and formal charges) of a Molecule object
2728+
that was perceived from xyz. Assumes the multiplicity attribute of the given molecule is correct.
2729+
2730+
Args:
2731+
mol (Molecule, optional): The molecule to fix.
2732+
2733+
Returns:
2734+
Molecule: The fixed molecule.
2735+
"""
2736+
if mol is None:
2737+
return None
2738+
multiplicity = mol.multiplicity
2739+
n_radicals = mol.get_radical_count()
2740+
if n_radicals + 1 > mol.multiplicity:
2741+
# Find adjacent atoms with opposite-spin radicals, and pair the radicals up into a bond.
2742+
mols = mol.generate_resonance_structures(keep_isomorphic=False, filter_structures=True, save_order=True)
2743+
for structure in mols + [mol]:
2744+
structure.multiplicity = multiplicity
2745+
visited = list()
2746+
updated = False
2747+
for mol_1 in mols:
2748+
mol_1.multiplicity = mol.multiplicity
2749+
for atom_1 in mol_1.atoms:
2750+
if atom_1 not in visited and atom_1.radical_electrons >= 1:
2751+
for atom_2, bond in atom_1.edges.items():
2752+
if atom_2.radical_electrons >= 1:
2753+
atom_1.radical_electrons -= 1
2754+
atom_2.radical_electrons -= 1
2755+
bond.order += 1
2756+
visited.append(atom_2)
2757+
updated = True
2758+
break
2759+
visited.append(atom_1)
2760+
# Update formal charges.
2761+
for atom in mol_1.atoms:
2762+
theoretical_charge = get_atom_theoretical_charge(atom)
2763+
if theoretical_charge != atom.charge:
2764+
atom.charge = theoretical_charge
2765+
if updated:
2766+
return mol_1
2767+
return mols[0]

0 commit comments

Comments
 (0)