{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Nibelungenlied and Völsunga saga"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Not only do the medieval Germanic people share a common ancestor concerning their languages, but they also have a common hero celebrated in several stories (poems, sagas).\n",
    "\n",
    "* **Völsunga saga** (*saga* written in Old Norse around the XIII century) \n",
    "* **Nibelungenlied** (poem written in Middle High German around the XII century)\n",
    "* the heroic lays of the **Poetic Edda** (poems written in Old Norse like **Grípisspá**, **Reginsmál**, **Fáfnismál**, **Sigrdrífumál**)\n",
    "\n",
    "Characters in such stories look similar. It would be insteresting to analyse how much they look alike. Are the characters' nouns related? Do the characters have similar relationships with each other. \n",
    "\n",
    "\n",
    "From a statistical point of view, we can set a null hypothesis: \"Characters' relationships with each other look alike in **Völsunga saga** and in **Nibelungenlied**\" and an alternative hypothesis: \"Characters' relationships with each other differ in **Völsunga saga** and in **Nibelungenlied**\"\n",
    "\n",
    "\n",
    "In other words, we will study in what extent **Völsunga saga** and **Nibelungenlied** differ.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Loading texts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.1 Völsunga saga"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.1.1 Reading the text"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import the code to load the text."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import norsecorpus.reader as ncr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "See which texts are available."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['volsunga.xml'])\n"
     ]
    }
   ],
   "source": [
    "available_texts = ncr.get_available_texts()\n",
    "print(available_texts.keys())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load the selected text."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "volsunga_saga = ncr.read_tei_words(available_texts[\"volsunga.xml\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check what was loaded."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Hér', 'hefr', 'upp', 'ok', 'segir', 'frá', 'þeim', 'manni', ',', 'er', 'Sigi', 'er', 'nefndr', 'ok', 'kallaðr', ',', 'at', 'héti', 'sonr', 'Óðins', '.']\n"
     ]
    }
   ],
   "source": [
    "print(volsunga_saga[0][0][0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see that the imported has a structure. \n",
    "\n",
    "Medival copists wrote the text without structure [see the original manuscript](https://handrit.is/en/manuscript/view/AM02-0006). The text structure was made later by philologists.\n",
    "\n",
    "Text => chapters. Chapter => paragraphs. Paragraph => sentences. Sentence => words. Word => character.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Text: `volsunga_saga`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(volsunga_saga)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Chapter: `volsunga_saga[i_chapter]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(volsunga_saga[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Paragraph: `volsunga_saga[i_chapter][j_paragraph]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(volsunga_saga[0][0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sentence: `volsunga_saga[i_chapter][j_paragraph][k_sentence]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(volsunga_saga[0][0][0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Word (or more precisely token): `volsunga_saga[i_chapter][j_paragraph][k_sentence][l_token]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hér\n"
     ]
    }
   ],
   "source": [
    "print(volsunga_saga[0][0][0][0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-----------------------------------\n",
    "This is an ideal case where we have available code to read the structure of a text. Most of the time, it is necessary to:\n",
    "- retrieve the text from a source,\n",
    "- clean the text\n",
    "- give a structure to the text (chapter, paragraph, sentence, word)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.1.2 Remove redundant information\n",
    "\n",
    "Removal of stop words (words which appear in all kinds of texts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from cltk.stop.old_norse.stops import STOPS_LIST"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# {word for word in capital_words if word.lower() not in STOPS_LIST}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['mjök', 'ór', 'áðr', 'saman', 'inn', 'undir', 'heldr', 'brott', 'enn', 'niðr']"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "STOPS_LIST[10:20]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is often needed to remove stop words because they cannot discriminate "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2 Loading Nieblungenlied (Augburg's corpus)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We import the functions to read the Nibelungenlied"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sigurd.nib_augsburg.nib_reader as nibaugr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`nibaugr.MAIN_LINKS` is the list of links to the different manuscription transcription of Nibelungenlied. The link is also the pointer to the stored text."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'https://www.hs-augsburg.de/~harsch/germanica/Chronologie/12Jh/Nibelungen/nib_c_00.html'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nibaugr.MAIN_LINKS[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`nibaugr.read_tei` extracts the content from a TEI-compliant XML file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "nibelungenlied_aug = nibaugr.read_tei(nibaugr.MAIN_LINKS[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(Explain why it is relevant to remove stop words from texts.) \n",
    "\n",
    "Less resourced languages often do not have many annotations and a stop word list is not always available. CLTK provides a class to extract stop words according to some criteria."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "from cltk.stop import stop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "mhg_stop_list = stop.BaseCorpusStoplist()\n",
    "string_nibelungenlied_aug = [\" \".join([\" \".join(long_line) for long_line in chapter]) \n",
    "                                       for chapter in nibelungenlied_aug]\n",
    "# mhg_stop_list.build_stoplist(string_nibelungenlied_aug)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "from cltk.stop.middle_high_german.stops import STOPS_LIST"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['abe',\n",
       " 'aber',\n",
       " 'al',\n",
       " 'alle',\n",
       " 'allen',\n",
       " 'aller',\n",
       " 'alleȥ',\n",
       " 'als',\n",
       " 'alse',\n",
       " 'alsô',\n",
       " 'an',\n",
       " 'ander',\n",
       " 'andern',\n",
       " 'anders',\n",
       " 'ane',\n",
       " 'âne',\n",
       " 'beide',\n",
       " 'besten',\n",
       " 'bin',\n",
       " 'bî']"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "STOPS_LIST[:20]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"von\" in STOPS_LIST"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[['UNS IST> In alten', 'mæren wnders vil geseit'],\n",
       " ['von heleden lobebæren', 'von grozer arebeit'],\n",
       " ['von frevde vn– hochgeciten', 'von weinen vn– klagen'],\n",
       " ['von kvner recken striten', 'mvget ir nv wnder horen sagen'],\n",
       " ['Ez whs <inBvregonden>', 'ein vil edel magedin'],\n",
       " ['daz in allen landen', 'niht schoners mohte sin'],\n",
       " ['Chriemhilt geheizen', 'div wart ein schone wip'],\n",
       " ['dar vmbe mvsin degene', 'vil verliesen den lip'],\n",
       " ['Ir pflagen dri kunige', 'edel un– rich'],\n",
       " ['Gunther un– Gernot', 'die rechen lobelich']]"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nibelungenlied_aug[0][:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[['IST>', 'alten'], ['mæren', 'wnders', 'geseit']],\n",
       " [['heleden', 'lobebæren'], ['grozer', 'arebeit']],\n",
       " [['frevde', 'vn–', 'hochgeciten'], ['weinen', 'vn–', 'klagen']],\n",
       " [['kvner', 'recken', 'striten'], ['mvget', 'nv', 'wnder', 'horen', 'sagen']],\n",
       " [['whs', '<inBvregonden>'], ['edel', 'magedin']],\n",
       " [['landen'], ['schoners', 'mohte', 'sin']],\n",
       " [['Chriemhilt', 'geheizen'], ['div', 'schone', 'wip']],\n",
       " [['vmbe', 'mvsin', 'degene'], ['verliesen', 'lip']],\n",
       " [['pflagen', 'dri', 'kunige'], ['edel', 'un–', 'rich']],\n",
       " [['Gunther', 'un–', 'Gernot'], ['rechen', 'lobelich']]]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[[[word for word in half_line.split(\" \") if word.lower() not in STOPS_LIST] for half_line in long_line] for long_line in nibelungenlied_aug[0][:10]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Analysis of vocabulary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Which words are more likely associated to the main characters?\n",
    "\n",
    "* See POS tagging and lemmatization.\n",
    "* Adjectives are more that are associated to the main character are more likely to describe him."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **method**:\n",
    "\n",
    "- using the POS tagger to detect words which are adjectives,\n",
    "- keep adjectives which are close to a main character,\n",
    "- keep adjectives which are inflected according to the character.\n",
    "\n",
    "The **main issue** is how words are spelled:\n",
    "\n",
    "- the complete text is not normalized, whereas the POS tagger for Middle High German was trained on normalized annotated texts,\n",
    "- the complete text is normalized, whereas the POS tagger for Old Norse was trained on Icelandic spelled texts.\n",
    "\n",
    "This part has not been implemented."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Tracking characters \n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 Sigurðr's relationships\n",
    "\n",
    "I chose to analyse Sigurðr's relationships because this character is present in the Nibelungenlied and in the Völsunga saga and is prominent. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.1.1 Proper nouns extraction\n",
    "\n",
    "The main feature of proper nouns is that... their first character is a capital character. (Just look at the name of your city, your first name and your family name).\n",
    "\n",
    "However, the first word of every sentence has also this feature. The idea is to keep the words with this feature without the ones which are after a punctuation marking a new sentence/sequence. We hope that we don't lose many proper nouns. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "capital_words = set()\n",
    "sentence_delimiters = \"?!.:``''\\\"\"\n",
    "all_words = [word for chapter in volsunga_saga for para in chapter for sentence in para for word in sentence]\n",
    "for i in range(1, len(all_words)):\n",
    "    if all_words[i-1][-1] not in sentence_delimiters and all_words[i] and all_words[i][0].isupper():\n",
    "        capital_words.add(all_words[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# capital_words"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We got proper nouns in the tex with their different attested inflections.\n",
    "\n",
    "Some are humans, some are dwarves, some are gods."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "\n",
    "def common_prefix(s1, s2):\n",
    "    \"\"\"\n",
    "    >>> len_common_prefix(\"bonjour\", \"bonsoir\")\n",
    "    \"bon\"\n",
    "    \"\"\"\n",
    "    len_1 = len(s1)\n",
    "    len_2 = len(s2)\n",
    "    min_1_2 = min(len_1, len_2)\n",
    "    i = 0\n",
    "    while i < min_1_2:\n",
    "        if s1[i] != s2[i]:\n",
    "            break\n",
    "        i += 1\n",
    "    return i, s1[:i]\n",
    "\n",
    "def find_paradigms(words):\n",
    "    common_words = defaultdict(set)\n",
    "    for i, w1 in enumerate(words):\n",
    "        for j in range(i+1, len(words)):\n",
    "            common_words[w1].add(w1)\n",
    "            w2 = words[j]\n",
    "            len_1_2, cw_1_2 = common_prefix(w1, w2)\n",
    "            if len(w1) + 2 < len(w2) or len(w2) + 2 < len(w1):\n",
    "                pass\n",
    "            elif(len(w1) <= len_1_2*1.4 and len(w2) <= len_1_2*1.4): #  (len_1_2 < 2 and len(w1) < 4 and len(w2) < 4) or \n",
    "                common_words[cw_1_2].add(w1)\n",
    "                common_words[cw_1_2].add(w2)\n",
    "    common_words = {common_word: common_words[common_word] for common_word in common_words \n",
    "                    if common_word not in [co for cw in common_words if cw != common_word for co in common_words[cw]]}    \n",
    "    return common_words\n",
    "\n",
    "\n",
    "proper_nouns_paradigms = find_paradigms(list(capital_words))\n",
    "\n",
    "volsunga_characters = {inflected_form: proper_noun_paradigm for proper_noun_paradigm in proper_nouns_paradigms \n",
    "                       for inflected_form in proper_nouns_paradigms[proper_noun_paradigm]}\n",
    "\n",
    "# print(len(proper_nouns_paradigms))\n",
    "# print(proper_nouns_paradigms)\n",
    "# print(volsunga_characters)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.1.2 Ego graph of Sigurðr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# From \"Applied Text Analysis with Python\"\n",
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "import itertools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "def one_of_them_in(l1, l2):\n",
    "    for i in l1:\n",
    "        if i in l2:\n",
    "            return True\n",
    "    return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cooccurrence_vol(text, characters):\n",
    "    possible_pairs = list(itertools.combinations(list(characters.keys()), 2))\n",
    "    cooccurring = dict.fromkeys(possible_pairs, 0)\n",
    "    for chapter in text:\n",
    "        for para in chapter:\n",
    "            for sent in para:\n",
    "                for pair in possible_pairs:\n",
    "                    if one_of_them_in(characters[pair[0]], sent) and one_of_them_in(characters[pair[1]], sent):\n",
    "#                         cooccurring[(characters[pair[0]], characters[pair[1]])] += 1\n",
    "                        cooccurring[pair] += 1\n",
    "    return cooccurring"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cooccurrence_nib_aug(text, characters):\n",
    "    possible_pairs = list(itertools.combinations(list(characters.keys()), 2))\n",
    "    cooccurring = dict.fromkeys(possible_pairs, 0)\n",
    "    for chapter in text:\n",
    "#         for long_line in chapter:\n",
    "            for pair in possible_pairs:\n",
    "                if one_of_them_in(characters[pair[0]], \" \".join([\" \".join(long_line) for long_line in chapter])) and one_of_them_in(characters[pair[1]], \" \".join([\" \".join(long_line) for long_line in chapter])):\n",
    "#                         cooccurring[(characters[pair[0]], characters[pair[1]])] += 1\n",
    "                    cooccurring[pair] += 1\n",
    "    return cooccurring"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Variants of Völsung."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Völsung', 'Völsunga', 'Völsungar', 'Völsungi', 'Völsungr', 'Völsungs'}"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proper_nouns_paradigms['Völsung']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 'Völsungr': nominative singular\n",
    "- 'Völsung': accusative singular\n",
    "- 'Völsungi': dative singular\n",
    "- 'Völsungs': genitive singular\n",
    "- 'Völsungar': nominative and accusative plural\n",
    "- 'Völsunga': genitive plural"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\clems\\pycharmprojects\\comparison_sigurdr_siegfried\\venv\\lib\\site-packages\\networkx\\drawing\\nx_pylab.py:579: MatplotlibDeprecationWarning: \n",
      "The iterable function was deprecated in Matplotlib 3.1 and will be removed in 3.3. Use np.iterable instead.\n",
      "  if not cb.iterable(width):\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 48156 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "g_vol = nx.Graph()\n",
    "g_vol.name = \"Relationships of Sigurðr\"\n",
    "pairs = cooccurrence_vol(volsunga_saga, proper_nouns_paradigms)\n",
    "for pair, weight in pairs.items():\n",
    "    if weight > 1:\n",
    "        g_vol.add_edge(pair[0], pair[1], weight=weight)\n",
    "sigurdr = nx.ego_graph(g_vol, \"Sigurð\")\n",
    "edges, weights = zip(*nx.get_edge_attributes(sigurdr, \"weight\").items())\n",
    "\n",
    "pos = nx.spring_layout(sigurdr, k=0.5, iterations=40)\n",
    "nx.draw(sigurdr, pos, node_color=\"gold\", node_size=50, edgelist=edges, width=0.5, \n",
    "        edge_color=\"orange\", with_labels=True, font_size=12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Sigurðr is at the center of the graph. \n",
    "- We can see a close relationship between Sigurðr and Brynhildr, one of his lovers, and a more distant relationship with Gudrun.\n",
    "- Ennemies of Sigurðr are Fafni (the dragon), Regin (Fafni's brother).\n",
    "- Sigurðr's ancestors: Sigmund, Völsung\n",
    "- A sword named Gram was used to kill Regin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.1.3 Ego graph of Guðrún"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 34532 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "g_vol = nx.Graph()\n",
    "g_vol.name = \"Relationships of Guðrún\"\n",
    "pairs = cooccurrence_vol(volsunga_saga, proper_nouns_paradigms)\n",
    "for pair, weight in pairs.items():\n",
    "    if weight > 1:\n",
    "        g_vol.add_edge(pair[0], pair[1], weight=weight)\n",
    "gudrun = nx.ego_graph(g_vol, \"Guðrún\")\n",
    "edges, weights = zip(*nx.get_edge_attributes(gudrun, \"weight\").items())\n",
    "\n",
    "pos = nx.spring_layout(gudrun, k=0.5, iterations=40)\n",
    "nx.draw(gudrun, pos, node_color=\"gold\", node_size=50, edgelist=edges, width=0.5, \n",
    "        edge_color=\"orange\", with_labels=True, font_size=12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 Sigfried's relationships"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.2.1 Proper nouns extraction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For this text, I extracted manually the places and the characters' names."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "nib_names = nibaugr.read_names()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Variants of Brünhild in the manuscript C."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"Prvnh'\",\n",
       " 'Prvenhilde',\n",
       " 'Privnhilde',\n",
       " 'Prvnhilt',\n",
       " 'Prvonhilde',\n",
       " 'Prvnhilde',\n",
       " 'Prunhilt',\n",
       " 'Prunhilde']"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nib_names['Brünhild']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.2.2 Ego graph of Siegfried"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 88228 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "g_nib_aug = nx.Graph()\n",
    "g_nib_aug.name = \"Relationships of Siegfried\"\n",
    "pairs = cooccurrence_nib_aug(nibelungenlied_aug, nib_names)\n",
    "for pair, weight in pairs.items():\n",
    "    if weight > 2:\n",
    "        g_nib_aug.add_edge(pair[0], pair[1], weight=weight)\n",
    "        \n",
    "siegfried = nx.ego_graph(g_nib_aug, \"Siegfried\")\n",
    "edges, weights = zip(*nx.get_edge_attributes(siegfried, \"weight\").items())\n",
    "\n",
    "pos = nx.spring_layout(siegfried, k=0.5, iterations=40)\n",
    "nx.draw(siegfried, pos, node_color=\"gold\", node_size=50, edgelist=edges, width=0.5, \n",
    "        edge_color=\"orange\", with_labels=True, font_size=12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is less visible here. It seems that there are more characters."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It has to be noted that Kriemhild and Gudrun are actually the same characters. Their names do not help recognize this fact, but they are both married with Siegfried/Sigurdr and "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.2.2 Ego graph of Kriemhild"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 73668 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "g_nib_aug = nx.Graph()\n",
    "g_nib_aug.name = \"Relationships of Kriemhild\"\n",
    "pairs = cooccurrence_nib_aug(nibelungenlied_aug, nib_names)\n",
    "for pair, weight in pairs.items():\n",
    "    if weight > 3:\n",
    "        g_nib_aug.add_edge(pair[0], pair[1], weight=weight)\n",
    "        \n",
    "kriemhild = nx.ego_graph(g_nib_aug, \"Kriemhild\")\n",
    "edges, weights = zip(*nx.get_edge_attributes(kriemhild, \"weight\").items())\n",
    "\n",
    "pos = nx.spring_layout(kriemhild, k=0.5, iterations=40)\n",
    "nx.draw(kriemhild, pos, node_color=\"gold\", node_size=50, edgelist=edges, width=0.5, \n",
    "        edge_color=\"orange\", with_labels=True, font_size=12)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We could see similarities and differencies between two medival works written in two different but related languages.\n",
    "If we know enough how our data are built, then it is possible to automate processes and analyze the outputs. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-----------------------------\n",
    "By Clément Besnier, CLTK contributor ([www.clementbesnier.fr](https://www.clementbesnier.fr/), [github](https://github.com/clemsciences), [twitter](https://twitter.com/clemsciences))."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
