User Tools

Site Tools


rlyazidi:solution_homework2

Table of Contents

Critères & points attribués (/10)
Rappel du contexte 7
Résultats 10
Qualité du code (commentaires, structures utilisées, …) 8
Animation du dessin 10
Explication en dehors du code 7
Total (/50) 43

B.P. : On obtient bien le résultat attendu et l'animation fonctionne bien. Vos explications en dehors du code sont un peu légères.

Icicleplot

icicle_plot_Reda_Lyazidi_withrecursion.py
# Powered by Python 2.7
 
# To cancel the modifications performed by the script
# on the current graph, click on the undo button.
 
# Some useful keyboards shortcuts : 
#   * Ctrl + D : comment selected lines.
#   * Ctrl + Shift + D  : uncomment selected lines.
#   * Ctrl + I : indent selected lines.
#   * Ctrl + Shift + I  : unindent selected lines.
#   * Ctrl + Return  : run script.
#   * Ctrl + F  : find selected text.
#   * Ctrl + R  : replace selected text.
#   * Ctrl + Space  : show auto-completion dialog.
 
from tulip import *
 
# the updateVisualization(centerViews = True) function can be called
# during script execution to update the opened views
 
# the pauseScript() function can be called to pause the script execution.
# To resume the script execution, you will have to click on the "Run script " button.
 
# the runGraphScript(scriptFile, graph) function can be called to launch another edited script on a tlp.Graph object.
# The scriptFile parameter defines the script name to call (in the form [a-zA-Z0-9_]+.py)
 
# the main(graph) function must be defined 
# to run the script on the current graph
 
rootX = 500
rootY = 100
rootZ = 0
counternode = 0
 
def main(graph): 
	Random_layout__viewLayout =  graph.getLayoutProperty("Random layout - (viewLayout)")
	viewBorderColor =  graph.getColorProperty("viewBorderColor")
	viewBorderWidth =  graph.getDoubleProperty("viewBorderWidth")
	viewColor =  graph.getColorProperty("viewColor")
	viewFont =  graph.getStringProperty("viewFont")
	viewFontSize =  graph.getIntegerProperty("viewFontSize")
	viewLabel =  graph.getStringProperty("viewLabel")
	viewLabelColor =  graph.getColorProperty("viewLabelColor")
	viewLabelPosition =  graph.getIntegerProperty("viewLabelPosition")
	viewLayout =  graph.getLayoutProperty("viewLayout")
	viewMetaGraph =  graph.getGraphProperty("viewMetaGraph")
	viewMetric =  graph.getDoubleProperty("viewMetric")
	viewRotation =  graph.getDoubleProperty("viewRotation")
	viewSelection =  graph.getBooleanProperty("viewSelection")
	viewShape =  graph.getIntegerProperty("viewShape")
	viewSize =  graph.getSizeProperty("viewSize")
	viewSrcAnchorShape =  graph.getIntegerProperty("viewSrcAnchorShape")
	viewSrcAnchorSize =  graph.getSizeProperty("viewSrcAnchorSize")
	viewTexture =  graph.getStringProperty("viewTexture")
	viewTgtAnchorShape =  graph.getIntegerProperty("viewTgtAnchorShape")
	viewTgtAnchorSize =  graph.getSizeProperty("viewTgtAnchorSize")
 
 
 
 
 
	def icicle_plot(graph,colorstep=10, gapSpace = 1):
		root = tlp.Graph.getSource(graph)
		rootSize = tlp.Size(rootX,rootY,rootZ)
 
		viewSize.setNodeValue(root,rootSize)		
 
 
		viewShape.setAllNodeStringValue("4")
 
		viewColor[root] = tlp.Color(0,0,0)
 
 
		viewLabel.setNodeValue(root,"root")
		viewLabelColor.setNodeValue(root,tlp.Color(255,255,255))
		i=0
		parent_position_x = viewLayout.getNodeValue(root).getX()
		icicle_plot_rec(root,colorstep,gapSpace)
 
		updateVisualization()
 
	def addColorstep(color,colorstep):
		return
	def icicle_plot_rec(node,colorstep=10,gapSpace=1):
		if  graph.outdeg(node) == 0: #si c'est une feuille
			return
		parent_position_x = viewLayout.getNodeValue(node).getX()
		i = 0
 
		for v in graph.getOutNodes(node):
			global counternode
			viewLabel.setNodeValue(v,"node"+str(counternode))
			viewLabelColor.setNodeValue(v,tlp.Color(255,255,255))
			viewColor[v] = tlp.Color(colorstep,colorstep,colorstep)
			childrenSize = tlp.Size(viewSize.getNodeValue(node).getW()/(graph.outdeg(node)*1.0), viewSize.getNodeValue(node).getH(), viewSize.getNodeValue(node).getD())
			viewSize.setNodeValue(v,childrenSize)
			newy = viewLayout.getNodeValue(node).getY() - viewSize.getNodeValue(node).getH() - gapSpace		
 
			#changer la position X des fils pour qu'ils soient alignes juste en dessous du pere
			#on a la position du bord du carre du noeud pere
			parentleftsideX = viewLayout.getNodeValue(node).getX() - (viewSize.getNodeValue(node).getW()/2.0)
			#chaque fils aura pour position par rapport au bord gauche de son pere
			#i un entier commencant a zero : positionfils = longueurPere/nbfils/2 + i*2/nbfils
			nbchildren = (graph.outdeg(node)*1.0)
			newx = parentleftsideX + (viewSize.getNodeValue(node).getW()/nbchildren/2.0) + i*viewSize.getNodeValue(node).getW() / nbchildren
			xcurrent = viewLayout.getNodeValue(v)
			xcurrent.setX(newx)
			xcurrent.setY(newy)
			viewLayout.setNodeValue(v,xcurrent)
 
			i+=1
			counternode +=1
			icicle_plot_rec(v,(colorstep + colorstep)% 255 ,gapSpace)
	icicle_plot(graph)
