In the Star Wars legendarium, knowledge and training in the Force passes down through master/apprentice relationships. So, plotting the relationship network between them could help to understand how Star Wars characters are connected and how they became the Jedi or Sith that they are.
All the info is gathered from Wookiepedia (http://starwars.wikia.com). Wookieepedia is a Star Wars encyclopedia written collaboratively by its readers. Wookieepedia strives to be the Internet's foremost comprehensive resource for Star Wars canon information. To this end, Wookieepedia adheres to the canon doctrines set forth by Lucasfilm Ltd. and its subsidiaries.
The plot will be created with the Python package PyGraphviz (http://pygraphviz.github.io/). This is a Python interface to the Graphviz graph layout and visualization package. With PyGraphviz you can create, edit, read, write, and draw graphs using Python to access the Graphviz graph data structure and layout algorithms.
The starting point will be the jedi master Yoda. Every canon character found in the relationship network will be plotted.
The objective is drawing the master/apprentice relationship network between the Star Wars characters with the PyGraphviz package of Python.
Character info has been formatted into a plain txt database.
In [1]:
fpath = "./database/swr_char_info-canon.txt"
fhand = open(fpath, 'rb')
for i in fhand:
print i.strip()
fhand.close()
Character info and training info are obtained separately.
chars_info: contains the master/apprentices names and the force alignment (bright or dark side) of the character. Eg.:
{
"Luke Skywalker": {
"apprentices": [
"."
],
"bright_side_force": "1",
"dark_side_force": "0",
"masters": [
"Obi-Wan Kenobi",
"Yoda"
]
},
"Darth Sidious": {
"apprentices": [
"Darth Maul",
"Darth Tyranus",
"Darth Vader"
],
"bright_side_force": "0",
"dark_side_force": "1",
"masters": [
"Darth Plagueis"
]
}
}
training_info: contains the force alignment of the given training between characters
[
['Yoda', 'Luke Skywalker', '1'],
['Qui-Gon Jinn', 'Darth Vader', '1'],
['Darth Sidious', 'Darth Vader', '0']
]
In [2]:
import re
import json
def parse_network_file(fpath):
'''It parses the file containing the network information'''
fhand = open(fpath,'rb')
chars_info = {}
training_info = []
for line in fhand:
line = line.strip()
if not line.startswith('#'): # Skipping header
char_data = re.sub('_', ' ', line).split('\t')
# Extracting fields
name = char_data[0]
masters = char_data[1].split(';')
apprentices = char_data[2].split(';')
bright_side_force = char_data[3]
dark_side_force = char_data[4]
training_master = char_data[5].split(';')
training_apprentice = char_data[6].split(';')
chars_info[name] = {}
chars_info[name]['masters'] = masters
chars_info[name]['apprentices'] = apprentices
chars_info[name]['bright_side_force'] = bright_side_force
chars_info[name]['dark_side_force'] = dark_side_force
for i, apprentice in enumerate(apprentices):
if not apprentice == '.':
training_relationship = [name, apprentice, training_apprentice[i]]
training_info.append(training_relationship)
fhand.close()
return chars_info, training_info
chars_info, training_info = parse_network_file(fpath)
The Python package "PyGraphviz" can use a dictionary of dictionaries as data structure for plotting the network graph. Eg:
{
'Darth Sidious': {
'Darth Maul': None,
'Darth Tyranus': None,
'Darth Vader': None
},
'Yoda': {
'Darth Tyranus': None,
'Luke Skywalker': None,
'Obi-Wan Kenobi': None
},
}
In [3]:
def create_dictionary_for_plotting(chars_info):
'''It populates dictionary "d" for plotting'''
d = {}
master_list = []
apprentice_list = []
for char in chars_info:
master_list.append(char)
apprentices = chars_info[char]['apprentices']
d[char] = {}
for apprentice in apprentices:
if not apprentice == '.':
apprentice_list.append(apprentice)
d[char][apprentice] = None
# Remove chars with no apprentice (empty element from 'd')
d = dict((k, v) for k, v in d.iteritems() if v)
return d
d = create_dictionary_for_plotting(chars_info)
A directed graphs is created to show the relationship network.
In [4]:
import pygraphviz as pgv
def plotting_graphs(d, training_info):
# Plotting the graphs
G = pgv.AGraph(d,
strict = False,
directed = True,
overlap = False, # Avoid overlapping nodes
splines = True) # Curvy edges
for training in training_info:
edge = G.get_edge(training[0], training[1])
edge.attr['len'] = 1
if int(training[2]):
edge.attr['color'] = 'green'
else:
edge.attr['color'] = 'red'
for char in chars_info:
node = G.get_node(char)
node.attr['style'] = 'filled'
bsf = int(chars_info[char]['bright_side_force'])
dsf = int(chars_info[char]['dark_side_force'])
if bsf and dsf:
continue
elif bsf:
node.attr['fillcolor'] = 'green'
elif dsf:
node.attr['fillcolor'] = 'red'
G.layout(prog = 'fdp')
G.draw('./images/file1.png')
# Plotting
plotting_graphs(d, training_info)
# Showing the image in the ipython notebook
from IPython.display import Image, display
i = Image(filename='./images/file1.png')
display(i)