#this script will calculate the pagerank for a directed network
import java
import javax.swing
import com
import math

class pageranktool(com.hp.hpl.guess.ui.DockableAdapter):

	testSlider = JSlider()
	label = JLabel("Teleportation probability (0.05)   ")
	label2 = JLabel("no iterations made")
	testButton = javax.swing.JButton("iterate")
	testCheckBox = javax.swing.JCheckBox("allow sinks");

	iteration = 0
	tele = 0.05
	nosink = 1
	sum = 0
	nodescale = 0

	def __init__(self):

		_isdirected = false
		for ed in g.edges:
			if (ed.directed !=0):
				_isdirected = true

		if (_isdirected == false):
			print "WARNING: this tool only works for directed graphs"

		g.nodes.outdegree
		overrideArrowWidth(3)
		# set up the slider limits
		self.testSlider.setMinimum(0)
		self.testSlider.setMaximum(100)
		self.myscale = (g.nodes.__len__())**0.8
		g.nodes.width=self.myscale
		g.nodes.height = self.myscale

		try:
			g.edges.nweight = 1
		except (Error),e:
			addEdgeField("nweight",Types.DOUBLE,1.0)

		try:
			g.edges.weight
		except (Error),e:
			addEdgeField("weight",Types.DOUBLE,1.0)

		try:
			g.nodes.sumweight = 0
		except (Error),e:
			addNodeField("sumweight",Types.DOUBLE,1.0)

		for _n in g.nodes:
			_edgeweightsum = 0
			for _e in _n.getOutEdges():
				if (_e.node1 == _n):
					if (_e.node1 != _e.node2):
						_edgeweightsum = _edgeweightsum+_e.weight
			_tmp = 0
			for _e in _n.getOutEdges():
				if (_e.node1 == _n):
					if (_e.node2 == _n):
						_e.nweight = 0
					else:
						_e.nweight = _e.weight/_edgeweightsum
					_tmp += _e.nweight
#			print _tmp

		resizeLinear(nweight,0.1,1)
		try:
			g.nodes.pagerankscore=20
		except (Error),e:
			addNodeField("pagerankscore",Types.DOUBLE,20.0)

		try:
			g.nodes.newpagerankscore=20
		except (Error),e:
			addNodeField("newpagerankscore",Types.DOUBLE,20.0)

		# set up the slider visual properties
		self.testSlider.setMajorTickSpacing(50)
		self.testSlider.setMinorTickSpacing(10)
		self.testSlider.setPaintTicks(true)
		self.testSlider.setPaintLabels(true)	
		self.testSlider.setValue(5)  # default value

		self.testCheckBox.mouseReleased = self.sc
		self.add(self.testCheckBox)

		# every time the mouse is released call the "sc" event	
		self.testSlider.mouseReleased = self.sc

		self.testButton.actionPerformed = self.buttonPressed

		# add the label and slider to the UI
		self.add(self.label)
		self.add(self.label2)
		self.add(self.testSlider)
		self.add(self.testButton)

#		overrideArrowLength(10)
		overrideArrowWidth(3)
		g.nodes.color=red
		g.edges.color=yellow
		#addNodeField("newpagerankscore",Types.DOUBLE,0)

		# dock the new panel into the UI
		ui.dock(self)

		# call the event function once so that the
		# display matches the slider value
		self.sc(None)

	def buttonPressed(self,event):
	  	# check if user wants the whole graph clustered, or to find the community around a node
			self.iter()

	def getTitle(self):
		return("pageranktool")

	def sc(self,evt):
		# get the value
		self.tele = self.testSlider.getValue()/100.0

		g.nodes.pagerankscore = 1/(g.nodes.__len__()+0.0)
	
		# hide nodes not connected to visible edges
#		self.calcPageRank()

		# set the label text
		self.label.setText("Teleportation probability ("+str(self.tele)+")")
		self.label2.setText("no iterations performed")

		for nod in g.nodes:
			nod.width=(math.log(nod.pagerankscore*g.nodes.__len__()+2))*self.myscale
			nod.height=(math.log(nod.pagerankscore*g.nodes.__len__()+2))*self.myscale

		self.iteration = 0

		if (self.testCheckBox.isSelected() == true):
			self.nosink = 0
		else:
			self.nosink = 1 

	def iter(self):

#		print "iteration ",self.iteration
		for nod in g.nodes:
			nod.newpagerankscore = self.tele/g.nodes.__len__()
			
		for nod in g.nodes:
			nod.pagerankscore = nod.pagerankscore*(1-self.tele);
			nod.sumweight = 0

		tmp2 = 0
		for n1 in g.nodes:  # for all nodes
			for ed in n1.getOutEdges():
				if (ed.node1 == n1):
#					if (ed.node1 == ed.node2):
#						print "self ",ed.node1
					ed.node2.newpagerankscore += (ed.node1.pagerankscore)*ed.nweight
					tmp = (ed.node1.pagerankscore)*ed.nweight
					tmp2 += tmp
#					print "transferring ",tmp," from ",ed.node1," to ",ed.node2
					ed.node1.sumweight += ed.nweight

#		for nod in g.nodes:
#			print nod," ",nod.sumweight

#		print "transferred ",tmp2

		if (self.nosink == 1):
			for nod in g.nodes:
				if (nod.sumweight == 0):
#					print nod," is a sink"
					for nod2 in g.nodes:
						nod2.newpagerankscore += (nod.pagerankscore)/g.nodes.__len__()
		else:
			for nod in g.nodes:
				if (nod.outdegree == 0):
					nod.newpagerankscore += nod.pagerankscore

		self.sum = 0	
		for nod in g.nodes:
			nod.pagerankscore = nod.newpagerankscore
			self.sum = self.sum+nod.pagerankscore

		#print "sum = ",self.sum
		
		self.iteration = self.iteration+1
		self.label2.setText("iteration ("+str(self.iteration)+")")

		g.nodes.style=1
		g.nodes.style=2
		for nod in g.nodes:
			nod.width=(math.log(nod.pagerankscore*g.nodes.__len__()+2))*self.myscale
			nod.height=(math.log(nod.pagerankscore*g.nodes.__len__()+2))*self.myscale


pageranktool()
