def test_from_SMILES_like_string1(self): # generate fragment from SMILES like string # the atom type is also calculated smiles_like = 'C' fragment = afm.fragment.Fragment().from_SMILES_like_string(smiles_like) # construct fragment manually atom_C = Atom(element=getElement('C'), radicalElectrons=0, charge=0, lonePairs=0) atom_H1 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H2 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H3 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H4 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_C.atomType = atomTypes['Cs'] atom_H1.atomType = atomTypes['H'] atom_H2.atomType = atomTypes['H'] atom_H3.atomType = atomTypes['H'] atom_H4.atomType = atomTypes['H'] vertices = [atom_C, atom_H1, atom_H2, atom_H3, atom_H4] bonds = [ Bond(atom_C, atom_H1, 1), Bond(atom_C, atom_H2, 1), Bond(atom_C, atom_H3, 1), Bond(atom_C, atom_H4, 1) ] expected_fragment = afm.fragment.Fragment() for vertex in vertices: expected_fragment.addVertex(vertex) for bond in bonds: expected_fragment.addEdge(bond) self.assertTrue(expected_fragment.isIsomorphic(fragment))
def setUp(self): """ A function run before each unit test in this class. """ # construct the first fragment atom_C1 = Atom(element=getElement('C'), radicalElectrons=0, charge=0, lonePairs=0) cutting_label_R1 = afm.fragment.CuttingLabel('R') cutting_label_L1 = afm.fragment.CuttingLabel('L') vertices = [atom_C1, cutting_label_R1, cutting_label_L1] bonds = [ Bond(atom_C1, cutting_label_R1), Bond(atom_C1, cutting_label_L1) ] self.fragment1 = afm.fragment.Fragment() for vertex in vertices: self.fragment1.addVertex(vertex) for bond in bonds: self.fragment1.addEdge(bond) # construct the second fragment atom_C2 = Atom(element=getElement('C'), radicalElectrons=0, charge=0, lonePairs=0) cutting_label_R2 = afm.fragment.CuttingLabel('R') cutting_label_L2 = afm.fragment.CuttingLabel('L') vertices = [atom_C2, cutting_label_R2, cutting_label_L2] bonds = [ Bond(atom_C2, cutting_label_R2), Bond(atom_C2, cutting_label_L2) ] self.fragment2 = afm.fragment.Fragment() for vertex in vertices: self.fragment2.addVertex(vertex) for bond in bonds: self.fragment2.addEdge(bond)
def generate_isotopomers(spc, N=1): """ Generate all isotopomers of the parameter species by adding max. N carbon isotopes to the atoms of the species. """ mol = spc.molecule[0] isotope = getElement(6, 13) mols = [] add_isotope(0, N, mol, mols, isotope) spcs = [] for isomol in mols: isotopomer = Species(molecule=[isomol], thermo=deepcopy(spc.thermo), transportData=spc.transportData, reactive=spc.reactive) isotopomer.generate_resonance_structures(keep_isomorphic=True) spcs.append(isotopomer) # do not retain identical species: filtered = [] while spcs: candidate = spcs.pop() unique = True for isotopomer in filtered: if isotopomer.isIsomorphic(candidate): unique = False break if unique: filtered.append(candidate) if spc.thermo: for isotopomer in filtered: correct_entropy(isotopomer, spc) return filtered
def test_update(self): atom_C = Atom(element=getElement('C'), radicalElectrons=0, charge=0, lonePairs=0) atom_H1 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H2 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) cutting_label_R1 = afm.fragment.CuttingLabel('R') cutting_label_R2 = afm.fragment.CuttingLabel('R') vertices = [ atom_C, cutting_label_R1, cutting_label_R2, atom_H1, atom_H2 ] bonds = [ Bond(atom_C, cutting_label_R1, 1), Bond(atom_C, cutting_label_R2, 1), Bond(atom_C, atom_H1, 1), Bond(atom_C, atom_H2, 1) ] fragment = afm.fragment.Fragment() for vertex in vertices: fragment.addVertex(vertex) for bond in bonds: fragment.addEdge(bond) fragment.update() for v in fragment.vertices: if isinstance(v, Atom) and v.isCarbon(): break self.assertTrue(v.atomType == atomTypes['Cs']) self.assertTrue(fragment.getNetCharge() == 0) self.assertTrue(fragment.multiplicity == 1)
def fromOBMol(mol, obmol): """ Convert a OpenBabel Mol object `obmol` to a molecular structure. Uses `OpenBabel <http://openbabel.org/>`_ to perform the conversion. """ # Below are the declared variables for cythonizing the module # cython.declare(i=cython.int) # cython.declare(radicalElectrons=cython.int, charge=cython.int, lonePairs=cython.int) # cython.declare(atom=Atom, atom1=Atom, atom2=Atom, bond=Bond) mol.vertices = [] # Add hydrogen atoms to complete molecule if needed obmol.AddHydrogens() # TODO Chem.rdmolops.Kekulize(obmol, clearAromaticFlags=True) # iterate through atoms in obmol for obatom in openbabel.OBMolAtomIter(obmol): idx = obatom.GetIdx() #openbabel idx starts at 1! # Use atomic number as key for element number = obatom.GetAtomicNum() element = elements.getElement(number) # Process charge charge = obatom.GetFormalCharge() obatom_multiplicity = obatom.GetSpinMultiplicity() radicalElectrons = obatom_multiplicity - 1 if obatom_multiplicity != 0 else 0 atom = Atom(element, radicalElectrons, charge, '', 0) mol.vertices.append(atom) # iterate through bonds in obmol for obbond in openbabel.OBMolBondIter(obmol): order = 0 # Process bond type oborder = obbond.GetBondOrder() if oborder == 1: order = 'S' elif oborder == 2: order = 'D' elif oborder == 3: order = 'T' elif obbond.IsAromatic(): order = 'B' bond = Bond(mol.vertices[obbond.GetBeginAtomIdx() - 1], mol.vertices[obbond.GetEndAtomIdx() - 1], order) #python array indices start at 0 mol.addBond(bond) # Set atom types and connectivity values mol.updateConnectivityValues() mol.updateAtomTypes() mol.updateMultiplicity() mol.updateLonePairs() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, mol.multiplicity = mol.getRadicalCount() + 1 return mol
def fromOBMol(mol, obmol): """ Convert a OpenBabel Mol object `obmol` to a molecular structure. Uses `OpenBabel <http://openbabel.org/>`_ to perform the conversion. """ # Below are the declared variables for cythonizing the module # cython.declare(i=cython.int) # cython.declare(radicalElectrons=cython.int, charge=cython.int, lonePairs=cython.int) # cython.declare(atom=Atom, atom1=Atom, atom2=Atom, bond=Bond) mol.vertices = [] # Add hydrogen atoms to complete molecule if needed obmol.AddHydrogens() # TODO Chem.rdmolops.Kekulize(obmol, clearAromaticFlags=True) # iterate through atoms in obmol for obatom in openbabel.OBMolAtomIter(obmol): idx = obatom.GetIdx()#openbabel idx starts at 1! # Use atomic number as key for element number = obatom.GetAtomicNum() element = elements.getElement(number) # Process charge charge = obatom.GetFormalCharge() obatom_multiplicity = obatom.GetSpinMultiplicity() radicalElectrons = obatom_multiplicity - 1 if obatom_multiplicity != 0 else 0 atom = Atom(element, radicalElectrons, charge, '', 0) mol.vertices.append(atom) # iterate through bonds in obmol for obbond in openbabel.OBMolBondIter(obmol): order = 0 # Process bond type oborder = obbond.GetBondOrder() if oborder == 1: order = 'S' elif oborder == 2: order = 'D' elif oborder == 3: order = 'T' elif obbond.IsAromatic() : order = 'B' bond = Bond(mol.vertices[obbond.GetBeginAtomIdx() - 1], mol.vertices[obbond.GetEndAtomIdx() - 1], order)#python array indices start at 0 mol.addBond(bond) # Set atom types and connectivity values mol.updateConnectivityValues() mol.updateAtomTypes() mol.updateMultiplicity() mol.updateLonePairs() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, mol.multiplicity = mol.getRadicalCount() + 1 return mol
def setUp(self): """ A method called before each unit test in this class. """ self.atom = Atom(element=getElement('C'), radicalElectrons=1, charge=0, label='*1', lonePairs=0)
def fromOBMol(mol, obmol): """ Convert a OpenBabel Mol object `obmol` to a molecular structure. Uses `OpenBabel <http://openbabel.org/>`_ to perform the conversion. """ # Below are the declared variables for cythonizing the module # cython.declare(i=cython.int) # cython.declare(radicalElectrons=cython.int, charge=cython.int, lonePairs=cython.int) # cython.declare(atom=mm.Atom, atom1=mm.Atom, atom2=mm.Atom, bond=mm.Bond) if not OB_INSTALLED: raise DependencyError( 'OpenBabel is not installed. Please install or use RDKit.') mol.vertices = [] # Add hydrogen atoms to complete molecule if needed obmol.AddHydrogens() # TODO Chem.rdmolops.Kekulize(obmol, clearAromaticFlags=True) # iterate through atoms in obmol for obatom in openbabel.OBMolAtomIter(obmol): # Use atomic number as key for element number = obatom.GetAtomicNum() isotope = obatom.GetIsotope() element = elements.getElement(number, isotope or -1) # Process charge charge = obatom.GetFormalCharge() obatom_multiplicity = obatom.GetSpinMultiplicity() radicalElectrons = obatom_multiplicity - 1 if obatom_multiplicity != 0 else 0 atom = mm.Atom(element, radicalElectrons, charge, '', 0) mol.vertices.append(atom) # iterate through bonds in obmol for obbond in openbabel.OBMolBondIter(obmol): # Process bond type oborder = obbond.GetBondOrder() if oborder not in [1, 2, 3] and obbond.IsAromatic(): oborder = 1.5 bond = mm.Bond(mol.vertices[obbond.GetBeginAtomIdx() - 1], mol.vertices[obbond.GetEndAtomIdx() - 1], oborder) #python array indices start at 0 mol.addBond(bond) # Set atom types and connectivity values mol.updateConnectivityValues() mol.updateAtomTypes() mol.updateMultiplicity() mol.identifyRingMembership() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, mol.multiplicity = mol.getRadicalCount() + 1 return mol
def setUp(self): """ A method called before each unit test in this class. """ self.atom = Atom(element=getElement('C'), radicalElectrons=1, spinMultiplicity=2, charge=0, label='*1')
def fromOBMol(mol, obmol): """ Convert a OpenBabel Mol object `obmol` to a molecular structure. Uses `OpenBabel <http://openbabel.org/>`_ to perform the conversion. """ # Below are the declared variables for cythonizing the module # cython.declare(i=cython.int) # cython.declare(radicalElectrons=cython.int, charge=cython.int, lonePairs=cython.int) # cython.declare(atom=mm.Atom, atom1=mm.Atom, atom2=mm.Atom, bond=mm.Bond) if not OB_INSTALLED: raise DependencyError('OpenBabel is not installed. Please install or use RDKit.') mol.vertices = [] # Add hydrogen atoms to complete molecule if needed obmol.AddHydrogens() # TODO Chem.rdmolops.Kekulize(obmol, clearAromaticFlags=True) # iterate through atoms in obmol for obatom in openbabel.OBMolAtomIter(obmol): # Use atomic number as key for element number = obatom.GetAtomicNum() isotope = obatom.GetIsotope() element = elements.getElement(number, isotope or -1) # Process charge charge = obatom.GetFormalCharge() obatom_multiplicity = obatom.GetSpinMultiplicity() radicalElectrons = obatom_multiplicity - 1 if obatom_multiplicity != 0 else 0 atom = mm.Atom(element, radicalElectrons, charge, '', 0) mol.vertices.append(atom) # iterate through bonds in obmol for obbond in openbabel.OBMolBondIter(obmol): # Process bond type oborder = obbond.GetBondOrder() if oborder not in [1,2,3,4] and obbond.IsAromatic() : oborder = 1.5 bond = mm.Bond(mol.vertices[obbond.GetBeginAtomIdx() - 1], mol.vertices[obbond.GetEndAtomIdx() - 1], oborder)#python array indices start at 0 mol.addBond(bond) # Set atom types and connectivity values mol.updateConnectivityValues() mol.updateAtomTypes() mol.updateMultiplicity() mol.identifyRingMembership() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, mol.multiplicity = mol.getRadicalCount() + 1 return mol
def get_xyz_string(coords, mol=None, numbers=None, symbols=None): """ Convert list of lists xyz form:: [[0.6616514836, 0.4027481525, -0.4847382281], [-0.6039793084, 0.6637270105, 0.0671637135], [-1.4226865648, -0.4973210697, -0.2238712255], [-0.4993010635, 0.6531020442, 1.0853092315], [-2.2115796924, -0.4529256762, 0.4144516252], [-1.8113671395, -0.3268900681, -1.1468957003]] into a geometry form read by an ESS:: C 0.6616514836 0.4027481525 -0.4847382281 N -0.6039793084 0.6637270105 0.0671637135 H -1.4226865648 -0.4973210697 -0.2238712255 H -0.4993010635 0.6531020442 1.0853092315 H -2.2115796924 -0.4529256762 0.4144516252 H -1.8113671395 -0.3268900681 -1.1468957003 The atom symbols are derived from either an RMG Molecule object, atom numbers, or explicitly given (`symbol`). This function isn't defined as a method of ARCSpecies since it is also used when parsing opt geometry in Scheduler. Args: coords (list): The array-format coordinates to be converted. mol (Molecule, optional): An RMG Molecule object. numbers (list, optional): Entries are atomic numbers (integers) corresponding to `coords`. symbols (list, optional): Entries are atomic symbols (strings) corresponding to `coords`. Returns: str: A string representation of the coordinates. """ if isinstance(coords, (str, unicode)): logger.debug('Cannot convert string format xyz into a string...') return coords result = '' if symbols is not None: elements = symbols elif numbers is not None: elements = [] for num in numbers: elements.append(getElement(int(num)).symbol) elif mol is not None: elements = [] for atom in mol.atoms: elements.append(atom.element.symbol) else: raise ValueError("Must have either an RMG:Molecule object input as `mol`, or atomic numbers / symbols.") for i, coordinate in enumerate(coords): result += elements[i] + ' ' * (4 - len(elements[i])) for c in coordinate: result += '{0:14.8f}'.format(c) result += '\n' return result
def pybel_to_rmg(pybelmol, addh=False): """ignore charge, multiplicity, and bond orders""" mol = molecule.Molecule() if addh: pybelmol.addh() for pybelatom in pybelmol: num = pybelatom.atomicnum element = elements.getElement(num) atom = molecule.Atom(element=element, coords=np.array(pybelatom.coords)) mol.vertices.append(atom) for obbond in pybel.ob.OBMolBondIter(pybelmol.OBMol): begin_idx = obbond.GetBeginAtomIdx() - 1 end_idx = obbond.GetEndAtomIdx() - 1 bond = molecule.Bond(mol.vertices[begin_idx], mol.vertices[end_idx]) mol.addBond(bond) return mol.toSingleBonds()
def is_enriched(obj): """ Returns True if the species or reaction object has any enriched isotopes. """ if isinstance(obj,Species): for atom in obj.molecule[0].atoms: if atom.element.isotope != -1 and not np.allclose(atom.element.mass, getElement(atom.element.symbol).mass): return True return False elif isinstance(obj,Reaction): enriched = [] for spec in obj.reactants: enriched.append(is_enriched(spec)) for spec in obj.products: enriched.append(is_enriched(spec)) return any(enriched) else: raise TypeError('is_enriched only takes species and reaction objects. {} was sent'.format(str(type(obj))))
def get_xyz_string(xyz, mol=None, number=None, symbol=None): """ Convert list of lists xyz form: [[0.6616514836, 0.4027481525, -0.4847382281], [-0.6039793084, 0.6637270105, 0.0671637135], [-1.4226865648, -0.4973210697, -0.2238712255], [-0.4993010635, 0.6531020442, 1.0853092315], [-2.2115796924, -0.4529256762, 0.4144516252], [-1.8113671395, -0.3268900681, -1.1468957003]] into a geometry form read by ESS: C 0.6616514836 0.4027481525 -0.4847382281 N -0.6039793084 0.6637270105 0.0671637135 H -1.4226865648 -0.4973210697 -0.2238712255 H -0.4993010635 0.6531020442 1.0853092315 H -2.2115796924 -0.4529256762 0.4144516252 H -1.8113671395 -0.3268900681 -1.1468957003 The atom symbols are derived from either an RMG Molecule object (`mol`) or atom numbers ('number`) or explicitly given (`symbol`). `number` and `symbol` are lists (optional parameters) `xyz` is an array of arrays, as shown in the example above. This function isn't defined as a method of ARCSpecies since it is also used when parsing opt geometry in Scheduler """ result = '' if symbol is not None: elements = symbol elif number is not None: elements = [] for num in number: elements.append(getElement(int(num)).symbol) elif mol is not None: elements = [] for atom in mol.atoms: elements.append(atom.element.symbol) else: raise ValueError( "Must have either an RMG:Molecule object input as `mol`, or atomic numbers \ symbols." ) for i, coord in enumerate(xyz): result += elements[i] + ' ' * (4 - len(elements[i])) for c in coord: result += '{0:14.8f}'.format(c) result += '\n' return result
def determine_symmetry(coords, symbols): """ Determine external symmetry and chirality (optical isomers) of the species. Args: coords (list): The 3D coordinates of a molecule in array-format. symbols (list): Entries are atomic symbols correcponding to coords. Returns: int: The external symmetry number. Returns: int: 1 if no chiral centers are present, 2 if chiral centers are present. """ atom_numbers = list() # List of atomic numbers for symbol in symbols: atom_numbers.append(getElement(str(symbol)).number) coords = np.array(coords, np.float64) # N x 3 numpy.ndarray of atomic coordinates # in the same order as `atom_numbers` unique_id = '0' # Just some name that the SYMMETRY code gives to one of its jobs scr_dir = os.path.join( arc_path, str('scratch') ) # Scratch directory that the SYMMETRY code writes its files in if not os.path.exists(scr_dir): os.makedirs(scr_dir) symmetry = optical_isomers = 1 qmdata = QMData( groundStateDegeneracy=1, # Only needed to check if valid QMData numberOfAtoms=len(atom_numbers), atomicNumbers=atom_numbers, atomCoords=(coords, str('angstrom')), energy=(0.0, str('kcal/mol')) # Only needed to avoid error ) settings = type( str(''), (), dict(symmetryPath=str('symmetry'), scratchDirectory=scr_dir))() pgc = PointGroupCalculator(settings, unique_id, qmdata) pg = pgc.calculate() if pg is not None: symmetry = pg.symmetryNumber optical_isomers = 2 if pg.chiral else optical_isomers return symmetry, optical_isomers
def get_representative_molecule(self, mode='minimal', update=True): if mode == 'minimal': # create a molecule from fragment.vertices.copy mapping = self.copyAndMap() # replace CuttingLabel with H atoms = [] for vertex in self.vertices: mapped_vertex = mapping[vertex] if isinstance(mapped_vertex, CuttingLabel): # replace cutting label with atom H atom_H = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) for bondedAtom, bond in mapped_vertex.edges.iteritems(): new_bond = Bond(bondedAtom, atom_H, order=bond.order) bondedAtom.edges[atom_H] = new_bond del bondedAtom.edges[mapped_vertex] atom_H.edges[bondedAtom] = new_bond mapping[vertex] = atom_H atoms.append(atom_H) else: atoms.append(mapped_vertex) # Note: mapping is a dict with # key: self.vertex and value: mol_repr.atom mol_repr = Molecule() mol_repr.atoms = atoms if update: mol_repr.update() return mol_repr, mapping
def fromRDKitMol(mol, rdkitmol): """ Convert a RDKit Mol object `rdkitmol` to a molecular structure. Uses `RDKit <http://rdkit.org/>`_ to perform the conversion. This Kekulizes everything, removing all aromatic atom types. """ cython.declare( i=cython.int, radicalElectrons=cython.int, charge=cython.int, lonePairs=cython.int, number=cython.int, order=cython.str, atom=Atom, atom1=Atom, atom2=Atom, bond=Bond, ) mol.vertices = [] # Add hydrogen atoms to complete molecule if needed rdkitmol = Chem.AddHs(rdkitmol) Chem.rdmolops.Kekulize(rdkitmol, clearAromaticFlags=True) # iterate through atoms in rdkitmol for i in xrange(rdkitmol.GetNumAtoms()): rdkitatom = rdkitmol.GetAtomWithIdx(i) # Use atomic number as key for element number = rdkitatom.GetAtomicNum() element = elements.getElement(number) # Process charge charge = rdkitatom.GetFormalCharge() radicalElectrons = rdkitatom.GetNumRadicalElectrons() atom = Atom(element, radicalElectrons, charge, "", 0) mol.vertices.append(atom) # Add bonds by iterating again through atoms for j in xrange(0, i): rdkitatom2 = rdkitmol.GetAtomWithIdx(j + 1) rdkitbond = rdkitmol.GetBondBetweenAtoms(i, j) if rdkitbond is not None: order = "" # Process bond type rdbondtype = rdkitbond.GetBondType() if rdbondtype.name == "SINGLE": order = "S" elif rdbondtype.name == "DOUBLE": order = "D" elif rdbondtype.name == "TRIPLE": order = "T" elif rdbondtype.name == "AROMATIC": order = "B" bond = Bond(mol.vertices[i], mol.vertices[j], order) mol.addBond(bond) # Set atom types and connectivity values mol.update() mol.updateLonePairs() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, mol.multiplicity = mol.getRadicalCount() + 1 return mol
def fromRDKitMol(self, rdkitmol, atom_replace_dict=None): """ Convert a RDKit Mol object `rdkitmol` to a molecular structure. Uses `RDKit <http://rdkit.org/>`_ to perform the conversion. This Kekulizes everything, removing all aromatic atom types. """ from rdkit import Chem self.vertices = [] # Add hydrogen atoms to complete molecule if needed rdkitmol.UpdatePropertyCache(strict=False) rdkitmol = Chem.AddHs(rdkitmol) Chem.rdmolops.Kekulize(rdkitmol, clearAromaticFlags=True) # iterate through atoms in rdkitmol for i in xrange(rdkitmol.GetNumAtoms()): rdkitatom = rdkitmol.GetAtomWithIdx(i) # Use atomic number as key for element number = rdkitatom.GetAtomicNum() element = getElement(number) # Process charge charge = rdkitatom.GetFormalCharge() radicalElectrons = rdkitatom.GetNumRadicalElectrons() ELE = element.symbol if atom_replace_dict.has_key('[' + ELE + ']'): cutting_label_name = atom_replace_dict['[' + ELE + ']'] cutting_label = CuttingLabel(name=cutting_label_name) self.vertices.append(cutting_label) else: atom = Atom(element, radicalElectrons, charge, '', 0) self.vertices.append(atom) # Add bonds by iterating again through atoms for j in xrange(0, i): rdkitbond = rdkitmol.GetBondBetweenAtoms(i, j) if rdkitbond is not None: order = 0 # Process bond type rdbondtype = rdkitbond.GetBondType() if rdbondtype.name == 'SINGLE': order = 1 elif rdbondtype.name == 'DOUBLE': order = 2 elif rdbondtype.name == 'TRIPLE': order = 3 elif rdbondtype.name == 'AROMATIC': order = 1.5 bond = Bond(self.vertices[i], self.vertices[j], order) self.addBond(bond) # We need to update lone pairs first because the charge was set by RDKit self.updateLonePairs() # Set atom types and connectivity values self.update() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, self.updateMultiplicity() # mol.updateAtomTypes() return self
def remove_isotope(labeledObj, inplace = False): """ Create a deep copy of the first molecule of the species object and replace non-normal Element objects (of special isotopes) by the expected isotope. If the boolean `inplace` is True, the method remove the isotopic atoms of the Species/Reaction inplace and returns a list of atom objects & element pairs for adding back to the oritinal object. This should significantly improve speed of this method. If successful, the non-inplace parts should be removed """ if isinstance(labeledObj,Species2): if inplace: modifiedAtoms = [] for mol in labeledObj.molecule: for atom in mol.atoms: if atom.element.isotope != -1: modifiedAtoms.append((atom,atom.element)) atom.element = getElement(atom.element.symbol) return modifiedAtoms else: stripped = labeledObj.copy(deep=True) for atom in stripped.molecule[0].atoms: if atom.element.isotope != -1: atom.element = getElement(atom.element.symbol) # only do it for the first molecule, generate the other resonance isomers. stripped.molecule = [stripped.molecule[0]] stripped.generate_resonance_structures(keep_isomorphic=True) return stripped elif isinstance(labeledObj,Reaction): if inplace: atomList = [] for reactant in labeledObj.reactants: removed = remove_isotope(reactant,inplace) if removed: atomList += removed for product in labeledObj.products: removed = remove_isotope(product,inplace) if removed: atomList += removed return atomList else: strippedRxn = labeledObj.copy() strippedReactants = [] for reactant in strippedRxn.reactants: strippedReactants.append(remove_isotope(reactant,inplace)) strippedRxn.reactants = strippedReactants strippedProducts = [] for product in strippedRxn.products: strippedProducts.append(remove_isotope(product,inplace)) strippedRxn.products = strippedProducts return strippedRxn elif isinstance(labeledObj,Molecule): if inplace: modifiedAtoms = [] for atom in labeledObj.atoms: if atom.element.isotope != -1: modifiedAtoms.append((atom,atom.element)) atom.element = getElement(atom.element.symbol) return modifiedAtoms else: stripped = labeledObj.copy(deep=True) for atom in stripped.atoms: if atom.element.isotope != -1: atom.element = getElement(atom.element.symbol) return stripped else: raise TypeError('Only Reaction, Species, and Molecule objects are supported')
def remove_isotope(labeledObj, inplace=False): """ Create a deep copy of the first molecule of the species object and replace non-normal Element objects (of special isotopes) by the expected isotope. If the boolean `inplace` is True, the method remove the isotopic atoms of the Species/Reaction inplace and returns a list of atom objects & element pairs for adding back to the oritinal object. This should significantly improve speed of this method. If successful, the non-inplace parts should be removed """ if isinstance(labeledObj, Species2): if inplace: modifiedAtoms = [] for mol in labeledObj.molecule: for atom in mol.atoms: if atom.element.isotope != -1: modifiedAtoms.append((atom, atom.element)) atom.element = getElement(atom.element.symbol) return modifiedAtoms else: stripped = labeledObj.copy(deep=True) for atom in stripped.molecule[0].atoms: if atom.element.isotope != -1: atom.element = getElement(atom.element.symbol) # only do it for the first molecule, generate the other resonance isomers. stripped.molecule = [stripped.molecule[0]] stripped.generate_resonance_structures(keep_isomorphic=True) return stripped elif isinstance(labeledObj, Reaction): if inplace: atomList = [] for reactant in labeledObj.reactants: removed = remove_isotope(reactant, inplace) if removed: atomList += removed for product in labeledObj.products: removed = remove_isotope(product, inplace) if removed: atomList += removed return atomList else: strippedRxn = labeledObj.copy() strippedReactants = [] for reactant in strippedRxn.reactants: strippedReactants.append(remove_isotope(reactant, inplace)) strippedRxn.reactants = strippedReactants strippedProducts = [] for product in strippedRxn.products: strippedProducts.append(remove_isotope(product, inplace)) strippedRxn.products = strippedProducts return strippedRxn elif isinstance(labeledObj, Molecule): if inplace: modifiedAtoms = [] for atom in labeledObj.atoms: if atom.element.isotope != -1: modifiedAtoms.append((atom, atom.element)) atom.element = getElement(atom.element.symbol) return modifiedAtoms else: stripped = labeledObj.copy(deep=True) for atom in stripped.atoms: if atom.element.isotope != -1: atom.element = getElement(atom.element.symbol) return stripped else: raise TypeError( 'Only Reaction, Species, and Molecule objects are supported')
def fromRDKitMol(mol, rdkitmol): """ Convert a RDKit Mol object `rdkitmol` to a molecular structure. Uses `RDKit <http://rdkit.org/>`_ to perform the conversion. This Kekulizes everything, removing all aromatic atom types. """ cython.declare(i=cython.int, radicalElectrons=cython.int, charge=cython.int, lonePairs=cython.int, number=cython.int, order=cython.float, atom=mm.Atom, atom1=mm.Atom, atom2=mm.Atom, bond=mm.Bond) mol.vertices = [] # Add hydrogen atoms to complete molecule if needed rdkitmol.UpdatePropertyCache(strict=False) rdkitmol = Chem.AddHs(rdkitmol) Chem.rdmolops.Kekulize(rdkitmol, clearAromaticFlags=True) # iterate through atoms in rdkitmol for i in xrange(rdkitmol.GetNumAtoms()): rdkitatom = rdkitmol.GetAtomWithIdx(i) # Use atomic number as key for element number = rdkitatom.GetAtomicNum() isotope = rdkitatom.GetIsotope() element = elements.getElement(number, isotope or -1) # Process charge charge = rdkitatom.GetFormalCharge() radicalElectrons = rdkitatom.GetNumRadicalElectrons() atom = mm.Atom(element, radicalElectrons, charge, '', 0) mol.vertices.append(atom) # Add bonds by iterating again through atoms for j in xrange(0, i): rdkitbond = rdkitmol.GetBondBetweenAtoms(i, j) if rdkitbond is not None: order = 0 # Process bond type rdbondtype = rdkitbond.GetBondType() if rdbondtype.name == 'SINGLE': order = 1 elif rdbondtype.name == 'DOUBLE': order = 2 elif rdbondtype.name == 'TRIPLE': order = 3 elif rdbondtype.name == 'QUADRUPLE': order = 4 elif rdbondtype.name == 'AROMATIC': order = 1.5 bond = mm.Bond(mol.vertices[i], mol.vertices[j], order) mol.addBond(bond) # We need to update lone pairs first because the charge was set by RDKit mol.updateLonePairs() # Set atom types and connectivity values mol.update() # Assume this is always true # There are cases where 2 radicalElectrons is a singlet, but # the triplet is often more stable, mol.multiplicity = mol.getRadicalCount() + 1 # mol.updateAtomTypes() return mol
def assign_representative_molecule(self): # create a molecule from fragment.vertices.copy mapping = self.copyAndMap() # replace CuttingLabel with CC atoms = [] additional_atoms = [] additional_bonds = [] for vertex in self.vertices: mapped_vertex = mapping[vertex] if isinstance(mapped_vertex, CuttingLabel): # replace cutting label with atom C atom_C1 = Atom(element=getElement('C'), radicalElectrons=0, charge=0, lonePairs=0) for bondedAtom, bond in mapped_vertex.edges.iteritems(): new_bond = Bond(bondedAtom, atom_C1, order=bond.order) bondedAtom.edges[atom_C1] = new_bond del bondedAtom.edges[mapped_vertex] atom_C1.edges[bondedAtom] = new_bond # add hydrogens and carbon to make it CC atom_H1 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H2 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_C2 = Atom(element=getElement('C'), radicalElectrons=0, charge=0, lonePairs=0) atom_H3 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H4 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atom_H5 = Atom(element=getElement('H'), radicalElectrons=0, charge=0, lonePairs=0) atoms.append(atom_C1) additional_atoms.extend( [atom_H1, atom_H2, atom_H3, atom_H4, atom_H5, atom_C2]) additional_bonds.extend([ Bond(atom_C1, atom_H1, 1), Bond(atom_C1, atom_H2, 1), Bond(atom_C2, atom_H3, 1), Bond(atom_C2, atom_H4, 1), Bond(atom_C2, atom_H5, 1), Bond(atom_C1, atom_C2, 1) ]) else: atoms.append(mapped_vertex) mol_repr = Molecule() mol_repr.atoms = atoms for atom in additional_atoms: mol_repr.addAtom(atom) for bond in additional_bonds: mol_repr.addBond(bond) # update connectivity mol_repr.update() # create a species object from molecule self.mol_repr = mol_repr return mapping
maxSiliconAtoms = speciesConstraints.get("maximumSiliconAtoms", -1) if maxSiliconAtoms != -1: if struct.getNumAtoms("Si") > maxSiliconAtoms: return True maxSulfurAtoms = speciesConstraints.get("maximumSulfurAtoms", -1) if maxSulfurAtoms != -1: if struct.getNumAtoms("S") > maxSulfurAtoms: return True maxHeavyAtoms = speciesConstraints.get("maximumHeavyAtoms", -1) if maxHeavyAtoms != -1: if struct.getNumAtoms() - struct.getNumAtoms("H") > maxHeavyAtoms: return True maxRadicals = speciesConstraints.get("maximumRadicalElectrons", -1) if maxRadicals != -1: if struct.getNumberOfRadicalElectrons() > maxRadicals: return True maxIsotopes = speciesConstraints.get("maximumIsotopicAtoms", -1) if maxIsotopes != -1: counter = 0 for atom in struct.atoms: if not isclose(atom.mass, getElement(atom.symbol).mass, atol=1e-04): counter += 1 if counter > maxIsotopes: return True return False
maxSiliconAtoms = speciesConstraints.get('maximumSiliconAtoms', -1) if maxSiliconAtoms != -1: if struct.getNumAtoms('Si') > maxSiliconAtoms: return True maxSulfurAtoms = speciesConstraints.get('maximumSulfurAtoms', -1) if maxSulfurAtoms != -1: if struct.getNumAtoms('S') > maxSulfurAtoms: return True maxHeavyAtoms = speciesConstraints.get('maximumHeavyAtoms', -1) if maxHeavyAtoms != -1: if struct.getNumAtoms() - struct.getNumAtoms('H') > maxHeavyAtoms: return True maxRadicals = speciesConstraints.get('maximumRadicalElectrons', -1) if maxRadicals != -1: if (struct.getNumberOfRadicalElectrons() > maxRadicals): return True maxIsotopes = speciesConstraints.get('maximumIsotopicAtoms', -1) if maxIsotopes != -1: counter = 0 for atom in struct.atoms: if not isclose(atom.mass, getElement(atom.symbol).mass, atol=1e-04): counter += 1 if counter > maxIsotopes: return True return False
wilhoit.fitToData(Tlist, Cplist, Cp0, CpInf, H298, S298, B0=500.0)\ NASA_fit = wilhoit.toNASA(Tlist[0], Tlist[-1], Tint=500.0) string = '' f = open('chem.inp', 'a') # Line 1 string += '{0:<16} '.format(SpeciesIdentifier) if len(elementCounts) <= 4: # Use the original Chemkin syntax for the element counts for key, count in elementCounts.iteritems(): if isinstance(key, tuple): symbol, isotope = key chemkinName = getElement(symbol, isotope=isotope).chemkinName else: chemkinName = key string += '{0!s:<2}{1:>3d}'.format(chemkinName, count) string += ' ' * (4 - len(elementCounts)) else: string += ' ' * 4 string += 'G{0:>10.3f}{1:>10.3f}{2:>8.2f} 1'.format(NASA_fit.polynomials[0].Tmin.value_si, NASA_fit.polynomials[1].Tmax.value_si, NASA_fit.polynomials[0].Tmax.value_si) if len(elementCounts) > 4: string += '&\n' # Use the new-style Chemkin syntax for the element counts # This will only be recognized by Chemkin 4 or later for key, count in elementCounts.iteritems(): if isinstance(key, tuple):
maxSiliconAtoms = speciesConstraints.get('maximumSiliconAtoms', -1) if maxSiliconAtoms != -1: if struct.getNumAtoms('Si') > maxSiliconAtoms: return True maxSulfurAtoms = speciesConstraints.get('maximumSulfurAtoms', -1) if maxSulfurAtoms != -1: if struct.getNumAtoms('S') > maxSulfurAtoms: return True maxHeavyAtoms = speciesConstraints.get('maximumHeavyAtoms', -1) if maxHeavyAtoms != -1: if struct.getNumAtoms() - struct.getNumAtoms('H') > maxHeavyAtoms: return True maxRadicals = speciesConstraints.get('maximumRadicalElectrons', -1) if maxRadicals != -1: if (struct.getRadicalCount() > maxRadicals): return True maxIsotopes = speciesConstraints.get('maximumIsotopicAtoms', -1) if maxIsotopes != -1: counter = 0 for atom in struct.atoms: if not isclose(atom.mass, getElement(atom.symbol).mass, atol=1e-04): counter += 1 if counter > maxIsotopes: return True return False
def failsSpeciesConstraints(species): """ Pass in either a `Species` or `Molecule` object and checks whether it passes the speciesConstraints set by the user. If not, returns `True` for failing speciesConstraints. """ from rmgpy.rmg.input import getInput try: speciesConstraints = getInput('speciesConstraints') except Exception: logging.debug('Species constraints could not be found.') speciesConstraints = {} if isinstance(species, Species): struct = species.molecule[0] else: # expects a molecule here struct = species explicitlyAllowedMolecules = speciesConstraints.get( 'explicitlyAllowedMolecules', []) for molecule in explicitlyAllowedMolecules: if struct.isIsomorphic(molecule): return False maxCarbonAtoms = speciesConstraints.get('maximumCarbonAtoms', -1) if maxCarbonAtoms != -1: if struct.getNumAtoms('C') > maxCarbonAtoms: return True maxOxygenAtoms = speciesConstraints.get('maximumOxygenAtoms', -1) if maxOxygenAtoms != -1: if struct.getNumAtoms('O') > maxOxygenAtoms: return True maxNitrogenAtoms = speciesConstraints.get('maximumNitrogenAtoms', -1) if maxNitrogenAtoms != -1: if struct.getNumAtoms('N') > maxNitrogenAtoms: return True maxSiliconAtoms = speciesConstraints.get('maximumSiliconAtoms', -1) if maxSiliconAtoms != -1: if struct.getNumAtoms('Si') > maxSiliconAtoms: return True maxSulfurAtoms = speciesConstraints.get('maximumSulfurAtoms', -1) if maxSulfurAtoms != -1: if struct.getNumAtoms('S') > maxSulfurAtoms: return True maxHeavyAtoms = speciesConstraints.get('maximumHeavyAtoms', -1) if maxHeavyAtoms != -1: if struct.getNumAtoms() - struct.getNumAtoms('H') > maxHeavyAtoms: return True maxRadicals = speciesConstraints.get('maximumRadicalElectrons', -1) if maxRadicals != -1: if (struct.getRadicalCount() > maxRadicals): return True maxCarbenes = speciesConstraints.get('maximumSingletCarbenes', 1) if maxRadicals != -1: if struct.getSingletCarbeneCount() > maxCarbenes: return True maxCarbeneRadicals = speciesConstraints.get('maximumCarbeneRadicals', 0) if maxCarbeneRadicals != -1: if struct.getSingletCarbeneCount() > 0 and struct.getRadicalCount( ) > maxCarbeneRadicals: return True maxIsotopes = speciesConstraints.get('maximumIsotopicAtoms', -1) if maxIsotopes != -1: counter = 0 for atom in struct.atoms: if not isclose(atom.mass, getElement(atom.symbol).mass, atol=1e-04): counter += 1 if counter > maxIsotopes: return True return False
def failsSpeciesConstraints(species): """ Pass in either a `Species` or `Molecule` object and checks whether it passes the speciesConstraints set by the user. If not, returns `True` for failing speciesConstraints. """ from rmgpy.rmg.input import getInput try: speciesConstraints = getInput('speciesConstraints') except Exception: logging.debug('Species constraints could not be found.') speciesConstraints = {} if isinstance(species, Species): struct = species.molecule[0] else: # expects a molecule here struct = species explicitlyAllowedMolecules = speciesConstraints.get('explicitlyAllowedMolecules', []) for molecule in explicitlyAllowedMolecules: if struct.isIsomorphic(molecule): return False maxCarbonAtoms = speciesConstraints.get('maximumCarbonAtoms', -1) if maxCarbonAtoms != -1: if struct.getNumAtoms('C') > maxCarbonAtoms: return True maxOxygenAtoms = speciesConstraints.get('maximumOxygenAtoms', -1) if maxOxygenAtoms != -1: if struct.getNumAtoms('O') > maxOxygenAtoms: return True maxNitrogenAtoms = speciesConstraints.get('maximumNitrogenAtoms', -1) if maxNitrogenAtoms != -1: if struct.getNumAtoms('N') > maxNitrogenAtoms: return True maxSiliconAtoms = speciesConstraints.get('maximumSiliconAtoms', -1) if maxSiliconAtoms != -1: if struct.getNumAtoms('Si') > maxSiliconAtoms: return True maxSulfurAtoms = speciesConstraints.get('maximumSulfurAtoms', -1) if maxSulfurAtoms != -1: if struct.getNumAtoms('S') > maxSulfurAtoms: return True maxHeavyAtoms = speciesConstraints.get('maximumHeavyAtoms', -1) if maxHeavyAtoms != -1: if struct.getNumAtoms() - struct.getNumAtoms('H') > maxHeavyAtoms: return True maxRadicals = speciesConstraints.get('maximumRadicalElectrons', -1) if maxRadicals != -1: if (struct.getRadicalCount() > maxRadicals): return True maxCarbenes = speciesConstraints.get('maximumSingletCarbenes', 1) if maxRadicals != -1: if struct.getSingletCarbeneCount() > maxCarbenes: return True maxCarbeneRadicals = speciesConstraints.get('maximumCarbeneRadicals', 0) if maxCarbeneRadicals != -1: if struct.getSingletCarbeneCount() > 0 and struct.getRadicalCount() > maxCarbeneRadicals: return True maxIsotopes = speciesConstraints.get('maximumIsotopicAtoms', -1) if maxIsotopes != -1: counter = 0 for atom in struct.atoms: if not isclose(atom.mass, getElement(atom.symbol).mass, atol=1e-04): counter += 1 if counter > maxIsotopes: return True return False