def matchNodeToStructure(self, node, structure, atoms): """ Return :data:`True` if the `structure` centered at `atom` matches the structure at `node` in the dictionary. The structure at `node` should have atoms with the appropriate labels because they are set on loading and never change. However, the atoms in `structure` may not have the correct labels, hence the `atoms` parameter. The `atoms` parameter may include extra labels, and so we only require that every labeled atom in the functional group represented by `node` has an equivalent labeled atom in `structure`. """ group = self.dictionary[node] if group.__class__ == str or group.__class__ == unicode: if group.lower() == 'union': match = False for child in self.tree.children[node]: if self.matchNodeToStructure(child, structure, atoms): match = True return match else: return False else: centers = group.getLabeledAtoms() map12_0 = {}; map21_0 = {} for label in centers.keys(): if label in centers and label in atoms: center = centers[label]; atom = atoms[label] # Make sure labels actually pointed to atoms if center is None or atom is None: return False # Semantic check #1: atoms with same label are equivalent elif not atom.equivalent(center): return False # Semantic check #2: labeled atoms that share bond in one # also share equivalent bond in the other for atom1, atom2 in map21_0.iteritems(): if group.hasBond(center, atom1) and structure.hasBond(atom, atom2): bond1 = group.getBond(center, atom1) bond2 = structure.getBond(atom, atom2) if not bond1.equivalent(bond2): return False elif group.hasBond(center, atom1) or structure.hasBond(atom, atom2): return False # Passed semantic checks, so add to maps of already-matched # atoms map21_0[center] = atom; map12_0[atom] = center else: return False return structure.isSubgraphIsomorphic(group, map12_0, map21_0)
def makeNewSpecies(structure, label='', reactive=True): """ Attempt to make a new species based on a chemical `structure`, which is a :class:`Structure` object. The proposed species is checked against the list of existing species; if the species already exists, this function returns the existing species. If the species does not exist, a :class:`Species` object is created and returned after being appended to the global species list. """ global speciesCounter # # Recalculate atom types for proposed structure (hopefully not necessary) # structure.simplifyAtomTypes() # structure.updateAtomTypes() # First check cache and return if species is found for i, spec in enumerate(speciesCache): if spec.isIsomorphic(structure): speciesCache.pop(i) speciesCache.insert(0, spec) return spec # Return an existing species if a match is found for spec in speciesList: if spec.isIsomorphic(structure): speciesCache.insert(0, spec) if len(speciesCache) > speciesCacheMaxSize: speciesCache.pop() return spec # Return None if the species has a forbidden structure if thermo.forbiddenStructures is not None: for lbl, struct in thermo.forbiddenStructures.iteritems(): if structure.isSubgraphIsomorphic(struct): return None # Otherwise make a new species if label == '': # label = structure.getFormula() # for atom in structure.atoms(): # if atom.hasFreeElectron(): label += 'J' label = structure.toSMILES() # Note in the log spec = Species(speciesCounter+1, label, structure, reactive) logging.verbose('Creating new species %s' % str(spec)) return processNewSpecies(spec)
def makeNewSpecies(structure, label='', reactive=True): """ Attempt to make a new species based on a chemical `structure`, which is a :class:`Structure` object. The proposed species is checked against the list of existing species; if the species already exists, this function returns the existing species. If the species does not exist, a :class:`Species` object is created and returned after being appended to the global species list. """ global speciesCounter # # Recalculate atom types for proposed structure (hopefully not necessary) # structure.simplifyAtomTypes() # structure.updateAtomTypes() # First check cache and return if species is found for i, spec in enumerate(speciesCache): if spec.isIsomorphic(structure): speciesCache.pop(i) speciesCache.insert(0, spec) return spec # Return an existing species if a match is found for spec in speciesList: if spec.isIsomorphic(structure): speciesCache.insert(0, spec) if len(speciesCache) > speciesCacheMaxSize: speciesCache.pop() return spec # Return None if the species has a forbidden structure if thermo.forbiddenStructures is not None: for lbl, struct in thermo.forbiddenStructures.iteritems(): if structure.isSubgraphIsomorphic(struct): return None # Otherwise make a new species if label == '': # label = structure.getFormula() # for atom in structure.atoms(): # if atom.hasFreeElectron(): label += 'J' label = structure.toSMILES() speciesCounter += 1 spec = Species(speciesCounter, label, structure, reactive) speciesList.insert(0, spec) spec.getResonanceIsomers() if thermoDatabase is not None: spec.getThermoData() # Draw species if settings.drawMolecules: mol = pybel.Molecule(spec.toOBMol()) mol.draw(False, os.path.join(settings.outputDirectory, 'species/' + str(spec) + '.png')) # Note in the log logging.debug('Created new species ' + str(spec) )# + ': ' + spec.toInChI()) # Return the newly created species speciesCache.insert(0, spec) if len(speciesCache) > speciesCacheMaxSize: speciesCache.pop() return spec