Présentation

Dans le cadre de cet exercice je devais modifier l'agencement et la visualisation d'un arbre en icicleplot.
Ceci consistait à regrouper les noeuds de mêmes groupes.
Ainsi la racine a une forme carrée et une taille arbitraire
et ses fils ont la même forme et la taille de tous les fils est égale
à celui de leur parent, ce principe est récursif, d'où le cheminement de mon implémentation.

Implémentation

En premier lieu, le programme ne concernait que la racine et ses fils,
puis lorsque le test fut concluant j'ai appliqué mon programme en récursif,
le label des noeuds montrent l'ordre du parcours, il s'agit d'un parcours en profondeur.
Pour les couleurs il s'agit simplement de nuances de gris, ainsi pour chaque nuance
correspond un étage soit un cluster.
La taille (seulement la longueur) du carré d'un noeud correspond à celle de son père divisé par le nombre de fils.
Cependant il fallait aussi déplacer les fils afin d'aligner les clusters.
Au niveau de l'ordonnée Y, la position du fils est :

posY = PereY - Largeur + ecartement

Ceci afin que les carrés ne se chevauchent pas,
pour l'alignement au niveau de l'abscisse X:
on prend la position du père moins la moitié de la longueur : posXdebut = pereX - longueur/2

posX = posXdebut + longueur/nbfils/2 + indiceFils * longueur/nbfils

indiceFils représente la position du fils (commence à 0).
Ensuite, pour l'ajout d'animation, le principe est au lieu d'effectuer
les changements (notamment les translations) d'un seul coup,
le but est de réaliser leur équivalent par pas de 1*vitesse par exemple,
avec un timer pour bloquer le script et la méthode updateVisualization()
pour que chaque changement soit visible à l'oeil.
Cette méthode a quelques inconvénients, en premier lieu dans les cas d'arbre
très grand avec une grande profondeur, à chaque étage cela mettra de plus en plus de temps
pour que les sommets se rapprochent de leurs parents.
Sinon j'ai essayé d'utiliser un pas proportionnel à la distance.
pas = vecteur/norme, vecteur répresente la translation que le sommet doit effectuer.
Cependant suite à un grand nombre d'erreur (division par zéro), ceci n'a pas marché,
donc mon script n'offre aucune animation.
Suite à ces problèmes je n'ai pas eu le temps de tester mon algorithme principal sur d'autres arbres
que celui créer par l'algorithme "Complete Tree" par défaut (celui avec une profondeur de 5).
La création du graphe et l'application de l'algorithme Walker se réalise via l'interface tulip.

/net/html/perso/melancon/Visual_Analytics_Course/data/pages/rlyazidi/solution_homework2.txt · Last modified: 2012/10/22 17:18 by bpinaud