[Bio] / Detour / RecoReader.py Repository:
ViewVC logotype

View of /Detour/RecoReader.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (download) (as text) (annotate)
Thu Sep 9 20:02:51 2004 UTC (15 years, 3 months ago) by sheradon
Branch point for: init, MAIN
Initial revision


import string
from pydot import *
# Compbio tools we'll need:
try:
	from KahOM.RecoElem import *
	from FaST.BssFactory import *
except:
	#print 'Could not import KahOM modules.'
	pass

class unique:
	uniqueN = 100
	def get(self):
		self.uniqueN = self.uniqueN + 1
		return self.uniqueN
uN = unique()		
recycling = {}

# -----------------
def makeDot(re):
# -----------------
	"""Generates a pydot Dot graph structure from a recoElem.
		@type re: RecoElem
		@rtype: Dot
	"""
	global recycling
	recycling = {}
	degree = {}
	s = Dot(graph_name = 'graph%d' % uN.get(), type = 'digraph', rankdir = 'LR', \
				label = re.Name, overlap = 'scale', fontsize = '12', nslimit = '2.0', mclimit = '2.0')
	
	rxns = []
	try:
		re.gatherReactions(rxns)		# make list of reactions
	except:
		print 'makeDot failed: Could not gatherReactions from recoElem.'
		return None
	rxns = uniqueReactions(rxns)	# remove duplicates

	# Make nodes & edges for each reaction here...
	for rxn in rxns:
		
		if rxn.Direction == '1' or rxn.Direction == 'forward': direction = 'forward'
		elif rxn.Direction == 'both': direction = 'both'

		# Inputs
		into = Node('invis%d' % uN.get(), style = 'invis', fixedsize = 'true', height = '0', width = '0')
		s.add_node(into)
		for input in rxn.Inputs:
			nn = getNodeByLabel(input.Name)
			# If not created yet or it's a "non-connected" (common things e.g. ATP), make a new node
			if nn == None or not input.isConnected: 
				label = string.replace(input.Name, ' ', r'\n')	#		 break into multiple lines
				nn = Node("node%d" % uN.get(), label = label, shape = 'box')
				if input.isConnected:	recycling[input.Name] = nn		# reuse node
				else:							nn.shape = 'plaintext'			# or mark it as a 'multi'
				s.add_node(nn)
				degree[nn.get_name()] = 1
			# Otherwise we keep the existing and increment its degree count
			else:	 degree[nn.get_name()] += 1
			ne = Edge(nn.get_name(), into.get_name(), dir=direction)
			s.add_edge(ne)
			if input.isConnected: ne.weight = '2'
			else: ne.weight = '1'

		# Outputs
		outof = Node('invis%d' % uN.get(), style = 'invis', fixedsize = 'true', height = '0', width = '0')
		s.add_node(outof)
		for output in rxn.Outputs:
			nn = getNodeByLabel(output.Name)
			# same drill as above... this is when we create a new node:
			if nn == None or not output.isConnected:
				label = string.replace(output.Name, ' ', r'\n')	#		 break into multiple lines
				nn = Node('node%d' % uN.get(), label = label, shape = 'box')
				if output.isConnected:	recycling[output.Name] = nn	# reuse node
				else:							nn.shape = 'plaintext'			# or mark it as a 'multi'
				s.add_node(nn)
				degree[nn.get_name()] = 1
			# Otherwise keep existing node, increment degree
			else:	degree[nn.get_name()] += 1
			ne = Edge(outof.get_name(), nn.get_name(), dir=direction)
			s.add_edge(ne)
			if output.isConnected: ne.weight = '2'
			else: ne.weight = '1'
			
		# edge connecting inputs to outputs
		s.add_edge(Edge(into.get_name(), outof.get_name(), tooltip = rxn.asString(), label = '?', dir = direction))

	# OK, go through each node and adjust its size based on its degree.
	# That is, ones with tons of in/out activity will be bigger.
	for n in s.get_node_list():
		if n.style == 'invis': continue
		try:
#			n.fontsize = 12 + 4*degree[n.get_name()]
			n.height = str(0.20 + 0.10 * degree[n.get_name()])
			n.width = str(0.7 * string.atof(n.height) * max(map(len, string.split(n.label, r'\n'))))
		except KeyError: pass
	return s


# --------------------------
def getNodeByLabel(label):
# --------------------------
	"""Get a Node with this label, if it's been created. Note that the pydot.Graph built-in
		get_node(str) won't work because it takes a name (eg. node132), not label.
		@type label: string
		@rtype: Node
	"""
	global recycling
	if label in recycling.keys():
		return recycling[label]
	else:
		return None

# --------------------------
def uniqueReactions(rxns):
# --------------------------
	"""Get rid of duplicates. Don't think it's very efficient because of
		the asString generation and rebuilding the list, but it's quick to write. 
		@type: [Reaction]
		@rtype: [Reaction]
	"""

	umap = {}
	urxns = []
	for r in rxns:
		umap[r.asString()] = r
	for key in umap.keys():
		urxns.append(umap[key])
	return urxns



MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3