def update_molecule(mol, to_single_bonds=False): """ Returns a copy of the current molecule with updated atomTypes if to_single_bonds is True, the returned mol contains only single bonds. This is useful for isomorphism comparison """ new_mol = Molecule() try: atoms = mol.atoms except AttributeError: return None atom_mapping = dict() for atom1 in atoms: new_atom = new_mol.addAtom(Atom(atom1.element)) atom_mapping[atom1] = new_atom for atom1 in atoms: for atom2 in atom1.bonds.keys(): bond_order = 1.0 if to_single_bonds else atom1.bonds[ atom2].getOrderNum() bond = Bond(atom_mapping[atom1], atom_mapping[atom2], bond_order) new_mol.addBond(bond) try: new_mol.updateAtomTypes() except AtomTypeError: pass new_mol.multiplicity = mol.multiplicity return new_mol
def testPickle(self): """ Test that a Molecule object can be successfully pickled and unpickled with no loss of information. """ molecule0 = Molecule().fromSMILES('C=CC=C[CH2]C') molecule0.updateAtomTypes() molecule0.updateConnectivityValues() import cPickle molecule = cPickle.loads(cPickle.dumps(molecule0)) self.assertEqual(len(molecule0.atoms), len(molecule.atoms)) self.assertEqual(molecule0.getFormula(), molecule.getFormula()) self.assertTrue(molecule0.isIsomorphic(molecule)) self.assertTrue(molecule.isIsomorphic(molecule0))
def getResonanceHybrid(self): """ Returns a molecule object with bond orders that are the average of all the resonance structures. """ # get labeled resonance isomers self.generate_resonance_structures(keep_isomorphic=True) # only consider reactive molecules as representative structures molecules = [mol for mol in self.molecule if mol.reactive] # return if no resonance if len(molecules) == 1: return molecules[0] # create a sorted list of atom objects for each resonance structure cython.declare(atomsFromStructures = list, oldAtoms = list, newAtoms = list, numResonanceStructures=cython.short, structureNum = cython.short, oldBondOrder = cython.float, index1 = cython.short, index2 = cython.short, newMol=Molecule, oldMol = Molecule, atom1=Atom, atom2=Atom, bond=Bond, atoms=list,) atomsFromStructures = [] for newMol in molecules: newMol.atoms.sort(key=lambda atom: atom.id) atomsFromStructures.append(newMol.atoms) numResonanceStructures = len(molecules) # make original structure with no bonds newMol = Molecule() originalAtoms = atomsFromStructures[0] for atom1 in originalAtoms: atom = newMol.addAtom(Atom(atom1.element)) atom.id = atom1.id newAtoms = newMol.atoms # initialize bonds to zero order for index1, atom1 in enumerate(originalAtoms): for atom2 in atom1.bonds: index2 = originalAtoms.index(atom2) bond = Bond(newAtoms[index1],newAtoms[index2], 0) newMol.addBond(bond) # set bonds to the proper value for structureNum, oldMol in enumerate(molecules): oldAtoms = atomsFromStructures[structureNum] for index1, atom1 in enumerate(oldAtoms): # make bond orders average of resonance structures for atom2 in atom1.bonds: index2 = oldAtoms.index(atom2) newBond = newMol.getBond(newAtoms[index1], newAtoms[index2]) oldBondOrder = oldMol.getBond(oldAtoms[index1], oldAtoms[index2]).getOrderNum() newBond.applyAction(('CHANGE_BOND',None,oldBondOrder / numResonanceStructures / 2)) # set radicals in resonance hybrid to maximum of all structures if atom1.radicalElectrons > 0: newAtoms[index1].radicalElectrons = max(atom1.radicalElectrons, newAtoms[index1].radicalElectrons) newMol.updateAtomTypes(logSpecies = False, raiseException=False) return newMol