Example #1
0
	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)
Example #2
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)
Example #3
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()
	
	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